/[svn]/gigedit/trunk/src/gigedit/dimensionmanager.cpp
ViewVC logotype

Diff of /gigedit/trunk/src/gigedit/dimensionmanager.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2169 by persson, Sun Mar 6 07:51:04 2011 UTC revision 3225 by schoenebeck, Fri May 26 22:10:16 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2011 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
# Line 17  Line 17 
17   * 02110-1301 USA.   * 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"  #include "dimensionmanager.h"
29    
30  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
# Line 30  Line 38 
38  #include "compat.h"  #include "compat.h"
39    
40  // returns a human readable name of the given dimension type  // returns a human readable name of the given dimension type
41  static Glib::ustring __dimTypeAsString(gig::dimension_t d) {  Glib::ustring dimTypeAsString(gig::dimension_t d) {
42      char buf[32];      char buf[32];
43      switch (d) {      switch (d) {
44          case gig::dimension_none:          case gig::dimension_none:
# Line 183  static Glib::ustring __dimDescriptionAsS Line 191  static Glib::ustring __dimDescriptionAsS
191      }      }
192  }  }
193    
194    DimTypeCellRenderer::DimTypeCellRenderer() :
195        Glib::ObjectBase(typeid(DimTypeCellRenderer)),
196        Gtk::CellRendererText(),
197        m_propertyDimType(*this, "gigdimension_t", gig::dimension_none),
198        m_propertyUsageCount(*this, "intusagecount", 0),
199        m_propertyTotalRegions(*this, "inttotalregions", 0)
200    {
201        propertyDimType().signal_changed().connect(
202            sigc::mem_fun(*this, &DimTypeCellRenderer::typeChanged)
203        );
204        propertyUsageCount().signal_changed().connect(
205            sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
206        );
207        propertyTotalRegions().signal_changed().connect(
208            sigc::mem_fun(*this, &DimTypeCellRenderer::statsChanged)
209        );
210    }
211    
212    void DimTypeCellRenderer::typeChanged() {
213        gig::dimension_t type = propertyDimType();
214        Glib::ustring s = dimTypeAsString(type);
215        property_text() = s;
216    }
217    
218    void DimTypeCellRenderer::statsChanged() {
219        int usageCount   = propertyUsageCount();
220        int totalRegions = propertyTotalRegions();
221        bool bDimensionExistsOnAllRegions = (usageCount == totalRegions);
222        property_foreground() = ((bDimensionExistsOnAllRegions) ? "black" : "gray");
223    }
224    
225    IntSetCellRenderer::IntSetCellRenderer() :
226        Glib::ObjectBase(typeid(IntSetCellRenderer)),
227        Gtk::CellRendererText(),
228        m_propertyValue(*this, "stdintset", std::set<int>())
229    {
230        propertyValue().signal_changed().connect(
231            sigc::mem_fun(*this, &IntSetCellRenderer::valueChanged)
232        );
233    }
234    
235    void IntSetCellRenderer::valueChanged() {
236        Glib::ustring s;
237        std::set<int> v = propertyValue();
238        for (std::set<int>::const_iterator it = v.begin(); it != v.end(); ++it) {
239            s += ToString(*it);
240            if (*it != *v.rbegin()) s += "|";
241        }
242        property_text() = s;
243        property_foreground() = (v.size() > 1) ? "gray" : "black";
244    }
245    
246  DimensionManager::DimensionManager() :  DimensionManager::DimensionManager() :
247  addButton(Gtk::Stock::ADD), removeButton(Gtk::Stock::REMOVE)      addButton(Gtk::Stock::ADD), removeButton(Gtk::Stock::REMOVE),
248        allRegionsCheckBox(_("All Regions"))
249  {  {
250        ignoreColumnClicked = true;
251    
252        if (!Settings::singleton()->autoRestoreWindowDimension) {
253            set_default_size(630, 250);
254            set_position(Gtk::WIN_POS_MOUSE);
255        }
256    
257      set_title(_("Dimensions of selected Region"));      set_title(_("Dimensions of selected Region"));
258      add(vbox);      add(vbox);
259      scrolledWindow.add(treeView);      scrolledWindow.add(treeView);
# Line 195  addButton(Gtk::Stock::ADD), removeButton Line 263  addButton(Gtk::Stock::ADD), removeButton
263      buttonBox.set_layout(Gtk::BUTTONBOX_END);      buttonBox.set_layout(Gtk::BUTTONBOX_END);
264      buttonBox.set_border_width(5);      buttonBox.set_border_width(5);
265      buttonBox.show();      buttonBox.show();
266        buttonBox.pack_start(allRegionsCheckBox, Gtk::PACK_EXPAND_PADDING);
267      buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);      buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);
268      buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);      buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);
269      addButton.show();      addButton.show();
270      removeButton.show();      removeButton.show();
271        allRegionsCheckBox.set_tooltip_text(
272            _("Enable this if you want to edit dimensions of all regions simultaniously.")
273        );
274    
275      // setup the table      // setup the table
276      refTableModel = Gtk::ListStore::create(tableModel);      refTableModel = Gtk::ListStore::create(tableModel);
277      treeView.set_model(refTableModel);      treeView.set_model(refTableModel);
278      treeView.append_column(_("Dimension Type"), tableModel.m_dim_type);      treeView.append_column(_("Dimension Type"), m_cellRendererDimType);
279      treeView.append_column(_("Bits"), tableModel.m_bits);      treeView.append_column(_("Bits"), m_cellRendererIntSet);
280      treeView.append_column(_("Zones"), tableModel.m_zones);      treeView.append_column(_("Zones"), m_cellRendererIntSet);
281      treeView.append_column(_("Description"), tableModel.m_description);      treeView.append_column(_("Description"), tableModel.m_description);
282        treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyDimType(), tableModel.m_type);
283        treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyUsageCount(), tableModel.m_usageCount);
284        treeView.get_column(0)->add_attribute(m_cellRendererDimType.propertyTotalRegions(), tableModel.m_totalRegions);
285        treeView.get_column(1)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_bits);
286        treeView.get_column(2)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_zones);
287      treeView.show();      treeView.show();
288    
289        treeView.signal_cursor_changed().connect(
290            sigc::mem_fun(*this, &DimensionManager::onColumnClicked)
291        );
292    
293      addButton.signal_clicked().connect(      addButton.signal_clicked().connect(
294          sigc::mem_fun(*this, &DimensionManager::addDimension)          sigc::mem_fun(*this, &DimensionManager::addDimension)
295      );      );
# Line 216  addButton(Gtk::Stock::ADD), removeButton Line 297  addButton(Gtk::Stock::ADD), removeButton
297      removeButton.signal_clicked().connect(      removeButton.signal_clicked().connect(
298          sigc::mem_fun(*this, &DimensionManager::removeDimension)          sigc::mem_fun(*this, &DimensionManager::removeDimension)
299      );      );
300        allRegionsCheckBox.signal_toggled().connect(
301            sigc::mem_fun(*this, &DimensionManager::onAllRegionsCheckBoxToggled)
302        );
303    
304      show_all_children();      show_all_children();
305  }  }
306    
307    bool DimensionManager::allRegions() const {
308        return allRegionsCheckBox.get_active();
309    }
310    
311    void DimensionManager::onAllRegionsCheckBoxToggled() {
312        set_title(
313            allRegions() ? _("Dimensions of all Regions") :  _("Dimensions of selected Region")
314        );
315        treeView.set_tooltip_text(
316            allRegions()
317                ? _("Dimensions and numbers in gray indicates a difference among the individual regions.")
318                : _("You are currently only viewing dimensions of the currently selected region.")
319        );
320        refreshManager();
321    }
322    
323    // following two data types are just used in DimensionManager::refresManager(),
324    // due to the maps template nature however, they must be declared at global
325    // space to avoid compilation errors
326    struct _DimDef {
327        std::set<int> bits;
328        std::set<int> zones;
329        int usageCount;
330    };
331    typedef std::map<gig::dimension_t, _DimDef> _Dimensions;
332    
333  // update all GUI elements according to current gig::Region informations  // update all GUI elements according to current gig::Region informations
334  void DimensionManager::refreshManager() {  void DimensionManager::refreshManager() {
335        set_sensitive(false);
336      refTableModel->clear();      refTableModel->clear();
337      if (region) {      if (allRegions()) {
338          for (int i = 0; i < region->Dimensions; i++) {          if (region) {
339              gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];              _Dimensions dims;
340              Gtk::TreeModel::Row row = *(refTableModel->append());              gig::Instrument* instr = (gig::Instrument*)region->GetParent();
341              row[tableModel.m_dim_type] = __dimTypeAsString(dim->dimension);              int iRegionsCount = 0;
342              row[tableModel.m_bits] = dim->bits;              for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion(), ++iRegionsCount) {
343              row[tableModel.m_zones] = dim->zones;                  for (uint i = 0; i < rgn->Dimensions; i++) {
344              row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);                      gig::dimension_def_t* dim = &rgn->pDimensionDefinitions[i];
345              row[tableModel.m_definition] = dim;                      dims[dim->dimension].bits.insert(dim->bits);
346                        dims[dim->dimension].zones.insert(dim->zones);
347                        dims[dim->dimension].usageCount++;
348                    }
349                }
350                for (_Dimensions::const_iterator it = dims.begin(); it != dims.end(); ++it) {
351                    Gtk::TreeModel::Row row = *(refTableModel->append());
352                    row[tableModel.m_type] = it->first;
353                    row[tableModel.m_bits] = it->second.bits;
354                    row[tableModel.m_zones] = it->second.zones;
355                    row[tableModel.m_description] = __dimDescriptionAsString(it->first);
356                    row[tableModel.m_usageCount] = it->second.usageCount;
357                    row[tableModel.m_totalRegions] = iRegionsCount;
358                }
359            }
360        } else {
361            if (region) {
362                for (uint i = 0; i < region->Dimensions; i++) {
363                    gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];
364                    Gtk::TreeModel::Row row = *(refTableModel->append());
365                    std::set<int> vBits;
366                    vBits.insert(dim->bits);
367                    row[tableModel.m_bits] = vBits;
368                    std::set<int> vZones;
369                    vZones.insert(dim->zones);
370                    row[tableModel.m_zones] = vZones;
371                    row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);
372                    row[tableModel.m_type] = dim->dimension;
373                    row[tableModel.m_usageCount] = 1;
374                    row[tableModel.m_totalRegions] = 1;
375                }
376          }          }
377      }      }
378      set_sensitive(region);      set_sensitive(region);
379  }  }
380    
381  void DimensionManager::show(gig::Region* region) {  void DimensionManager::show(gig::Region* region) {
382        ignoreColumnClicked = true;
383      this->region = region;      this->region = region;
384      refreshManager();      refreshManager();
385      Gtk::Window::show();      Gtk::Window::show();
386      deiconify();      deiconify();
387        ignoreColumnClicked = false;
388  }  }
389    
390  void DimensionManager::set_region(gig::Region* region) {  void DimensionManager::set_region(gig::Region* region) {
391        ignoreColumnClicked = true;
392      this->region = region;      this->region = region;
393      refreshManager();      refreshManager();
394        ignoreColumnClicked = false;
395  }  }
396    
397  void DimensionManager::addDimension() {  void DimensionManager::onColumnClicked() {
398      try {      printf("DimensionManager::onColumnClicked()\n");
399          Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);  
400          // add dimension type combo box to the dialog      //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 !
401    
402        //HACK: Prevents that onColumnClicked() gets called multiple times or at times where it is not desired
403        if (ignoreColumnClicked) {
404            ignoreColumnClicked = false;
405            return;
406        }
407    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 18) || GTKMM_MAJOR_VERSION > 2
408        // prevents app to crash if this dialog is closed
409        if (!get_visible())
410            return;
411    #else
412    # warning Your GTKMM version is too old; dimension manager dialog might crash when changing a dimension type !
413    #endif
414    
415    #if (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 3
416        if (!is_visible()) return;
417    #endif
418    
419        Gtk::TreeModel::Path path;
420        Gtk::TreeViewColumn* focus_column;
421        treeView.get_cursor(path, focus_column);
422        //const int row = path[0];
423        if (focus_column == treeView.get_column(0)) {
424            Gtk::TreeModel::iterator it = treeView.get_model()->get_iter(path);
425            if (!it) return;
426            Gtk::TreeModel::Row row = *it;
427            gig::dimension_t oldType = row[tableModel.m_type];
428    
429            Gtk::Dialog dialog(_("Change Dimension"), true /*modal*/);
430            int oldTypeIndex = -1;
431          Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);          Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
432          for (int i = 0x01; i < 0xff; i++) {          for (int i = 0x01, count = 0; i < 0xff; i++) {
433              Glib::ustring sType =              Glib::ustring sType =
434                  __dimTypeAsString(static_cast<gig::dimension_t>(i));                  dimTypeAsString(static_cast<gig::dimension_t>(i));
435                if (i == oldType) oldTypeIndex = count;
436              if (sType.find("Unknown") != 0) {              if (sType.find("Unknown") != 0) {
437                  Gtk::TreeModel::Row row = *(refComboModel->append());                  Gtk::TreeModel::Row row = *(refComboModel->append());
438                  row[comboModel.m_type_id]   = i;                  row[comboModel.m_type_id]   = i;
439                  row[comboModel.m_type_name] = sType;                  row[comboModel.m_type_name] = sType;
440                    count++;
441              }              }
442          }          }
443          Gtk::Table table(2, 2);          Gtk::Table table(1, 2);
444          Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);          Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
445          Gtk::ComboBox comboDimType;          Gtk::ComboBox comboDimType;
446          comboDimType.set_model(refComboModel);          comboDimType.set_model(refComboModel);
447          comboDimType.pack_start(comboModel.m_type_id);          comboDimType.pack_start(comboModel.m_type_id);
448          comboDimType.pack_start(comboModel.m_type_name);          comboDimType.pack_start(comboModel.m_type_name);
         Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);  
