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