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

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

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

revision 3089 by schoenebeck, Sun Jan 15 19:18:39 2017 UTC revision 3783 by schoenebeck, Sat May 30 00:14:27 2020 UTC
# Line 1  Line 1 
1  /*  /*
2      Copyright (c) 2014-2017 Christian Schoenebeck      Copyright (c) 2014-2020 Christian Schoenebeck
3        
4      This file is part of "gigedit" and released under the terms of the      This file is part of "gigedit" and released under the terms of the
5      GNU General Public License version 2.      GNU General Public License version 2.
6  */  */
7    
8    #include "global.h"
9  #include "CombineInstrumentsDialog.h"  #include "CombineInstrumentsDialog.h"
10    
11  // enable this for debug messages being printed while combining the instruments  // enable this for debug messages being printed while combining the instruments
12  #define DEBUG_COMBINE_INSTRUMENTS 0  #define DEBUG_COMBINE_INSTRUMENTS 0
13    
 #include "global.h"  
14  #include "compat.h"  #include "compat.h"
15    
16  #include <set>  #include <set>
# Line 20  Line 20 
20  #include <string.h>  #include <string.h>
21    
22  #include <glibmm/ustring.h>  #include <glibmm/ustring.h>
23    #if HAS_GTKMM_STOCK
24    # include <gtkmm/stock.h>
25    #endif
26  #include <gtkmm/messagedialog.h>  #include <gtkmm/messagedialog.h>
27  #include <gtkmm/label.h>  #include <gtkmm/label.h>
28    #include <gtk/gtkwidget.h> // for gtk_widget_modify_*()
29    
 Glib::ustring gig_to_utf8(const gig::String& gig_string);  