449          table.attach(labelDimType, 0, 1, 0, 1);          table.attach(labelDimType, 0, 1, 0, 1);
450          table.attach(comboDimType, 1, 2, 0, 1);          table.attach(comboDimType, 1, 2, 0, 1);
         table.attach(labelZones, 0, 1, 1, 2);  
451          dialog.get_vbox()->pack_start(table);          dialog.get_vbox()->pack_start(table);
452    
         // number of zones: use a combo box with fix values for gig  
         // v2 and a spin button for v3  
         Gtk::ComboBoxText comboZones;  
         Gtk::SpinButton spinZones;  
         bool version2 = false;  
         if (region) {  
             gig::File* file = (gig::File*)region->GetParent()->GetParent();  
             version2 = file->pVersion && file->pVersion->major == 2;  
         }  
         if (version2) {  
             for (int i = 1; i <= 5; i++) {  
                 char buf[3];  
                 sprintf(buf, "%d", 1 << i);  
 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  
                 comboZones.append_text(buf);  
 #else  
                 comboZones.append(buf);  
 #endif  
             }  
             table.attach(comboZones, 1, 2, 1, 2);  
         } else {  
             spinZones.set_increments(1, 8);  
             spinZones.set_numeric(true);  
             spinZones.set_range(2, 128);  
             spinZones.set_value(2);  
             table.attach(spinZones, 1, 2, 1, 2);  
         }  
   
