/[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 1831 by persson, Tue Feb 3 19:38:19 2009 UTC revision 3450 by schoenebeck, Wed Jan 2 16:39:20 2019 UTC
# Line 1  Line 1 
1  /*                                                         -*- c++ -*-  /*
2   * Copyright (C) 2006-2009 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 "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>  #include <gtkmm/spinbutton.h>
37  #include <gtkmm/table.h>  #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"  #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:
# Line 182  static Glib::ustring __dimDescriptionAsS Line 198  static Glib::ustring __dimDescriptionAsS
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        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"));      set_title(_("Dimensions of selected Region"));
275      add(vbox);      add(vbox);
276      scrolledWindow.add(treeView);      scrolledWindow.add(treeView);
# Line 192  addButton(Gtk::Stock::ADD), removeButton Line 278  addButton(Gtk::Stock::ADD), removeButton
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 > 24)
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      );      );
# Line 215  addButton(Gtk::Stock::ADD), removeButton Line 318  addButton(Gtk::Stock::ADD), removeButton
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    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  // update all GUI elements according to current gig::Region informations  // 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      if (region) {      if (allRegions()) {
375          for (int i = 0; i < region->Dimensions; i++) {          if (region) {
376              gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];              _Dimensions dims;
377              Gtk::TreeModel::Row row = *(refTableModel->append());              gig::Instrument* instr = (gig::Instrument*)region->GetParent();
378              row[tableModel.m_dim_type] = __dimTypeAsString(dim->dimension);              int iRegionsCount = 0;
379              row[tableModel.m_bits] = dim->bits;              for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion(), ++iRegionsCount) {
380              row[tableModel.m_zones] = dim->zones;                  for (uint i = 0; i < rgn->Dimensions; i++) {
381              row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);                      gig::dimension_def_t* dim = &rgn->pDimensionDefinitions[i];
382              row[tableModel.m_definition] = dim;                      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 = &region->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);      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::set_region(gig::Region* region) {  void DimensionManager::set_region(gig::Region* region) {
428        ignoreColumnClicked = true;
429      this->region = region;      this->region = region;
430      refreshManager();      refreshManager();
431        ignoreColumnClicked = false;
432  }  }
433    
434  void DimensionManager::addDimension() {  void DimensionManager::onColumnClicked() {
435      try {      printf("DimensionManager::onColumnClicked()\n");
436          Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);  
437          // 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 !
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          Gtk::Table table(2, 2);  #if USE_GTKMM_GRID
481          Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_LEFT);          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);
         Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_LEFT);  
490          table.attach(labelDimType, 0, 1, 0, 1);          table.attach(labelDimType, 0, 1, 0, 1);
491          table.attach(comboDimType, 1, 2, 0, 1);          table.attach(comboDimType, 1, 2, 0, 1);
492          table.attach(labelZones, 0, 1, 1, 2);  #if USE_GTKMM_BOX
493            dialog.get_content_area()->pack_start(table);
494    #else
495          dialog.get_vbox()->pack_start(table);          dialog.get_vbox()->pack_start(table);
496    #endif
497    
498          // number of zones: use a combo box with fix values for gig  #if HAS_GTKMM_STOCK
         // 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);  
                 comboZones.append_text(buf);  
             }  
             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);  
         }  
   
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 (newType == oldType) return;
520              if (version2) {              //printf("change 0x%x -> 0x%x\n", oldType, newType);
521                  if (comboZones.get_active_row_number() < 0) return;  
522                  dim.bits = comboZones.get_active_row_number() + 1;              // assemble the list of regions where the selected dimension type
523                  dim.zones = 1 << dim.bits;              // shall be changed
524              } else {              std::vector<gig::Region*> vRegions;
525                  dim.zones = spinZones.get_value_as_int();              if (allRegions()) {
526                  // Find the number of bits required to hold the                  gig::Instrument* instr = (gig::Instrument*)region->GetParent();
527                  // specified amount of zones.                  for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
528                  int zoneBits = dim.zones - 1;                      if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
529                  for (dim.bits = 0; zoneBits > 1; dim.bits += 2, zoneBits >>= 2);                  }
530                  dim.bits += zoneBits;              } else vRegions.push_back(region);
531              }  
532              printf(              std::set<Glib::ustring> errors;
533                  "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",  
534                  dim.dimension, dim.bits, dim.zones              for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
535              );                  gig::Region* region = vRegions[iRgn];
536              // notify everybody that we're going to update the region                  try {
537              region_to_be_changed_signal.emit(region);                      // notify everybody that we're going to update the region
538              // add the new dimension to the region                      region_to_be_changed_signal.emit(region);
539              // (implicitly creates new dimension regions)                      // change the dimension type on that region
540              region->AddDimension(&dim);                      region->SetDimensionType(oldType, newType);
541              // let everybody know there was a change                      // let everybody know there was a change
542              region_changed_signal.emit(region);                      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              // let everybody know there was a change              gig::Instrument* instr = (gig::Instrument*)region->GetParent();
760              region_changed_signal.emit(region);              for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
761              // update all GUI elements                  if (rgn->GetDimensionDefinition(type)) vRegions.push_back(rgn);
762              refreshManager();              }
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          }          }

Legend:
Removed from v.1831  
changed lines
  Added in v.3450

  ViewVC Help
Powered by ViewVC