/[svn]/gigedit/trunk/src/gigedit/dimensionmanager.cpp
ViewVC logotype

Contents of /gigedit/trunk/src/gigedit/dimensionmanager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2976 - (show annotations) (download)
Thu Jul 28 06:47:25 2016 UTC (7 years, 8 months ago) by schoenebeck
File size: 29714 byte(s)
* Fixed crash when opening dimension manager dialolg multiple times
  (and i.e. adding or removing dimensions each time).
* Bumped version (1.0.0.svn21).

1 /*
2 * Copyright (C) 2006-2014 Andreas Persson
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with program; see the file COPYING. If not, write to the Free
16 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17 * 02110-1301 USA.
18 */
19
20 #include <glibmmconfig.h>
21 // threads.h must be included first to be able to build with
22 // G_DISABLE_DEPRECATED
23 #if (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION == 31 && GLIBMM_MICRO_VERSION >= 2) || \
24 (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION > 31) || GLIBMM_MAJOR_VERSION > 2
25 #include <glibmm/threads.h>
26 #endif
27
28 #include "dimensionmanager.h"
29
30 #include <gtkmm/messagedialog.h>
31 #include <gtkmm/dialog.h>
32 #include <gtkmm/comboboxtext.h>
33 #include <gtkmm/spinbutton.h>
34 #include <gtkmm/table.h>
35
36 #include "global.h"
37 #include "compat.h"
38
39 // returns a human readable name of the given dimension type
40 Glib::ustring dimTypeAsString(gig::dimension_t d) {
41 char buf[32];
42 switch (d) {
43 case gig::dimension_none:
44 return _("None");
45 case gig::dimension_samplechannel:
46 return _("Sample Channel");
47 case gig::dimension_layer:
48 return _("Layer");
49 case gig::dimension_velocity:
50 return _("Velocity");
51 case gig::dimension_channelaftertouch:
52 return _("Aftertouch");
53 case gig::dimension_releasetrigger:
54 return _("Release Trigger");
55 case gig::dimension_keyboard:
56 return _("Keyswitching");
57 case gig::dimension_roundrobin:
58 return _("Round Robin");
59 case gig::dimension_random:
60 return _("Random Generator");
61 case gig::dimension_smartmidi:
62 return _("Smart MIDI");
63 case gig::dimension_roundrobinkeyboard:
64 return _("Keyboard Round Robin");
65 case gig::dimension_modwheel:
66 return _("Modulation Wheel");
67 case gig::dimension_breath:
68 return _("Breath Ctrl.");
69 case gig::dimension_foot:
70 return _("Foot Ctrl.");
71 case gig::dimension_portamentotime:
72 return _("Portamento Time Ctrl.");
73 case gig::dimension_effect1:
74 return _("Effect Ctrl. 1");
75 case gig::dimension_effect2:
76 return _("Effect Ctrl. 2");
77 case gig::dimension_genpurpose1:
78 return _("General Purpose Ctrl. 1");
79 case gig::dimension_genpurpose2:
80 return _("General Purpose Ctrl. 2");
81 case gig::dimension_genpurpose3:
82 return _("General Purpose Ctrl. 3");
83 case gig::dimension_genpurpose4:
84 return _("General Purpose Ctrl. 4");
85 case gig::dimension_sustainpedal:
86 return _("Sustain Pedal");
87 case gig::dimension_portamento:
88 return _("Portamento Ctrl.");
89 case gig::dimension_sostenutopedal:
90 return _("Sostenuto Pedal");
91 case gig::dimension_softpedal:
92 return _("Soft Pedal");
93 case gig::dimension_genpurpose5:
94 return _("General Purpose Ctrl. 5");
95 case gig::dimension_genpurpose6:
96 return _("General Purpose Ctrl. 6");
97 case gig::dimension_genpurpose7:
98 return _("General Purpose Ctrl. 7");
99 case gig::dimension_genpurpose8:
100 return _("General Purpose Ctrl. 8");
101 case gig::dimension_effect1depth:
102 return _("Effect 1 Depth");
103 case gig::dimension_effect2depth:
104 return _("Effect 2 Depth");
105 case gig::dimension_effect3depth:
106 return _("Effect 3 Depth");
107 case gig::dimension_effect4depth:
108 return _("Effect 4 Depth");
109 case gig::dimension_effect5depth:
110 return _("Effect 5 Depth");
111 default:
112 sprintf(buf, "Unknown Type (0x%x) !!!", d);
113 return buf;
114 }
115 }
116
117 // returns a human readable description of the given dimension
118 static Glib::ustring __dimDescriptionAsString(gig::dimension_t d) {
119 switch (d) {
120 case gig::dimension_none:
121 return _("Dimension not in use");
122 case gig::dimension_samplechannel:
123 return _("If used sample has more than one channel (thus is not mono)");
124 case gig::dimension_layer:
125 return _("For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers");
126 case gig::dimension_velocity:
127 return _("Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined)");
128 case gig::dimension_channelaftertouch:
129 return _("Channel Key Pressure");
130 case gig::dimension_releasetrigger:
131 return _("Special dimension for triggering samples on releasing a key");
132 case gig::dimension_keyboard:
133 return _("Dimension for keyswitching (keyboard)");
134 case gig::dimension_roundrobin:
135 return _("Different samples triggered each time a note is played, dimension regions selected in sequence");
136 case gig::dimension_random:
137 return _("Different samples triggered each time a note is played, random order");
138 case gig::dimension_smartmidi:
139 return _("For MIDI tools like legato and repetition mode");
140 case gig::dimension_roundrobinkeyboard:
141 return _("Different samples triggered each time a note is played, any key advances the counter");
142 case gig::dimension_modwheel:
143 return _("MIDI Controller 1");
144 case gig::dimension_breath:
145 return _("MIDI Controller 2");
146 case gig::dimension_foot:
147 return _("MIDI Controller 4");
148 case gig::dimension_portamentotime:
149 return _("MIDI Controller 5");
150 case gig::dimension_effect1:
151 return _("MIDI Controller 12");
152 case gig::dimension_effect2:
153 return _("MIDI Controller 13");
154 case gig::dimension_genpurpose1:
155 return _("Slider, MIDI Controller 16");
156 case gig::dimension_genpurpose2:
157 return _("Slider, MIDI Controller 17");
158 case gig::dimension_genpurpose3:
159 return _("Slider, MIDI Controller 18");
160 case gig::dimension_genpurpose4:
161 return _("Slider, MIDI Controller 19");
162 case gig::dimension_sustainpedal:
163 return _("MIDI Controller 64");
164 case gig::dimension_portamento:
165 return _("MIDI Controller 65");
166 case gig::dimension_sostenutopedal:
167 return _("MIDI Controller 66");
168 case gig::dimension_softpedal:
169 return _("MIDI Controller 67");
170 case gig::dimension_genpurpose5:
171 return _("Button, MIDI Controller 80");
172 case gig::dimension_genpurpose6:
173 return _("Button, MIDI Controller 81");
174 case gig::dimension_genpurpose7:
175 return _("Button, MIDI Controller 82");
176 case gig::dimension_genpurpose8:
177 return _("Button, MIDI Controller 83");
178 case gig::dimension_effect1depth:
179 return _("MIDI Controller 91");
180 case gig::dimension_effect2depth:
181 return _("MIDI Controller 92");
182 case gig::dimension_effect3depth:
183 return _("MIDI Controller 93");
184 case gig::dimension_effect4depth:
185 return _("MIDI Controller 94");
186 case gig::dimension_effect5depth:
187 return _("MIDI Controller 95");
188 default:
189 return _("Please report this !!!");
190 }
191 }
192
193 DimTypeCellRenderer::DimTypeCellRenderer() :
194 Glib::ObjectBase(typeid(DimTypeCellRenderer)),
195 Gtk::CellRendererText(),
196 m_propertyDimType(*this, "gigdimension_t", gig::dimension_none),
197 m_propertyUsageCount(*this, "intusagecount", 0),
198 m_propertyTotalRegions(*this, "inttotalregions", 0)
199 {
200 propertyDimType().signal_changed().connect(
201 sigc::mem_fun(*this, &DimTypeCellRenderer::typeChanged)
202 );
203 propertyUsageCount().signal_changed().connect(
204 sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
205 );
206 propertyTotalRegions().signal_changed().connect(
207 sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
208 );
209 }
210
211 void DimTypeCellRenderer::typeChanged() {
212 gig::dimension_t type = propertyDimType();
213 Glib::ustring s = dimTypeAsString(type);
214 property_text() = s;
215 }
216
217 void DimTypeCellRenderer::statsChanged() {
218 int usageCount = propertyUsageCount();
219 int totalRegions = propertyTotalRegions();
220 bool bDimensionExistsOnAllRegions = (usageCount == totalRegions);
221 property_foreground() = ((bDimensionExistsOnAllRegions) ? "black" : "gray");
222 }
223
224 IntSetCellRenderer::IntSetCellRenderer() :
225 Glib::ObjectBase(typeid(IntSetCellRenderer)),
226 Gtk::CellRendererText(),
227 m_propertyValue(*this, "stdintset", std::set<int>())
228 {
229 propertyValue().signal_changed().connect(
230 sigc::mem_fun(*this, &IntSetCellRenderer::valueChanged)
231 );
232 }
233
234 void IntSetCellRenderer::valueChanged() {
235 Glib::ustring s;
236 std::set<int> v = propertyValue();
237 for (std::set<int>::const_iterator it = v.begin(); it != v.end(); ++it) {
238 s += ToString(*it);
239 if (*it != *v.rbegin()) s += "|";
240 }
241 property_text() = s;
242 property_foreground() = (v.size() > 1) ? "gray" : "black";
243 }
244
245 DimensionManager::DimensionManager() :
246 addButton(_("_Add"), true),
247 removeButton(_("_Remove"), true),
248 allRegionsCheckBox(_("All Regions"))
249 {
250 ignoreColumnClicked = true;
251
252 set_title(_("Dimensions of selected Region"));
253 add(vbox);
254 scrolledWindow.add(treeView);
255 vbox.pack_start(scrolledWindow);
256 scrolledWindow.show();
257 vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
258 buttonBox.set_layout(Gtk::BUTTONBOX_END);
259 buttonBox.set_border_width(5);
260 buttonBox.show();
261 buttonBox.pack_start(allRegionsCheckBox, Gtk::PACK_EXPAND_PADDING);
262 buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);
263 buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);
264 addButton.show();
265 removeButton.show();
266 allRegionsCheckBox.set_tooltip_text(
267 _("Enable this if you want to edit dimensions of all regions simultaniously.")
268 );
269
270 // setup the table
271 refTableModel = Gtk::ListStore::create(tableModel);
272 treeView.set_model(refTableModel);
273 treeView.append_column(_("Dimension Type"), m_cellRendererDimType);
274 treeView.append_column(_("Bits"), m_cellRendererIntSet);
275 treeView.append_column(_("Zones"), m_cellRendererIntSet);
276 treeView.append_column(_("Description"), tableModel.m_description);
277 treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyDimType(), tableModel.m_type);
278 treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyUsageCount(), tableModel.m_usageCount);
279 treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyTotalRegions(), tableModel.m_totalRegions);
280 treeView.get_column(1)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_bits);
281 treeView.get_column(2)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_zones);
282 treeView.show();
283
284 treeView.signal_cursor_changed().connect(
285 sigc::mem_fun(*this, &DimensionManager::onColumnClicked)
286 );
287
288 addButton.signal_clicked().connect(
289 sigc::mem_fun(*this, &DimensionManager::addDimension)
290 );
291
292 removeButton.signal_clicked().connect(
293 sigc::mem_fun(*this, &DimensionManager::removeDimension)
294 );
295 allRegionsCheckBox.signal_toggled().connect(
296 sigc::mem_fun(*this, &DimensionManager::onAllRegionsCheckBoxToggled)
297 );
298
299 show_all_children();
300
301 resize(460,300);
302 }
303
304 bool DimensionManager::allRegions() const {
305 return allRegionsCheckBox.get_active();
306 }
307
308 void DimensionManager::onAllRegionsCheckBoxToggled() {
309 set_title(
310 allRegions() ? _("Dimensions of all Regions") : _("Dimensions of selected Region")
311 );
312 treeView.set_tooltip_text(
313 allRegions()
314 ? _("Dimensions and numbers in gray indicates a difference among the individual regions.")
315 : _("You are currently only viewing dimensions of the currently selected region.")
316 );
317 refreshManager();
318 }
319
320 // following two data types are just used in DimensionManager::refresManager(),
321 // due to the maps template nature however, they must be declared at global
322 // space to avoid compilation errors
323 struct _DimDef {
324 std::set<int> bits;
325 std::set<int> zones;
326 int usageCount;
327 };
328 typedef std::map<gig::dimension_t, _DimDef> _Dimensions;
329
330 // update all GUI elements according to current gig::Region informations
331 void DimensionManager::refreshManager() {
332 set_sensitive(false);
333 refTableModel->clear();
334 if (allRegions()) {
335 if (region) {
336 _Dimensions dims;
337 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
338 int iRegionsCount = 0;
339 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion(), ++iRegionsCount) {
340 for (uint i = 0; i < rgn->Dimensions; i++) {
341 gig::dimension_def_t* dim = &rgn->pDimensionDefinitions[i];
342 dims[dim->dimension].bits.insert(dim->bits);
343 dims[dim->dimension].zones.insert(dim->zones);
344 dims[dim->dimension].usageCount++;
345 }
346 }
347 for (_Dimensions::const_iterator it = dims.begin(); it != dims.end(); ++it) {
348 Gtk::TreeModel::Row row = *(refTableModel->append());
349 row[tableModel.m_type] = it->first;
350 row[tableModel.m_bits] = it->second.bits;
351 row[tableModel.m_zones] = it->second.zones;
352 row[tableModel.m_description] = __dimDescriptionAsString(it->first);
353 row[tableModel.m_usageCount] = it->second.usageCount;
354 row[tableModel.m_totalRegions] = iRegionsCount;
355 }
356 }
357 } else {
358 if (region) {
359 for (uint i = 0; i < region->Dimensions; i++) {
360 gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];
361 Gtk::TreeModel::Row row = *(refTableModel->append());
362 std::set<int> vBits;
363 vBits.insert(dim->bits);
364 row[tableModel.m_bits] = vBits;
365 std::set<int> vZones;
366 vZones.insert(dim->zones);
367 row[tableModel.m_zones] = vZones;
368 row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);
369 row[tableModel.m_type] = dim->dimension;
370 row[tableModel.m_usageCount] = 1;
371 row[tableModel.m_totalRegions] = 1;
372 }
373 }
374 }
375 set_sensitive(region);
376 }
377
378 void DimensionManager::show(gig::Region* region) {
379 ignoreColumnClicked = true;
380 this->region = region;
381 refreshManager();
382 Gtk::Window::show();
383 deiconify();
384 ignoreColumnClicked = false;
385 }
386
387 void DimensionManager::set_region(gig::Region* region) {
388 ignoreColumnClicked = true;
389 this->region = region;
390 refreshManager();
391 ignoreColumnClicked = false;
392 }
393
394 void DimensionManager::onColumnClicked() {
395 printf("DimensionManager::onColumnClicked()\n");
396
397 //FIXME: BUG: this method is currently very unreliably called, it should actually be called when the user selects another column, it is ATM however also called when the table content changed programmatically causing the dialog below to popup at undesired times !
398
399 //HACK: Prevents that onColumnClicked() gets called multiple times or at times where it is not desired
400 if (ignoreColumnClicked) {
401 ignoreColumnClicked = false;
402 return;
403 }
404 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 18) || GTKMM_MAJOR_VERSION > 2
405 // prevents app to crash if this dialog is closed
406 if (!get_visible())
407 return;
408 #else
409 # warning Your GTKMM version is too old; dimension manager dialog might crash when changing a dimension type !
410 #endif
411
412 #if (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 3
413 if (!is_visible()) return;
414 #endif
415
416 Gtk::TreeModel::Path path;
417 Gtk::TreeViewColumn* focus_column;
418 treeView.get_cursor(path, focus_column);
419 //const int row = path[0];
420 if (focus_column == treeView.get_column(0)) {
421 Gtk::TreeModel::iterator it = treeView.get_model()->get_iter(path);
422 if (!it) return;
423 Gtk::TreeModel::Row row = *it;
424 gig::dimension_t oldType = row[tableModel.m_type];
425
426 Gtk::Dialog dialog(_("Change Dimension"), true /*modal*/);
427 int oldTypeIndex = -1;
428 Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
429 for (int i = 0x01, count = 0; i < 0xff; i++) {
430 Glib::ustring sType =
431 dimTypeAsString(static_cast<gig::dimension_t>(i));
432 if (i == oldType) oldTypeIndex = count;
433 if (sType.find("Unknown") != 0) {
434 Gtk::TreeModel::Row row = *(refComboModel->append());
435 row[comboModel.m_type_id] = i;
436 row[comboModel.m_type_name] = sType;
437 count++;
438 }
439 }
440 Gtk::Table table(1, 2);
441 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
442 Gtk::ComboBox comboDimType;
443 comboDimType.set_model(refComboModel);
444 comboDimType.pack_start(comboModel.m_type_id);
445 comboDimType.pack_start(comboModel.m_type_name);
446 table.attach(labelDimType, 0, 1, 0, 1);
447 table.attach(comboDimType, 1, 2, 0, 1);
448 dialog.get_vbox()->pack_start(table);
449
450 dialog.add_button(_("_OK"), 0);
451 dialog.add_button(_("_Cancel"), 1);
452 dialog.show_all_children();
453
454 comboDimType.set_active(oldTypeIndex);
455
456 if (!dialog.run()) { // OK selected ...
457 ignoreColumnClicked = true;
458 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
459 if (!iterType) return;
460 Gtk::TreeModel::Row rowType = *iterType;
461 if (!rowType) return;
462 int iTypeID = rowType[comboModel.m_type_id];
463 gig::dimension_t newType = static_cast<gig::dimension_t>(iTypeID);
464 if (newType == oldType) return;
465 //printf("change 0x%x -> 0x%x\n", oldType, newType);
466
467 // assemble the list of regions where the selected dimension type
468 // shall be changed
469 std::vector<gig::Region*> vRegions;
470 if (allRegions()) {
471 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
472 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
473 if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
474 }
475 } else vRegions.push_back(region);
476
477 std::set<Glib::ustring> errors;
478
479 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
480 gig::Region* region = vRegions[iRgn];
481 try {
482 // notify everybody that we're going to update the region
483 region_to_be_changed_signal.emit(region);
484 // change the dimension type on that region
485 region->SetDimensionType(oldType, newType);
486 // let everybody know there was a change
487 region_changed_signal.emit(region);
488 } catch (RIFF::Exception e) {
489 // notify that the changes are over (i.e. to avoid dead locks)
490 region_changed_signal.emit(region);
491 Glib::ustring txt = _("Could not alter dimension: ") + e.Message;
492 if (vRegions.size() == 1) {
493 // show error message directly
494 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
495 msg.run();
496 } else {
497 // remember error, they are shown after all regions have been processed
498 errors.insert(txt);
499 }
500 }
501 }
502 // update all GUI elements
503 refreshManager();
504
505 if (!errors.empty()) {
506 Glib::ustring txt = _(
507 "The following errors occurred while trying to change the dimension type on all regions:"
508 );
509 txt += "\n\n";
510 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
511 it != errors.end(); ++it)
512 {
513 txt += "-> " + *it + "\n";
514 }
515 txt += "\n";
516 txt += _(
517 "You might also want to check the console for further warnings and "
518 "error messages."
519 );
520 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
521 msg.run();
522 }
523 }
524 }
525 }
526
527 void DimensionManager::addDimension() {
528 Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
529 // add dimension type combo box to the dialog
530 Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
531 for (int i = 0x01; i < 0xff; i++) {
532 Glib::ustring sType =
533 dimTypeAsString(static_cast<gig::dimension_t>(i));
534 if (sType.find("Unknown") != 0) {
535 Gtk::TreeModel::Row row = *(refComboModel->append());
536 row[comboModel.m_type_id] = i;
537 row[comboModel.m_type_name] = sType;
538 }
539 }
540 Gtk::Table table(2, 2);
541 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
542 Gtk::ComboBox comboDimType;
543 comboDimType.set_model(refComboModel);
544 comboDimType.pack_start(comboModel.m_type_id);
545 comboDimType.pack_start(comboModel.m_type_name);
546 Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
547 table.attach(labelDimType, 0, 1, 0, 1);
548 table.attach(comboDimType, 1, 2, 0, 1);
549 table.attach(labelZones, 0, 1, 1, 2);
550 dialog.get_vbox()->pack_start(table);
551
552 // number of zones: use a combo box with fix values for gig
553 // v2 and a spin button for v3
554 Gtk::ComboBoxText comboZones;
555 Gtk::SpinButton spinZones;
556 bool version2 = false;
557 if (region) {
558 gig::File* file = (gig::File*)region->GetParent()->GetParent();
559 version2 = file->pVersion && file->pVersion->major == 2;
560 }
561 if (version2) {
562 for (int i = 1; i <= 5; i++) {
563 char buf[3];
564 sprintf(buf, "%d", 1 << i);
565 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
566 comboZones.append_text(buf);
567 #else
568 comboZones.append(buf);
569 #endif
570 }
571 table.attach(comboZones, 1, 2, 1, 2);
572 } else {
573 spinZones.set_increments(1, 8);
574 spinZones.set_numeric(true);
575 spinZones.set_range(2, 128);
576 spinZones.set_value(2);
577 table.attach(spinZones, 1, 2, 1, 2);
578 }
579
580 dialog.add_button(_("_OK"), 0);
581 dialog.add_button(_("_Cancel"), 1);
582 dialog.show_all_children();
583
584 if (!dialog.run()) { // OK selected ...
585 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
586 if (!iterType) return;
587 Gtk::TreeModel::Row rowType = *iterType;
588 if (!rowType) return;
589 int iTypeID = rowType[comboModel.m_type_id];
590 gig::dimension_t type = static_cast<gig::dimension_t>(iTypeID);
591 gig::dimension_def_t dim;
592 dim.dimension = type;
593
594 if (version2) {
595 if (comboZones.get_active_row_number() < 0) return;
596 dim.bits = comboZones.get_active_row_number() + 1;
597 dim.zones = 1 << dim.bits;
598 } else {
599 dim.zones = spinZones.get_value_as_int();
600 dim.bits = zoneCountToBits(dim.zones);
601 }
602
603 // assemble the list of regions where the selected dimension shall be
604 // added to
605 std::vector<gig::Region*> vRegions;
606 if (allRegions()) {
607 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
608 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
609 if (!rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
610 }
611 } else vRegions.push_back(region);
612
613 std::set<Glib::ustring> errors;
614
615 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
616 gig::Region* region = vRegions[iRgn];
617 try {
618 printf(
619 "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
620 dim.dimension, dim.bits, dim.zones
621 );
622 // notify everybody that we're going to update the region
623 region_to_be_changed_signal.emit(region);
624 // add the new dimension to the region
625 // (implicitly creates new dimension regions)
626 region->AddDimension(&dim);
627 // let everybody know there was a change
628 region_changed_signal.emit(region);
629 } catch (RIFF::Exception e) {
630 // notify that the changes are over (i.e. to avoid dead locks)
631 region_changed_signal.emit(region);
632 Glib::ustring txt = _("Could not add dimension: ") + e.Message;
633 if (vRegions.size() == 1) {
634 // show error message directly
635 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
636 msg.run();
637 } else {
638 // remember error, they are shown after all regions have been processed
639 errors.insert(txt);
640 }
641 }
642 }
643 // update all GUI elements
644 refreshManager();
645
646 if (!errors.empty()) {
647 Glib::ustring txt = _(
648 "The following errors occurred while trying to create the dimension on all regions:"
649 );
650 txt += "\n\n";
651 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
652 it != errors.end(); ++it)
653 {
654 txt += "-> " + *it + "\n";
655 }
656 txt += "\n";
657 txt += _(
658 "You might also want to check the console for further warnings and "
659 "error messages."
660 );
661 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
662 msg.run();
663 }
664 }
665 }
666
667 void DimensionManager::removeDimension() {
668 Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
669 Gtk::TreeModel::iterator it = sel->get_selected();
670 if (it) {
671 Gtk::TreeModel::Row row = *it;
672 gig::dimension_t type = row[tableModel.m_type];
673
674 // assemble the list of regions where the selected dimension shall be
675 // added to
676 std::vector<gig::Region*> vRegions;
677 if (allRegions()) {
678 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
679 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
680 if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
681 }
682 } else vRegions.push_back(region);
683
684 std::set<Glib::ustring> errors;
685
686 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
687 gig::Region* region = vRegions[iRgn];
688 gig::dimension_def_t* dim = region->GetDimensionDefinition(type);
689 try {
690 // notify everybody that we're going to update the region
691 region_to_be_changed_signal.emit(region);
692 // remove selected dimension
693 region->DeleteDimension(dim);
694 // let everybody know there was a change
695 region_changed_signal.emit(region);
696 } catch (RIFF::Exception e) {
697 // notify that the changes are over (i.e. to avoid dead locks)
698 region_changed_signal.emit(region);
699 Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
700 if (vRegions.size() == 1) {
701 // show error message directly
702 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
703 msg.run();
704 } else {
705 // remember error, they are shown after all regions have been processed
706 errors.insert(txt);
707 }
708 }
709 }
710 // update all GUI elements
711 refreshManager();
712
713 if (!errors.empty()) {
714 Glib::ustring txt = _(
715 "The following errors occurred while trying to remove the dimension from all regions:"
716 );
717 txt += "\n\n";
718 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
719 it != errors.end(); ++it)
720 {
721 txt += "-> " + *it + "\n";
722 }
723 txt += "\n";
724 txt += _(
725 "You might also want to check the console for further warnings and "
726 "error messages."
727 );
728 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
729 msg.run();
730 }
731 }
732 }

  ViewVC Help
Powered by ViewVC