453          dialog.add_button(Gtk::Stock::OK, 0);          dialog.add_button(Gtk::Stock::OK, 0);
454          dialog.add_button(Gtk::Stock::CANCEL, 1);          dialog.add_button(Gtk::Stock::CANCEL, 1);
455          dialog.show_all_children();          dialog.show_all_children();
456            
457            comboDimType.set_active(oldTypeIndex);
458    
459          if (!dialog.run()) { // OK selected ...          if (!dialog.run()) { // OK selected ...
460                ignoreColumnClicked = true;
461              Gtk::TreeModel::iterator iterType = comboDimType.get_active();              Gtk::TreeModel::iterator iterType = comboDimType.get_active();
462              if (!iterType) return;              if (!iterType) return;
463              Gtk::TreeModel::Row rowType = *iterType;              Gtk::TreeModel::Row rowType = *iterType;
464              if (!rowType) return;              if (!rowType) return;
             gig::dimension_def_t dim;  
465              int iTypeID = rowType[comboModel.m_type_id];              int iTypeID = rowType[comboModel.m_type_id];
466              dim.dimension = static_cast<gig::dimension_t>(iTypeID);              gig::dimension_t newType = static_cast<gig::dimension_t>(iTypeID);
467                if (newType == oldType) return;
468              if (version2) {              //printf("change 0x%x -> 0x%x\n", oldType, newType);
469                  if (comboZones.get_active_row_number() < 0) return;  
470                  dim.bits = comboZones.get_active_row_number() + 1;              // assemble the list of regions where the selected dimension type
471                  dim.zones = 1 << dim.bits;              // shall be changed
472              } else {              std::vector<gig::Region*> vRegions;
473                  dim.zones = spinZones.get_value_as_int();              if (allRegions()) {
474                  // Find the number of bits required to hold the                  gig::Instrument* instr = (gig::Instrument*)region->GetParent();
475                  // specified amount of zones.                  for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
476                  int zoneBits = dim.zones - 1;                      if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
477                  for (dim.bits = 0; zoneBits > 1; dim.bits += 2, zoneBits >>= 2);                  }
478                  dim.bits += zoneBits;              } else vRegions.push_back(region);
479              }  
480              printf(              std::set<Glib::ustring> errors;
481                  "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",  
482                  dim.dimension, dim.bits, dim.zones              for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
483              );                  gig::Region* region = vRegions[iRgn];
484              // notify everybody that we're going to update the region                  try {
485              region_to_be_changed_signal.emit(region);                      // notify everybody that we're going to update the region
486              // add the new dimension to the region                      region_to_be_changed_signal.emit(region);
487              // (implicitly creates new dimension regions)                      // change the dimension type on that region
488              region->AddDimension(&dim);                      region->SetDimensionType(oldType, newType);
489              // let everybody know there was a change                      // let everybody know there was a change
490              region_changed_signal.emit(region);                      region_changed_signal.emit(region);
491                    } catch (RIFF::Exception e) {
492                        // notify that the changes are over (i.e. to avoid dead locks)
493                        region_changed_signal.emit(region);
494                        Glib::ustring txt = _("Could not alter dimension: ") + e.Message;
495                        if (vRegions.size() == 1) {
496                            // show error message directly
497                            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
498                            msg.run();
499                        } else {
500                            // remember error, they are shown after all regions have been processed
501                            errors.insert(txt);
502                        }
503                    }
504                }
505              // update all GUI elements              // update all GUI elements
506              refreshManager();              refreshManager();
507    
508                if (!errors.empty()) {
509                    Glib::ustring txt = _(
510                        "The following errors occurred while trying to change the dimension type on all regions:"
511                    );
512                    txt += "\n\n";
513                    for (std::set<Glib::ustring>::const_iterator it = errors.begin();
514                        it != errors.end(); ++it)
515                    {
516                        txt += "-> " + *it + "\n";
517                    }
518                    txt += "\n";
519                    txt += _(
520                        "You might also want to check the console for further warnings and "
521                        "error messages."
522                    );
523                    Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
524                    msg.run();
525                }
526          }          }
527      } catch (RIFF::Exception e) {      } else if (focus_column == treeView.get_column(1) || focus_column == treeView.get_column(2)) {
528          // 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!");
529          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);  
530          msg.run();          msg.run();
531      }      }
532  }  }
533    
534  void DimensionManager::removeDimension() {  void DimensionManager::addDimension() {
535        Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
536        // add dimension type combo box to the dialog
537        Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
538        for (int i = 0x01; i < 0xff; i++) {
539            Glib::ustring sType =
540                dimTypeAsString(static_cast<gig::dimension_t>(i));
541            if (sType.find("Unknown") != 0) {
542                Gtk::TreeModel::Row row = *(refComboModel->append());
543                row[comboModel.m_type_id]   = i;
544                row[comboModel.m_type_name] = sType;
545            }
546        }
547        Gtk::Table table(2, 2);
548        Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
549        Gtk::ComboBox comboDimType;
550        comboDimType.set_model(refComboModel);
551        comboDimType.pack_start(comboModel.m_type_id);
552        comboDimType.pack_start(comboModel.m_type_name);
553        Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
554        table.attach(labelDimType, 0, 1, 0, 1);
555        table.attach(comboDimType, 1, 2, 0, 1);
556        table.attach(labelZones, 0, 1, 1, 2);
557        dialog.get_vbox()->pack_start(table);
558    
559        // number of zones: use a combo box with fix values for gig
560        // v2 and a spin button for v3
561        Gtk::ComboBoxText comboZones;
562        Gtk::SpinButton spinZones;
563        bool version2 = false;
564        if (region) {
565            gig::File* file = (gig::File*)region->GetParent()->GetParent();
566            version2 = file->pVersion && file->pVersion->major == 2;
567        }
568        if (version2) {
569            for (int i = 1; i <= 5; i++) {
570                char buf[3];
571                sprintf(buf, "%d", 1 << i);
572    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
573                comboZones.append_text(buf);
574    #else
575                comboZones.append(buf);
576    #endif
577            }
578            table.attach(comboZones, 1, 2, 1, 2);
579        } else {
580            spinZones.set_increments(1, 8);
581            spinZones.set_numeric(true);
582            spinZones.set_range(2, 128);
583            spinZones.set_value(2);
584            table.attach(spinZones, 1, 2, 1, 2);
585        }
586    
587        dialog.add_button(Gtk::Stock::OK, 0);
588        dialog.add_button(Gtk::Stock::CANCEL, 1);
589        dialog.show_all_children();
590    
591        if (!dialog.run()) { // OK selected ...
592            Gtk::TreeModel::iterator iterType = comboDimType.get_active();
593            if (!iterType) return;
594            Gtk::TreeModel::Row rowType = *iterType;
595            if (!rowType) return;
596            int iTypeID = rowType[comboModel.m_type_id];
597            gig::dimension_t type = static_cast<gig::dimension_t>(iTypeID);
598            gig::dimension_def_t dim;
599            dim.dimension = type;
600    
601            if (version2) {
602                if (comboZones.get_active_row_number() < 0) return;
603                dim.bits = comboZones.get_active_row_number() + 1;
604                dim.zones = 1 << dim.bits;
605            } else {
606                dim.zones = spinZones.get_value_as_int();
607                dim.bits = zoneCountToBits(dim.zones);
608            }
609    
610            // assemble the list of regions where the selected dimension shall be
611            // added to
612            std::vector<gig::Region*> vRegions;
613            if (allRegions()) {
614                gig::Instrument* instr = (gig::Instrument*)region->GetParent();
615                for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
616                    if (!rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
617                }
618            } else vRegions.push_back(region);
619                
620            std::set<Glib::ustring> errors;
621    
622            for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
623                gig::Region* region = vRegions[iRgn];
624                try {
625                    printf(
626                        "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
627                        dim.dimension, dim.bits, dim.zones
628                    );
629                    // notify everybody that we're going to update the region
630                    region_to_be_changed_signal.emit(region);
631                    // add the new dimension to the region
632                    // (implicitly creates new dimension regions)
633                    region->AddDimension(&dim);
634                    // let everybody know there was a change
635                    region_changed_signal.emit(region);
636                } catch (RIFF::Exception e) {
637                    // notify that the changes are over (i.e. to avoid dead locks)
638                    region_changed_signal.emit(region);
639                    Glib::ustring txt = _("Could not add dimension: ") + e.Message;
640                    if (vRegions.size() == 1) {
641                        // show error message directly
642                        Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
643                        msg.run();
644                    } else {
645                        // remember error, they are shown after all regions have been processed
646                        errors.insert(txt);
647                    }
648                }
649            }
650            // update all GUI elements
651            refreshManager();
652    
653            if (!errors.empty()) {
654                Glib::ustring txt = _(
655                    "The following errors occurred while trying to create the dimension on all regions:"
656                );
657                txt += "\n\n";
658                for (std::set<Glib::ustring>::const_iterator it = errors.begin();
659                     it != errors.end(); ++it)
660                {
661                    txt += "-> " + *it + "\n";
662                }
663                txt += "\n";
664                txt += _(
665                    "You might also want to check the console for further warnings and "
666                    "error messages."
667                );
668                Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
669                msg.run();
670            }
671        }
672    }
673    
674    void DimensionManager::removeDimension() {        
675      Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
676      Gtk::TreeModel::iterator it = sel->get_selected();      Gtk::TreeModel::iterator it = sel->get_selected();
677      if (it) {      if (it) {
678          try {          Gtk::TreeModel::Row row = *it;
679              // notify everybody that we're going to update the region          gig::dimension_t type = row[tableModel.m_type];
680              region_to_be_changed_signal.emit(region);  
681              // remove selected dimension          // assemble the list of regions where the selected dimension shall be
682              Gtk::TreeModel::Row row = *it;          // added to
683              gig::dimension_def_t* dim = row[tableModel.m_definition];          std::vector<gig::Region*> vRegions;
684              region->DeleteDimension(dim);          if (allRegions()) {
685              // let everybody know there was a change              gig::Instrument* instr = (gig::Instrument*)region->GetParent();
686              region_changed_signal.emit(region);              for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
687              // update all GUI elements                  if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
688              refreshManager();              }
689          } catch (RIFF::Exception e) {          } else vRegions.push_back(region);
690              // notify that the changes are over (i.e. to avoid dead locks)  
691              region_changed_signal.emit(region);          std::set<Glib::ustring> errors;
692              // show error message  
693              Glib::ustring txt = _("Could not remove dimension: ") + e.Message;          for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
694                gig::Region* region = vRegions[iRgn];
695                gig::dimension_def_t* dim = region->GetDimensionDefinition(type);
696                try {
697                    // notify everybody that we're going to update the region
698                    region_to_be_changed_signal.emit(region);
699                    // remove selected dimension    
700                    region->DeleteDimension(dim);
701                    // let everybody know there was a change
702                    region_changed_signal.emit(region);
703                } catch (RIFF::Exception e) {
704                    // notify that the changes are over (i.e. to avoid dead locks)
705                    region_changed_signal.emit(region);
706                    Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
707                    if (vRegions.size() == 1) {
708                        // show error message directly
709                        Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
710                        msg.run();
711                    } else {
712                        // remember error, they are shown after all regions have been processed
713                        errors.insert(txt);
714                    }
715                }
716            }
717            // update all GUI elements
718            refreshManager();
719    
720            if (!errors.empty()) {
721                Glib::ustring txt = _(
722                    "The following errors occurred while trying to remove the dimension from all regions:"
723                );
724                txt += "\n\n";
725                for (std::set<Glib::ustring>::const_iterator it = errors.begin();
726                     it != errors.end(); ++it)
727                {
728                    txt += "-> " + *it + "\n";
729                }
730                txt += "\n";
731                txt += _(
732                    "You might also want to check the console for further warnings and "
733                    "error messages."
734                );
735              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
736              msg.run();              msg.run();
737          }          }

Legend:
Removed from v.2169  
changed lines
  Added in v.3225

  ViewVC Help
Powered by ViewVC