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

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

  ViewVC Help
Powered by ViewVC