/[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 2921 - (show annotations) (download)
Wed May 18 11:57:58 2016 UTC (7 years, 10 months ago) by schoenebeck
File size: 29564 byte(s)
- Fixed compile error with older GTKMM versions.

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

  ViewVC Help
Powered by ViewVC