/[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 2641 - (show annotations) (download)
Mon Jun 16 15:24:54 2014 UTC (5 years, 5 months ago) by schoenebeck
File size: 28642 byte(s)
* Region Chooser: Double click opens dimension manager dialog.
* Dimension Manager: Clicking on dimension type cell of an existing
  dimension opens a popup to alter the dimension type.

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

  ViewVC Help
Powered by ViewVC