/[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 2562 by schoenebeck, Mon May 19 18:06:57 2014 UTC revision 3364 by schoenebeck, Tue Nov 14 18:07:25 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2014 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"  #include "compat.h"
# Line 236  void IntSetCellRenderer::valueChanged() Line 251  void IntSetCellRenderer::valueChanged()
251  }  }
252    
253  DimensionManager::DimensionManager() :  DimensionManager::DimensionManager() :
254  addButton(Gtk::Stock::ADD), removeButton(Gtk::Stock::REMOVE),  #if HAS_GTKMM_STOCK
255  allRegionsCheckBox(_("All Regions"))      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 246  allRegionsCheckBox(_("All Regions")) Line 278  allRegionsCheckBox(_("All Regions"))
278      scrolledWindow.show();      scrolledWindow.show();
279      vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);      vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
280      buttonBox.set_layout(Gtk::BUTTONBOX_END);      buttonBox.set_layout(Gtk::BUTTONBOX_END);
281    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22)
282        buttonBox.set_margin(5);
283    #else
284      buttonBox.set_border_width(5);      buttonBox.set_border_width(5);
285    #endif
286      buttonBox.show();      buttonBox.show();
287      buttonBox.pack_start(allRegionsCheckBox, Gtk::PACK_EXPAND_PADDING);      buttonBox.pack_start(allRegionsCheckBox, Gtk::PACK_EXPAND_PADDING);
288      buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);      buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);
# Line 271  allRegionsCheckBox(_("All Regions")) Line 307  allRegionsCheckBox(_("All Regions"))
307      treeView.get_column(2)->add_attribute(m_cellRendererIntSet.propertyValue(), tableModel.m_zones);      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 282  allRegionsCheckBox(_("All Regions")) Line 322  allRegionsCheckBox(_("All Regions"))
322          sigc::mem_fun(*this, &DimensionManager::onAllRegionsCheckBoxToggled)          sigc::mem_fun(*this, &DimensionManager::onAllRegionsCheckBoxToggled)
323      );      );
324    
325    #if HAS_GTKMM_SHOW_ALL_CHILDREN
326      show_all_children();      show_all_children();
327        #endif
     resize(460,300);  
