/[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 2845 - (show annotations) (download)
Sun Sep 20 10:18:22 2015 UTC (8 years, 6 months ago) by persson
File size: 28937 byte(s)
* avoid using gtk stock items, as they are deprecated in gtk 3.10

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

  ViewVC Help
Powered by ViewVC