30  Glib::ustring dimTypeAsString(gig::dimension_t d);  Glib::ustring dimTypeAsString(gig::dimension_t d);
31    
32  typedef std::vector< std::pair<gig::Instrument*, gig::Region*> > OrderedRegionGroup;  typedef std::vector< std::pair<gig::Instrument*, gig::Region*> > OrderedRegionGroup;
# Line 214  static RegionGroups groupByRegionInterse Line 217  static RegionGroups groupByRegionInterse
217   *   *
218   * Takes a planned new region (@a regionGroup) as argument and identifies which   * Takes a planned new region (@a regionGroup) as argument and identifies which
219   * precise dimensions would have to be created for that new region, along with   * precise dimensions would have to be created for that new region, along with
220   * the amount of dimension zones and their precise individual zone sizes.   * the amount of dimension zones.
221   *   *
222   * @param regionGroup - planned new region for a new instrument   * @param regionGroup - planned new region for a new instrument
223   * @returns set of dimensions that shall be created for the given planned region   * @returns set of dimensions that shall be created for the given planned region
# Line 222  static RegionGroups groupByRegionInterse Line 225  static RegionGroups groupByRegionInterse
225  static Dimensions getDimensionsForRegionGroup(RegionGroup& regionGroup) {  static Dimensions getDimensionsForRegionGroup(RegionGroup& regionGroup) {
226      std::map<gig::dimension_t, std::set<int> > dimUpperLimits;      std::map<gig::dimension_t, std::set<int> > dimUpperLimits;
227    
228        #if DEBUG_COMBINE_INSTRUMENTS
229        printf("dimUpperLimits = {\n");
230        #endif
231      // collect all dimension region zones' upper limits      // collect all dimension region zones' upper limits
232      for (RegionGroup::iterator it = regionGroup.begin();      for (RegionGroup::iterator it = regionGroup.begin();
233           it != regionGroup.end(); ++it)           it != regionGroup.end(); ++it)
# Line 230  static Dimensions getDimensionsForRegion Line 236  static Dimensions getDimensionsForRegion
236          int previousBits = 0;          int previousBits = 0;
237          for (uint d = 0; d < rgn->Dimensions; ++d) {          for (uint d = 0; d < rgn->Dimensions; ++d) {
238              const gig::dimension_def_t& def = rgn->pDimensionDefinitions[d];              const gig::dimension_def_t& def = rgn->pDimensionDefinitions[d];
239                #if DEBUG_COMBINE_INSTRUMENTS
240                printf("\t[rgn=%p,dim=%#x] = {", rgn, def.dimension);
241                #endif
242              for (uint z = 0; z < def.zones; ++z) {              for (uint z = 0; z < def.zones; ++z) {
243                  int dr = z << previousBits;                  int dr = z << previousBits;
244                  gig::DimensionRegion* dimRgn = rgn->pDimensionRegions[dr];                  gig::DimensionRegion* dimRgn = rgn->pDimensionRegions[dr];
245                  // Store the individual dimension zone sizes (or actually their                  // NOTE: Originally this function collected dimensions' upper
246                  // upper limits here) for each dimension.                  // limits. However that caused combined instruments (e.g. with
247                  // HACK: Note that the velocity dimension is specially handled                  // unequal dimension zone counts, not being a power of two) to
248                  // here. Instead of taking over custom velocity split sizes                  // end up having too many dimension zones and those extra zones
249                  // here, only a bogus number (zone index number) is stored for                  // containing no sample. For that reason we simply collect the
250                  // each velocity zone, that way only the maxiumum amount of                  // required amount of output dimension zones here now instead.
251                  // velocity splits of all regions is stored here, and when their                  const int upperLimit =
252                  // individual DimensionRegions are finally copied (later), the  /*
                 // individual velocity split size are copied by that.  
                 dimUpperLimits[def.dimension].insert(  
253                      (def.dimension == gig::dimension_velocity) ?                      (def.dimension == gig::dimension_velocity) ?
254                          z : (def.split_type == gig::split_type_bit) ?                          z : (def.split_type == gig::split_type_bit) ?
255                              ((z+1) * 128/def.zones - 1) : dimRgn->DimensionUpperLimits[dr]                              ((z+1) * 128/def.zones - 1) : dimRgn->DimensionUpperLimits[dr];
256                  );   */
257                        z;
258                    #if DEBUG_COMBINE_INSTRUMENTS
259                    printf(" %d,", upperLimit);
260                    #endif
261                    dimUpperLimits[def.dimension].insert(upperLimit);
262              }              }
263              previousBits += def.bits;              previousBits += def.bits;
264                #if DEBUG_COMBINE_INSTRUMENTS
265                printf(" }\n");
266                #endif
267          }          }
268      }      }
269        #if DEBUG_COMBINE_INSTRUMENTS
270        printf("}\n");
271        #endif
272    
273      // convert upper limit set to range vector      // convert upper limit set to range vector
274      Dimensions dims;      Dimensions dims;
275        #if DEBUG_COMBINE_INSTRUMENTS
276        printf("dims = {\n");
277        #endif
278      for (std::map<gig::dimension_t, std::set<int> >::const_iterator it = dimUpperLimits.begin();      for (std::map<gig::dimension_t, std::set<int> >::const_iterator it = dimUpperLimits.begin();
279           it != dimUpperLimits.end(); ++it)           it != dimUpperLimits.end(); ++it)
280      {      {
281          gig::dimension_t type = it->first;          gig::dimension_t type = it->first;
282            #if DEBUG_COMBINE_INSTRUMENTS
283            printf("\t[dim=%#x] = {", type);
284            #endif
285          int iLow = 0;          int iLow = 0;
286          for (std::set<int>::const_iterator itNums = it->second.begin();          for (std::set<int>::const_iterator itNums = it->second.begin();
287               itNums != it->second.end(); ++itNums)               itNums != it->second.end(); ++itNums)
# Line 265  static Dimensions getDimensionsForRegion Line 289  static Dimensions getDimensionsForRegion
289              const int iUpperLimit = *itNums;              const int iUpperLimit = *itNums;
290              DLS::range_t range = { uint16_t(iLow), uint16_t(iUpperLimit) };              DLS::range_t range = { uint16_t(iLow), uint16_t(iUpperLimit) };
291              dims[type].push_back(range);              dims[type].push_back(range);
292                #if DEBUG_COMBINE_INSTRUMENTS
293                printf(" %d..%d,", iLow, iUpperLimit);
294                #endif
295              iLow = iUpperLimit + 1;              iLow = iUpperLimit + 1;
296          }          }
297            #if DEBUG_COMBINE_INSTRUMENTS
298            printf(" }\n");
299            #endif
300      }      }
301        #if DEBUG_COMBINE_INSTRUMENTS
302        printf("}\n");
303        #endif
304    
305      return dims;      return dims;
306  }  }
# Line 284  static void fillDimValues(uint* values/* Line 317  static void fillDimValues(uint* values/*
317          else if (iDimIndex < 0) continue;          else if (iDimIndex < 0) continue;
318          values[iDimIndex] = it->second;          values[iDimIndex] = it->second;
319          #if DEBUG_COMBINE_INSTRUMENTS          #if DEBUG_COMBINE_INSTRUMENTS
320          printf("%x=%d, ", type, it->second);          printf("0x%x=%d, ", type, it->second);
321          #endif          #endif
322      }      }
323      #if DEBUG_COMBINE_INSTRUMENTS      #if DEBUG_COMBINE_INSTRUMENTS
# Line 379  struct CopyAssignSchedEntry { Line 412  struct CopyAssignSchedEntry {
412  };  };
413  typedef std::vector<CopyAssignSchedEntry> CopyAssignSchedule;  typedef std::vector<CopyAssignSchedEntry> CopyAssignSchedule;
414    
415    /** @brief Constrain @a dimCase according to @a rgn's dimension zones.
416     *
417     * To avoid @a dimCase being an invalid dimension region selection on @a rgn,
418     * this function automatically wraps (if required) the individual dimension case
419     * entries according to region's actual amount of dimension zones.
420     *
421     * @param dimCase - dimension case to be potentially corrected
422     * @param rgn - the region upon @a dimCase shall be corrected for
423     */
424    static void wrapDimCase(DimensionCase& dimCase, gig::Region* rgn) {
425        for (auto& it : dimCase) {
426            gig::dimension_def_t* def = rgn->GetDimensionDefinition(it.first);
427            const int zones = (def) ? def->zones : 1;
428            it.second %= zones;
429        }
430    }
431    
432  /** @brief Schedule copying DimensionRegions from source Region to target Region.  /** @brief Schedule copying DimensionRegions from source Region to target Region.
433   *   *
434   * Schedules copying the entire articulation informations (including sample   * Schedules copying the entire articulation informations (including sample
# Line 423  static void scheduleCopyDimensionRegions Line 473  static void scheduleCopyDimensionRegions
473          uint dstDimValues[8] = {};          uint dstDimValues[8] = {};
474          DimensionCase srcDimCase = dimCase;          DimensionCase srcDimCase = dimCase;
475          DimensionCase dstDimCase = dimCase;          DimensionCase dstDimCase = dimCase;
476    
477            // source might have less zones than destination, so to prevent output
478            // instrument ending up with NULL samples in some of the dimension
479            // zones, wrap here the source zone according to the amount of zones the
480            // source really has
481            wrapDimCase(srcDimCase, inRgn);
482    
483          srcDimCase[mainDim] = iSrcMainBit;          srcDimCase[mainDim] = iSrcMainBit;
484          dstDimCase[mainDim] = iDstMainBit;          dstDimCase[mainDim] = iDstMainBit;
485    
# Line 781  static void combineInstruments(std::vect Line 838  static void combineInstruments(std::vect
838  CombineInstrumentsDialog::CombineInstrumentsDialog(Gtk::Window& parent, gig::File* gig)  CombineInstrumentsDialog::CombineInstrumentsDialog(Gtk::Window& parent, gig::File* gig)
839      : ManagedDialog(_("Combine Instruments"), parent, true),      : ManagedDialog(_("Combine Instruments"), parent, true),
840        m_gig(gig), m_fileWasChanged(false), m_newCombinedInstrument(NULL),        m_gig(gig), m_fileWasChanged(false), m_newCombinedInstrument(NULL),
841    #if HAS_GTKMM_STOCK
842          m_cancelButton(Gtk::Stock::CANCEL), m_OKButton(Gtk::Stock::OK),
843    #else
844        m_cancelButton(_("_Cancel"), true), m_OKButton(_("_OK"), true),        m_cancelButton(_("_Cancel"), true), m_OKButton(_("_OK"), true),
845        m_descriptionLabel(), m_tableDimCombo(2, 2), m_comboDimType(),  #endif
846          m_descriptionLabel(),
847    #if USE_GTKMM_GRID
848          m_tableDimCombo(),
849    #else
850          m_tableDimCombo(2, 2),
851    #endif
852          m_comboDimType(),
853        m_labelDimType(Glib::ustring(_("Combine by Dimension:")) + "  ", Gtk::ALIGN_END)        m_labelDimType(Glib::ustring(_("Combine by Dimension:")) + "  ", Gtk::ALIGN_END)
854  {  {
855        if (!Settings::singleton()->autoRestoreWindowDimension) {
856            set_default_size(500, 600);
857            set_position(Gtk::WIN_POS_MOUSE);
858        }
859    
860      m_scrolledWindow.add(m_treeView);      m_scrolledWindow.add(m_treeView);
861      m_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);      m_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
862    
863    #if USE_GTKMM_BOX
864        get_content_area()->pack_start(m_descriptionLabel, Gtk::PACK_SHRINK);
865        get_content_area()->pack_start(m_tableDimCombo, Gtk::PACK_SHRINK);
866        get_content_area()->pack_start(m_scrolledWindow);
867        get_content_area()->pack_start(m_labelOrder, Gtk::PACK_SHRINK);
868        get_content_area()->pack_start(m_iconView, Gtk::PACK_SHRINK);
869        get_content_area()->pack_start(m_buttonBox, Gtk::PACK_SHRINK);
870    #else
871      get_vbox()->pack_start(m_descriptionLabel, Gtk::PACK_SHRINK);      get_vbox()->pack_start(m_descriptionLabel, Gtk::PACK_SHRINK);
872      get_vbox()->pack_start(m_tableDimCombo, Gtk::PACK_SHRINK);      get_vbox()->pack_start(m_tableDimCombo, Gtk::PACK_SHRINK);
873      get_vbox()->pack_start(m_scrolledWindow);      get_vbox()->pack_start(m_scrolledWindow);
874        get_vbox()->pack_start(m_labelOrder, Gtk::PACK_SHRINK);
875        get_vbox()->pack_start(m_iconView, Gtk::PACK_SHRINK);
876      get_vbox()->pack_start(m_buttonBox, Gtk::PACK_SHRINK);      get_vbox()->pack_start(m_buttonBox, Gtk::PACK_SHRINK);
877    #endif
878    
879  #if GTKMM_MAJOR_VERSION >= 3  #if GTKMM_MAJOR_VERSION >= 3
880      m_descriptionLabel.set_line_wrap();      m_descriptionLabel.set_line_wrap();
# Line 835  CombineInstrumentsDialog::CombineInstrum Line 918  CombineInstrumentsDialog::CombineInstrum
918          "Use SHIFT + left click or CTRL + left click to select the instruments "          "Use SHIFT + left click or CTRL + left click to select the instruments "
919          "you want to combine."          "you want to combine."
920      ));      ));
921      m_treeView.append_column("Instrument", m_columns.m_col_name);      m_treeView.append_column(_("Nr"), m_columns.m_col_index);
922      m_treeView.set_headers_visible(false);      m_treeView.append_column(_("Instrument"), m_columns.m_col_name);
923        m_treeView.set_headers_visible(true);
924      m_treeView.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);      m_treeView.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
925      m_treeView.get_selection()->signal_changed().connect(      m_treeView.get_selection()->signal_changed().connect(
926          sigc::mem_fun(*this, &CombineInstrumentsDialog::onSelectionChanged)          sigc::mem_fun(*this, &CombineInstrumentsDialog::onSelectionChanged)
# Line 861  CombineInstrumentsDialog::CombineInstrum Line 945  CombineInstrumentsDialog::CombineInstrum
945          Glib::ustring name(gig_to_utf8(instr->pInfo->Name));          Glib::ustring name(gig_to_utf8(instr->pInfo->Name));
946          Gtk::TreeModel::iterator iter = m_refTreeModel->append();          Gtk::TreeModel::iterator iter = m_refTreeModel->append();
947          Gtk::TreeModel::Row row = *iter;          Gtk::TreeModel::Row row = *iter;
948            row[m_columns.m_col_index] = i;
949          row[m_columns.m_col_name] = name;          row[m_columns.m_col_name] = name;
950          row[m_columns.m_col_instr] = instr;          row[m_columns.m_col_instr] = instr;
951      }      }
952    
953        m_refOrderModel = Gtk::ListStore::create(m_orderColumns);
954        m_iconView.set_model(m_refOrderModel);
955        m_iconView.set_tooltip_text(_("Use drag & drop to change the order."));
956        m_iconView.set_markup_column(1);
957        m_iconView.set_selection_mode(Gtk::SELECTION_SINGLE);
958        // force background to retain white also on selections
959        // (this also fixes a bug with GTK 2 which often causes visibility issue
960        //  with the text of the selected item)
961        {
962    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
963            Gdk::Color white;
964    #else
965            Gdk::RGBA white;
966    #endif
967            white.set("#ffffff");
968            GtkWidget* widget = (GtkWidget*) m_iconView.gobj();
969    #if GTK_MAJOR_VERSION < 3
970            gtk_widget_modify_base(widget, GTK_STATE_SELECTED, white.gobj());
971            gtk_widget_modify_base(widget, GTK_STATE_ACTIVE, white.gobj());
972            gtk_widget_modify_bg(widget, GTK_STATE_SELECTED, white.gobj());
973            gtk_widget_modify_bg(widget, GTK_STATE_ACTIVE, white.gobj());
974    #endif
975        }
976    
977        m_labelOrder.set_text(_("Order of the instruments to be combined:"));
978    
979        // establish drag&drop within the instrument tree view, allowing to reorder
980        // the sequence of instruments within the gig file
981        {
982            std::vector<Gtk::TargetEntry> drag_target_instrument;
983            drag_target_instrument.push_back(Gtk::TargetEntry("gig::Instrument"));
984            m_iconView.drag_source_set(drag_target_instrument);
985            m_iconView.drag_dest_set(drag_target_instrument);
986            m_iconView.signal_drag_begin().connect(
987                sigc::mem_fun(*this, &CombineInstrumentsDialog::on_order_drag_begin)
988            );
989            m_iconView.signal_drag_data_get().connect(
990                sigc::mem_fun(*this, &CombineInstrumentsDialog::on_order_drag_data_get)
991            );
992            m_iconView.signal_drag_data_received().connect(
993                sigc::mem_fun(*this, &CombineInstrumentsDialog::on_order_drop_drag_data_received)
994            );
995        }
996    
997      m_buttonBox.set_layout(Gtk::BUTTONBOX_END);      m_buttonBox.set_layout(Gtk::BUTTONBOX_END);
998    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24)
999        m_buttonBox.set_margin(5);
1000    #else
1001      m_buttonBox.set_border_width(5);      m_buttonBox.set_border_width(5);
1002    #endif
1003      m_buttonBox.pack_start(m_cancelButton, Gtk::PACK_SHRINK);      m_buttonBox.pack_start(m_cancelButton, Gtk::PACK_SHRINK);
1004      m_buttonBox.pack_start(m_OKButton, Gtk::PACK_SHRINK);      m_buttonBox.pack_start(m_OKButton, Gtk::PACK_SHRINK);
1005      m_buttonBox.show();      m_buttonBox.show();
# Line 883  CombineInstrumentsDialog::CombineInstrum Line 1016  CombineInstrumentsDialog::CombineInstrum
1016          sigc::mem_fun(*this, &CombineInstrumentsDialog::combineSelectedInstruments)          sigc::mem_fun(*this, &CombineInstrumentsDialog::combineSelectedInstruments)
1017      );      );
1018    
1019    #if HAS_GTKMM_SHOW_ALL_CHILDREN
1020      show_all_children();      show_all_children();
1021    #endif
1022    
1023        Settings::singleton()->showTooltips.get_proxy().signal_changed().connect(
1024            sigc::mem_fun(*this, &CombineInstrumentsDialog::on_show_tooltips_changed)
1025        );
1026        on_show_tooltips_changed();
1027    
1028      // show a warning to user if he uses a .gig in v2 format      // show a warning to user if he uses a .gig in v2 format
1029      if (gig->pVersion->major < 3) {      if (gig->pVersion->major < 3) {
# Line 896  CombineInstrumentsDialog::CombineInstrum Line 1036  CombineInstrumentsDialog::CombineInstrum
1036          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_WARNING);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_WARNING);
1037          msg.run();          msg.run();
1038      }      }
1039    
1040        // OK button should have focus by default for quick combining with Return key
1041        m_OKButton.grab_focus();
1042    }
1043    
1044    void CombineInstrumentsDialog::on_order_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
1045    {
1046        #if DEBUG_COMBINE_INSTRUMENTS
1047        printf("Drag begin\n");
1048        #endif
1049        first_call_to_drag_data_get = true;
1050    }
1051    
1052    void CombineInstrumentsDialog::on_order_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context,
1053                                                           Gtk::SelectionData& selection_data, guint, guint)
1054    {
1055        #if DEBUG_COMBINE_INSTRUMENTS
1056        printf("Drag data get\n");
1057        #endif
1058        if (!first_call_to_drag_data_get) return;
1059        first_call_to_drag_data_get = false;
1060    
1061        // get selected source instrument
1062        gig::Instrument* src = NULL;
1063        {
1064            std::vector<Gtk::TreeModel::Path> rows = m_iconView.get_selected_items();
1065            if (!rows.empty()) {
1066                Gtk::TreeModel::iterator it = m_refOrderModel->get_iter(rows[0]);
1067                if (it) {
1068                    Gtk::TreeModel::Row row = *it;
1069                    src = row[m_orderColumns.m_col_instr];
1070                }
1071            }
1072        }
1073        if (!src) {
1074            printf("Drag data get: !src\n");
1075            return;
1076        }
1077        #if DEBUG_COMBINE_INSTRUMENTS
1078        printf("src=%ld\n", (size_t)src);
1079        #endif
1080    
1081        // pass the source gig::Instrument as pointer
1082        selection_data.set(selection_data.get_target(), 0/*unused*/, (const guchar*)&src,
1083                           sizeof(src)/*length of data in bytes*/);
1084    }
1085    
1086    void CombineInstrumentsDialog::on_order_drop_drag_data_received(
1087        const Glib::RefPtr<Gdk::DragContext>& context, int x, int y,
1088        const Gtk::SelectionData& selection_data, guint, guint time)
1089    {
1090        #if DEBUG_COMBINE_INSTRUMENTS
1091        printf("Drag data received\n");
1092        #endif
1093        if (!selection_data.get_data()) {
1094            printf("selection_data.get_data() == NULL\n");
1095            return;
1096        }
1097    
1098        gig::Instrument* src = *((gig::Instrument**) selection_data.get_data());
1099        if (!src || selection_data.get_length() != sizeof(gig::Instrument*)) {
1100            printf("!src\n");
1101            return;
1102        }
1103        #if DEBUG_COMBINE_INSTRUMENTS
1104        printf("src=%ld\n", (size_t)src);
1105        #endif
1106    
1107        gig::Instrument* dst = NULL;
1108        {
1109            Gtk::TreeModel::Path path = m_iconView.get_path_at_pos(x, y);
1110            if (!path) return;
1111    
1112            Gtk::TreeModel::iterator iter = m_refOrderModel->get_iter(path);
1113            if (!iter) return;
1114            Gtk::TreeModel::Row row = *iter;
1115            dst = row[m_orderColumns.m_col_instr];
1116        }
1117        if (!dst) {
1118            printf("!dst\n");
1119            return;
1120        }
1121    
1122        #if DEBUG_COMBINE_INSTRUMENTS
1123        printf("dragdrop received src='%s' dst='%s'\n", src->pInfo->Name.c_str(), dst->pInfo->Name.c_str());
1124        #endif
1125    
1126        // swap the two items
1127        typedef Gtk::TreeModel::Children Children;
1128        Children children = m_refOrderModel->children();
1129        Children::iterator itSrc, itDst;
1130        int i = 0, iSrc = -1, iDst = -1;
1131        for (Children::iterator iter = children.begin();
1132             iter != children.end(); ++iter, ++i)
1133        {
1134            Gtk::TreeModel::Row row = *iter;
1135            if (row[m_orderColumns.m_col_instr] == src) {
1136                itSrc = iter;
1137                iSrc  = i;
1138            } else if (row[m_orderColumns.m_col_instr] == dst) {
1139                itDst = iter;
1140                iDst  = i;
1141            }
1142        }
1143        if (itSrc && itDst) {
1144            // swap elements
1145            m_refOrderModel->iter_swap(itSrc, itDst);
1146            // update markup
1147            Gtk::TreeModel::Row rowSrc = *itSrc;
1148            Gtk::TreeModel::Row rowDst = *itDst;
1149            {
1150                Glib::ustring name = rowSrc[m_orderColumns.m_col_name];
1151                Glib::ustring markup =
1152                    "<span foreground='black' background='white'>" + ToString(iDst+1) + ".</span>\n<span foreground='green' background='white'>" + name + "</span>";
1153                rowSrc[m_orderColumns.m_col_markup] = markup;
1154            }
1155            {
1156                Glib::ustring name = rowDst[m_orderColumns.m_col_name];
1157                Glib::ustring markup =
1158                    "<span foreground='black' background='white'>" + ToString(iSrc+1) + ".</span>\n<span foreground='green' background='white'>" + name + "</span>";
1159                rowDst[m_orderColumns.m_col_markup] = markup;
1160            }
1161        }
1162    }
1163    
1164    void CombineInstrumentsDialog::setSelectedInstruments(const std::set<int>& instrumentIndeces) {
1165        typedef Gtk::TreeModel::Children Children;
1166        Children children = m_refTreeModel->children();
1167        for (Children::iterator iter = children.begin();
1168             iter != children.end(); ++iter)
1169        {
1170            Gtk::TreeModel::Row row = *iter;
1171            int index = row[m_columns.m_col_index];
1172            if (instrumentIndeces.count(index))
1173                m_treeView.get_selection()->select(iter);
1174        }
1175        // hack: OK button lost focus after doing the above, it should have focus by default for quick combining with Return key
1176        m_OKButton.grab_focus();
1177  }  }
1178    
1179  void CombineInstrumentsDialog::combineSelectedInstruments() {  void CombineInstrumentsDialog::combineSelectedInstruments() {
1180      std::vector<gig::Instrument*> instruments;      std::vector<gig::Instrument*> instruments;
1181      std::vector<Gtk::TreeModel::Path> v = m_treeView.get_selection()->get_selected_rows();      {
1182      for (uint i = 0; i < v.size(); ++i) {          typedef Gtk::TreeModel::Children Children;
1183          Gtk::TreeModel::iterator it = m_refTreeModel->get_iter(v[i]);          int i = 0;
1184          Gtk::TreeModel::Row row = *it;          Children selection = m_refOrderModel->children();
1185          Glib::ustring name = row[m_columns.m_col_name];          for (Children::iterator it = selection.begin();
1186          gig::Instrument* instrument = row[m_columns.m_col_instr];               it != selection.end(); ++it, ++i)
1187          #if DEBUG_COMBINE_INSTRUMENTS          {
1188          printf("Selection '%s' 0x%lx\n\n", name.c_str(), int64_t((void*)instrument));              Gtk::TreeModel::Row row = *it;
1189          #endif              Glib::ustring name = row[m_orderColumns.m_col_name];
1190          instruments.push_back(instrument);              gig::Instrument* instrument = row[m_orderColumns.m_col_instr];
1191                #if DEBUG_COMBINE_INSTRUMENTS
1192                printf("Selection %d. '%s' %p\n\n", (i+1), name.c_str(), instrument);
1193                #endif
1194                instruments.push_back(instrument);
1195            }
1196      }      }
1197    
1198      g_warnings.clear();      g_warnings.clear();
# Line 926  void CombineInstrumentsDialog::combineSe Line 1209  void CombineInstrumentsDialog::combineSe
1209              mainDimension = static_cast<gig::dimension_t>(iTypeID);              mainDimension = static_cast<gig::dimension_t>(iTypeID);
1210          }          }
1211    
1212          // now start the actual cobination task ...          // now start the actual combination task ...
1213          combineInstruments(instruments, m_gig, m_newCombinedInstrument, mainDimension);          combineInstruments(instruments, m_gig, m_newCombinedInstrument, mainDimension);
1214      } catch (RIFF::Exception e) {;      } catch (RIFF::Exception e) {;
1215          Gtk::MessageDialog msg(*this, e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, e.Message, false, Gtk::MESSAGE_ERROR);
# Line 966  void CombineInstrumentsDialog::combineSe Line 1249  void CombineInstrumentsDialog::combineSe
1249  void CombineInstrumentsDialog::onSelectionChanged() {  void CombineInstrumentsDialog::onSelectionChanged() {
1250      std::vector<Gtk::TreeModel::Path> v = m_treeView.get_selection()->get_selected_rows();      std::vector<Gtk::TreeModel::Path> v = m_treeView.get_selection()->get_selected_rows();
1251      m_OKButton.set_sensitive(v.size() >= 2);      m_OKButton.set_sensitive(v.size() >= 2);
1252    
1253        typedef Gtk::TreeModel::Children Children;
1254    
1255        // update horizontal selection list (icon view) ...
1256    
1257        // remove items which are not part of the new selection anymore
1258        {
1259            Children allOrdered = m_refOrderModel->children();
1260            for (Children::iterator itOrder = allOrdered.begin();
1261                 itOrder != allOrdered.end(); )
1262            {
1263                Gtk::TreeModel::Row rowOrder = *itOrder;
1264                gig::Instrument* instr = rowOrder[m_orderColumns.m_col_instr];
1265                for (uint i = 0; i < v.size(); ++i) {
1266                    Gtk::TreeModel::iterator itSel = m_refTreeModel->get_iter(v[i]);
1267                    Gtk::TreeModel::Row rowSel = *itSel;
1268                    if (rowSel[m_columns.m_col_instr] == instr)
1269                        goto nextOrderedItem;
1270                }
1271                goto removeOrderedItem;
1272            nextOrderedItem:
1273                ++itOrder;
1274                continue;
1275            removeOrderedItem:
1276                // postfix increment here to avoid iterator invalidation
1277                m_refOrderModel->erase(itOrder++);
1278            }
1279        }
1280    
1281        // add items newly added to the selection
1282        for (uint i = 0; i < v.size(); ++i) {
1283            Gtk::TreeModel::iterator itSel = m_refTreeModel->get_iter(v[i]);
1284            Gtk::TreeModel::Row rowSel = *itSel;
1285            gig::Instrument* instr = rowSel[m_columns.m_col_instr];
1286            Children allOrdered = m_refOrderModel->children();
1287            for (Children::iterator itOrder = allOrdered.begin();
1288                 itOrder != allOrdered.end(); ++itOrder)
1289            {
1290                Gtk::TreeModel::Row rowOrder = *itOrder;
1291                if (rowOrder[m_orderColumns.m_col_instr] == instr)
1292                    goto nextSelectionItem;
1293            }
1294            goto addNewSelectionItem;
1295        nextSelectionItem:
1296            continue;
1297        addNewSelectionItem:
1298            Glib::ustring name = gig_to_utf8(instr->pInfo->Name);
1299            Gtk::TreeModel::iterator iterOrder = m_refOrderModel->append();
1300            Gtk::TreeModel::Row rowOrder = *iterOrder;
1301            rowOrder[m_orderColumns.m_col_name] = name;
1302            rowOrder[m_orderColumns.m_col_instr] = instr;
1303        }
1304    
1305        // update markup
1306        {
1307            int i = 0;
1308            Children allOrdered = m_refOrderModel->children();
1309            for (Children::iterator itOrder = allOrdered.begin();
1310                 itOrder != allOrdered.end(); ++itOrder, ++i)
1311            {
1312                Gtk::TreeModel::Row rowOrder = *itOrder;
1313                Glib::ustring name = rowOrder[m_orderColumns.m_col_name];
1314                Glib::ustring markup =
1315                    "<span foreground='black' background='white'>" + ToString(i+1) + ".</span>\n<span foreground='green' background='white'>" + name + "</span>";
1316                rowOrder[m_orderColumns.m_col_markup] = markup;
1317            }
1318        }
1319    }
1320    
1321    void CombineInstrumentsDialog::on_show_tooltips_changed() {
1322        const bool b = Settings::singleton()->showTooltips;
1323    
1324        m_treeView.set_has_tooltip(b);
1325        m_iconView.set_has_tooltip(b);
1326    
1327        set_has_tooltip(b);
1328  }  }
1329    
1330  bool CombineInstrumentsDialog::fileWasChanged() const {  bool CombineInstrumentsDialog::fileWasChanged() const {

Legend:
Removed from v.3089  
changed lines
  Added in v.3783

  ViewVC Help
Powered by ViewVC