328  }  }
329    
330  bool DimensionManager::allRegions() const {  bool DimensionManager::allRegions() const {
# Line 362  void DimensionManager::refreshManager() Line 402  void DimensionManager::refreshManager()
402  }  }
403    
404  void DimensionManager::show(gig::Region* region) {  void DimensionManager::show(gig::Region* region) {
405        ignoreColumnClicked = true;
406      this->region = region;      this->region = region;
407      refreshManager();      refreshManager();
408      Gtk::Window::show();      Gtk::Window::show();
409      deiconify();      deiconify();
410        ignoreColumnClicked = false;
411  }  }
412    
413  void DimensionManager::set_region(gig::Region* region) {  void DimensionManager::set_region(gig::Region* region) {
414        ignoreColumnClicked = true;
415      this->region = region;      this->region = region;
416      refreshManager();      refreshManager();
417        ignoreColumnClicked = false;
418    }
419    
420    void DimensionManager::onColumnClicked() {
421        printf("DimensionManager::onColumnClicked()\n");
422    
423        //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 !
424    
425        //HACK: Prevents that onColumnClicked() gets called multiple times or at times where it is not desired
426        if (ignoreColumnClicked) {
427            ignoreColumnClicked = false;
428            return;
429        }
430    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 18) || GTKMM_MAJOR_VERSION > 2
431        // prevents app to crash if this dialog is closed
432        if (!get_visible())
433            return;
434    #else
435    # warning Your GTKMM version is too old; dimension manager dialog might crash when changing a dimension type !
436    #endif
437    
438    #if (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 3
439        if (!is_visible()) return;
440    #endif
441    
442        Gtk::TreeModel::Path path;
443        Gtk::TreeViewColumn* focus_column;
444        treeView.get_cursor(path, focus_column);
445        //const int row = path[0];
446        if (focus_column == treeView.get_column(0)) {
447            Gtk::TreeModel::iterator it = treeView.get_model()->get_iter(path);
448            if (!it) return;
449            Gtk::TreeModel::Row row = *it;
450            gig::dimension_t oldType = row[tableModel.m_type];
451    
452            Gtk::Dialog dialog(_("Change Dimension"), true /*modal*/);
453            int oldTypeIndex = -1;
454            Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
455            for (int i = 0x01, count = 0; i < 0xff; i++) {
456                Glib::ustring sType =
457                    dimTypeAsString(static_cast<gig::dimension_t>(i));
458                if (i == oldType) oldTypeIndex = count;
459                if (sType.find("Unknown") != 0) {
460                    Gtk::TreeModel::Row row = *(refComboModel->append());
461                    row[comboModel.m_type_id]   = i;
462                    row[comboModel.m_type_name] = sType;
463                    count++;
464                }
465            }
466    #if USE_GTKMM_GRID
467            Gtk::Grid table;
468    #else
469            Gtk::Table table(1, 2);
470    #endif
471            Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
472            Gtk::ComboBox comboDimType;
473            comboDimType.set_model(refComboModel);
474            comboDimType.pack_start(comboModel.m_type_id);
475            comboDimType.pack_start(comboModel.m_type_name);
476            table.attach(labelDimType, 0, 1, 0, 1);
477            table.attach(comboDimType, 1, 2, 0, 1);
478    #if USE_GTKMM_BOX
479            dialog.get_content_area()->pack_start(table);
480    #else
481            dialog.get_vbox()->pack_start(table);
482    #endif
483    
484    #if HAS_GTKMM_STOCK
485            dialog.add_button(Gtk::Stock::OK, 0);
486            dialog.add_button(Gtk::Stock::CANCEL, 1);
487    #else
488            dialog.add_button(_("_OK"), 0);
489            dialog.add_button(_("_Cancel"), 1);
490    #endif
491    #if HAS_GTKMM_SHOW_ALL_CHILDREN
492            dialog.show_all_children();
493    #endif
494            
495            comboDimType.set_active(oldTypeIndex);
496    
497            if (!dialog.run()) { // OK selected ...
498                ignoreColumnClicked = true;
499                Gtk::TreeModel::iterator iterType = comboDimType.get_active();
500                if (!iterType) return;
501                Gtk::TreeModel::Row rowType = *iterType;
502                if (!rowType) return;
503                int iTypeID = rowType[comboModel.m_type_id];
504                gig::dimension_t newType = static_cast<gig::dimension_t>(iTypeID);
505                if (newType == oldType) return;
506                //printf("change 0x%x -> 0x%x\n", oldType, newType);
507    
508                // assemble the list of regions where the selected dimension type
509                // shall be changed
510                std::vector<gig::Region*> vRegions;
511                if (allRegions()) {
512                    gig::Instrument* instr = (gig::Instrument*)region->GetParent();
513                    for (gig::Region* rgn = instr->GetFirstRegion(); rgn; rgn = instr->GetNextRegion()) {
514                        if (rgn->GetDimensionDefinition(oldType)) vRegions.push_back(rgn);
515                    }
516                } else vRegions.push_back(region);
517    
518                std::set<Glib::ustring> errors;
519    
520                for (uint iRgn = 0; iRgn < vRegions.size(); ++iRgn) {
521                    gig::Region* region = vRegions[iRgn];
522                    try {
523                        // notify everybody that we're going to update the region
524                        region_to_be_changed_signal.emit(region);
525                        // change the dimension type on that region
526                        region->SetDimensionType(oldType, newType);
527                        // let everybody know there was a change
528                        region_changed_signal.emit(region);
529                    } catch (RIFF::Exception e) {
530                        // notify that the changes are over (i.e. to avoid dead locks)
531                        region_changed_signal.emit(region);
532                        Glib::ustring txt = _("Could not alter dimension: ") + e.Message;
533                        if (vRegions.size() == 1) {
534                            // show error message directly
535                            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
536                            msg.run();
537                        } else {
538                            // remember error, they are shown after all regions have been processed
539                            errors.insert(txt);
540                        }
541                    }
542                }
543                // update all GUI elements
544                refreshManager();
545    
546                if (!errors.empty()) {
547                    Glib::ustring txt = _(
548                        "The following errors occurred while trying to change the dimension type on all regions:"
549                    );
550                    txt += "\n\n";
551                    for (std::set<Glib::ustring>::const_iterator it = errors.begin();
552                        it != errors.end(); ++it)
553                    {
554                        txt += "-> " + *it + "\n";
555                    }
556                    txt += "\n";
557                    txt += _(
558                        "You might also want to check the console for further warnings and "
559                        "error messages."
560                    );
561                    Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
562                    msg.run();
563                }
564            }
565        } else if (focus_column == treeView.get_column(1) || focus_column == treeView.get_column(2)) {
566            Glib::ustring txt = _("Right-click on a specific dimension zone of the dimension region selector to delete or split that particular dimension zone!");
567            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_INFO);
568            msg.run();
569        }
570  }  }
571    
572  void DimensionManager::addDimension() {  void DimensionManager::addDimension() {
# Line 386  void DimensionManager::addDimension() { Line 582  void DimensionManager::addDimension() {
582              row[comboModel.m_type_name] = sType;              row[comboModel.m_type_name] = sType;
583          }          }
584      }      }
585    #if USE_GTKMM_GRID
586        Gtk::Grid table;
587    #else
588      Gtk::Table table(2, 2);      Gtk::Table table(2, 2);
589    #endif
590      Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);      Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
591      Gtk::ComboBox comboDimType;      Gtk::ComboBox comboDimType;
592      comboDimType.set_model(refComboModel);      comboDimType.set_model(refComboModel);
593      comboDimType.pack_start(comboModel.m_type_id);      comboDimType.pack_start(comboModel.m_type_id);
594      comboDimType.pack_start(comboModel.m_type_name);      comboDimType.pack_start(comboModel.m_type_name);
595      Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);      Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
596    #if USE_GTKMM_GRID
597        table.attach(labelDimType, 0, 0);
598        table.attach(comboDimType, 1, 0);
599        table.attach(labelZones, 0, 1);
600    #else
601      table.attach(labelDimType, 0, 1, 0, 1);      table.attach(labelDimType, 0, 1, 0, 1);
602      table.attach(comboDimType, 1, 2, 0, 1);      table.attach(comboDimType, 1, 2, 0, 1);
603      table.attach(labelZones, 0, 1, 1, 2);      table.attach(labelZones, 0, 1, 1, 2);
604    #endif
605    
606    #if USE_GTKMM_BOX
607        dialog.get_content_area()->pack_start(table);
608    #else
609      dialog.get_vbox()->pack_start(table);      dialog.get_vbox()->pack_start(table);
610    #endif
611    
612      // number of zones: use a combo box with fix values for gig      // number of zones: use a combo box with fix values for gig
613      // v2 and a spin button for v3      // v2 and a spin button for v3
# Line 426  void DimensionManager::addDimension() { Line 637  void DimensionManager::addDimension() {
637          table.attach(spinZones, 1, 2, 1, 2);          table.attach(spinZones, 1, 2, 1, 2);
638      }      }
639    
640    #if HAS_GTKMM_STOCK
641      dialog.add_button(Gtk::Stock::OK, 0);      dialog.add_button(Gtk::Stock::OK, 0);
642      dialog.add_button(Gtk::Stock::CANCEL, 1);      dialog.add_button(Gtk::Stock::CANCEL, 1);
643    #else
644        dialog.add_button(_("_OK"), 0);
645        dialog.add_button(_("_Cancel"), 1);
646    #endif
647    #if HAS_GTKMM_SHOW_ALL_CHILDREN
648      dialog.show_all_children();      dialog.show_all_children();
649    #endif
650    
651      if (!dialog.run()) { // OK selected ...      if (!dialog.run()) { // OK selected ...
652          Gtk::TreeModel::iterator iterType = comboDimType.get_active();          Gtk::TreeModel::iterator iterType = comboDimType.get_active();

Legend:
Removed from v.2562  
changed lines
  Added in v.3364

  ViewVC Help
Powered by ViewVC