/[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 2919 - (show annotations) (download)
Wed May 18 11:37:31 2016 UTC (7 years, 10 months ago) by schoenebeck
File size: 29353 byte(s)
* Fixed crash after changing a dimension type with the dimension manager
  dialog.
* Bumped version (1.0.0.svn15).

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 // prevents app to crash if this dialog is closed
405 if (!get_visible())
406 return;
407
408 Gtk::TreeModel::Path path;
409 Gtk::TreeViewColumn* focus_column;
410 treeView.get_cursor(path, focus_column);
411 //const int row = path[0];
412 if (focus_column == treeView.get_column(0)) {
413 Gtk::TreeModel::iterator it = treeView.get_model()->get_iter(path);
414 Gtk::TreeModel::Row row = *it;
415 gig::dimension_t oldType = row[tableModel.m_type];
416
417 Gtk::Dialog dialog(_("Change Dimension"), true /*modal*/);
418 int oldTypeIndex = -1;
419 Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
420 for (int i = 0x01, count = 0; i < 0xff; i++) {
421 Glib::ustring sType =
422 dimTypeAsString(static_cast<gig::dimension_t>(i));
423 if (i == oldType) oldTypeIndex = count;
424 if (sType.find("Unknown") != 0) {
425 Gtk::TreeModel::Row row = *(refComboModel->append());
426 row[comboModel.m_type_id] = i;
427 row[comboModel.m_type_name] = sType;
428 count++;
429 }
430 }
431 Gtk::Table table(1, 2);
432 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
433 Gtk::ComboBox comboDimType;
434 comboDimType.set_model(refComboModel);
435 comboDimType.pack_start(comboModel.m_type_id);
436 comboDimType.pack_start(comboModel.m_type_name);
437 table.attach(labelDimType, 0, 1, 0, 1);
438 table.attach(comboDimType, 1, 2, 0, 1);
439 dialog.get_vbox()->pack_start(table);
440
441 dialog.add_button(_("_OK"), 0);
442 dialog.add_button(_("_Cancel"), 1);
443 dialog.show_all_children();
444
445 comboDimType.set_active(oldTypeIndex);
446
447 if (!dialog.run()) { // OK selected ...
448 ignoreColumnClicked = true;
449 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
450 if (!iterType) return;
451 Gtk::TreeModel::Row rowType = *iterType;
452 if (!rowType) return;
453 int iTypeID = rowType[comboModel.m_type_id];
454 gig::dimension_t newType = static_cast<gig::dimension_t>(iTypeID);
455 if (newType == oldType) return;
456 //printf("change 0x%x -> 0x%x\n", oldType, newType);
457
458 // assemble the list of regions where the selected dimension type
459 // shall be changed
460 std::vector<gig::Region*> vRegions;
461 if (allRegions()) {
462 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
463 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
464 if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
465 }
466 } else vRegions.push_back(region);
467
468 std::set<Glib::ustring> errors;
469
470 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
471 gig::Region* region = vRegions[iRgn];
472 try {
473 // notify everybody that we're going to update the region
474 region_to_be_changed_signal.emit(region);
475 // change the dimension type on that region
476 region->SetDimensionType(oldType, newType);
477 // let everybody know there was a change
478 region_changed_signal.emit(region);
479 } catch (RIFF::Exception e) {
480 // notify that the changes are over (i.e. to avoid dead locks)
481 region_changed_signal.emit(region);
482 Glib::ustring txt = _("Could not alter dimension: ") + e.Message;
483 if (vRegions.size() == 1) {
484 // show error message directly
485 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
486 msg.run();
487 } else {
488 // remember error, they are shown after all regions have been processed
489 errors.insert(txt);
490 }
491 }
492 }
493 // update all GUI elements
494 refreshManager();
495
496 if (!errors.empty()) {
497 Glib::ustring txt = _(
498 "The following errors occurred while trying to change the dimension type on all regions:"
499 );
500 txt += "\n\n";
501 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
502 it != errors.end(); ++it)
503 {
504 txt += "-> " + *it + "\n";
505 }
506 txt += "\n";
507 txt += _(
508 "You might also want to check the console for further warnings and "
509 "error messages."
510 );
511 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
512 msg.run();
513 }
514 }
515 }
516 }
517
518 void DimensionManager::addDimension() {
519 Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
520 // add dimension type combo box to the dialog
521 Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
522 for (int i = 0x01; i < 0xff; i++) {
523 Glib::ustring sType =
524 dimTypeAsString(static_cast<gig::dimension_t>(i));
525 if (sType.find("Unknown") != 0) {
526 Gtk::TreeModel::Row row = *(refComboModel->append());
527 row[comboModel.m_type_id] = i;
528 row[comboModel.m_type_name] = sType;
529 }
530 }
531 Gtk::Table table(2, 2);
532 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
533 Gtk::ComboBox comboDimType;
534 comboDimType.set_model(refComboModel);
535 comboDimType.pack_start(comboModel.m_type_id);
536 comboDimType.pack_start(comboModel.m_type_name);
537 Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
538 table.attach(labelDimType, 0, 1, 0, 1);
539 table.attach(comboDimType, 1, 2, 0, 1);
540 table.attach(labelZones, 0, 1, 1, 2);
541 dialog.get_vbox()->pack_start(table);
542
543 // number of zones: use a combo box with fix values for gig
544 // v2 and a spin button for v3
545 Gtk::ComboBoxText comboZones;
546 Gtk::SpinButton spinZones;
547 bool version2 = false;
548 if (region) {
549 gig::File* file = (gig::File*)region->GetParent()->GetParent();
550 version2 = file->pVersion && file->pVersion->major == 2;
551 }
552 if (version2) {
553 for (int i = 1; i <= 5; i++) {
554 char buf[3];
555 sprintf(buf, "%d", 1 << i);
556 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
557 comboZones.append_text(buf);
558 #else
559 comboZones.append(buf);
560 #endif
561 }
562 table.attach(comboZones, 1, 2, 1, 2);
563 } else {
564 spinZones.set_increments(1, 8);
565 spinZones.set_numeric(true);
566 spinZones.set_range(2, 128);
567 spinZones.set_value(2);
568 table.attach(spinZones, 1, 2, 1, 2);
569 }
570
571 dialog.add_button(_("_OK"), 0);
572 dialog.add_button(_("_Cancel"), 1);
573 dialog.show_all_children();
574
575 if (!dialog.run()) { // OK selected ...
576 Gtk::TreeModel::iterator iterType = comboDimType.get_active();
577 if (!iterType) return;
578 Gtk::TreeModel::Row rowType = *iterType;
579 if (!rowType) return;
580 int iTypeID = rowType[comboModel.m_type_id];
581 gig::dimension_t type = static_cast<gig::dimension_t>(iTypeID);
582 gig::dimension_def_t dim;
583 dim.dimension = type;
584
585 if (version2) {
586 if (comboZones.get_active_row_number() < 0) return;
587 dim.bits = comboZones.get_active_row_number() + 1;
588 dim.zones = 1 << dim.bits;
589 } else {
590 dim.zones = spinZones.get_value_as_int();
591 dim.bits = zoneCountToBits(dim.zones);
592 }
593
594 // assemble the list of regions where the selected dimension shall be
595 // added to
596 std::vector<gig::Region*> vRegions;
597 if (allRegions()) {
598 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
599 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
600 if (!rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
601 }
602 } else vRegions.push_back(region);
603
604 std::set<Glib::ustring> errors;
605
606 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
607 gig::Region* region = vRegions[iRgn];
608 try {
609 printf(
610 "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
611 dim.dimension, dim.bits, dim.zones
612 );
613 // notify everybody that we're going to update the region
614 region_to_be_changed_signal.emit(region);
615 // add the new dimension to the region
616 // (implicitly creates new dimension regions)
617 region->AddDimension(&dim);
618 // let everybody know there was a change
619 region_changed_signal.emit(region);
620 } catch (RIFF::Exception e) {
621 // notify that the changes are over (i.e. to avoid dead locks)
622 region_changed_signal.emit(region);
623 Glib::ustring txt = _("Could not add dimension: ") + e.Message;
624 if (vRegions.size() == 1) {
625 // show error message directly
626 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
627 msg.run();
628 } else {
629 // remember error, they are shown after all regions have been processed
630 errors.insert(txt);
631 }
632 }
633 }
634 // update all GUI elements
635 refreshManager();
636
637 if (!errors.empty()) {
638 Glib::ustring txt = _(
639 "The following errors occurred while trying to create the dimension on all regions:"
640 );
641 txt += "\n\n";
642 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
643 it != errors.end(); ++it)
644 {
645 txt += "-> " + *it + "\n";
646 }
647 txt += "\n";
648 txt += _(
649 "You might also want to check the console for further warnings and "
650 "error messages."
651 );
652 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
653 msg.run();
654 }
655 }
656 }
657
658 void DimensionManager::removeDimension() {
659 Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
660 Gtk::TreeModel::iterator it = sel->get_selected();
661 if (it) {
662 Gtk::TreeModel::Row row = *it;
663 gig::dimension_t type = row[tableModel.m_type];
664
665 // assemble the list of regions where the selected dimension shall be
666 // added to
667 std::vector<gig::Region*> vRegions;
668 if (allRegions()) {
669 gig::Instrument* instr = (gig::Instrument*)region->GetParent();
670 for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
671 if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
672 }
673 } else vRegions.push_back(region);
674
675 std::set<Glib::ustring> errors;
676
677 for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
678 gig::Region* region = vRegions[iRgn];
679 gig::dimension_def_t* dim = region->GetDimensionDefinition(type);
680 try {
681 // notify everybody that we're going to update the region
682 region_to_be_changed_signal.emit(region);
683 // remove selected dimension
684 region->DeleteDimension(dim);
685 // let everybody know there was a change
686 region_changed_signal.emit(region);
687 } catch (RIFF::Exception e) {
688 // notify that the changes are over (i.e. to avoid dead locks)
689 region_changed_signal.emit(region);
690 Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
691 if (vRegions.size() == 1) {
692 // show error message directly
693 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
694 msg.run();
695 } else {
696 // remember error, they are shown after all regions have been processed
697 errors.insert(txt);
698 }
699 }
700 }
701 // update all GUI elements
702 refreshManager();
703
704 if (!errors.empty()) {
705 Glib::ustring txt = _(
706 "The following errors occurred while trying to remove the dimension from all regions:"
707 );
708 txt += "\n\n";
709 for (std::set<Glib::ustring>::const_iterator it = errors.begin();
710 it != errors.end(); ++it)
711 {
712 txt += "-> " + *it + "\n";
713 }
714 txt += "\n";
715 txt += _(
716 "You might also want to check the console for further warnings and "
717 "error messages."
718 );
719 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
720 msg.run();
721 }
722 }
723 }

  ViewVC Help
Powered by ViewVC