/[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 3299 by schoenebeck, Sun Jul 9 12:44:59 2017 UTC revision 3762 by schoenebeck, Wed Apr 1 17:43:49 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  */  */
# Line 20  Line 20 
20  #include <string.h>  #include <string.h>
21    
22  #include <glibmm/ustring.h>  #include <glibmm/ustring.h>
23  #include <gtkmm/stock.h>  #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    
30  Glib::ustring dimTypeAsString(gig::dimension_t d);  Glib::ustring dimTypeAsString(gig::dimension_t d);
31    
# Line 781  static void combineInstruments(std::vect Line 784  static void combineInstruments(std::vect
784  CombineInstrumentsDialog::CombineInstrumentsDialog(Gtk::Window& parent, gig::File* gig)  CombineInstrumentsDialog::CombineInstrumentsDialog(Gtk::Window& parent, gig::File* gig)
785      : ManagedDialog(_("Combine Instruments"), parent, true),      : ManagedDialog(_("Combine Instruments"), parent, true),
786        m_gig(gig), m_fileWasChanged(false), m_newCombinedInstrument(NULL),        m_gig(gig), m_fileWasChanged(false), m_newCombinedInstrument(NULL),
787    #if HAS_GTKMM_STOCK
788        m_cancelButton(Gtk::Stock::CANCEL), m_OKButton(Gtk::Stock::OK),        m_cancelButton(Gtk::Stock::CANCEL), m_OKButton(Gtk::Stock::OK),
789        m_descriptionLabel(), m_tableDimCombo(2, 2), m_comboDimType(),  #else
790          m_cancelButton(_("_Cancel"), true), m_OKButton(_("_OK"), true),
791    #endif
792          m_descriptionLabel(),
793    #if USE_GTKMM_GRID
794          m_tableDimCombo(),
795    #else
796          m_tableDimCombo(2, 2),
797    #endif
798          m_comboDimType(),
799        m_labelDimType(Glib::ustring(_("Combine by Dimension:")) + "  ", Gtk::ALIGN_END)        m_labelDimType(Glib::ustring(_("Combine by Dimension:")) + "  ", Gtk::ALIGN_END)
800  {  {
801      if (!Settings::singleton()->autoRestoreWindowDimension) {      if (!Settings::singleton()->autoRestoreWindowDimension) {
# Line 793  CombineInstrumentsDialog::CombineInstrum Line 806  CombineInstrumentsDialog::CombineInstrum
806      m_scrolledWindow.add(m_treeView);      m_scrolledWindow.add(m_treeView);
807      m_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);      m_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
808    
809    #if USE_GTKMM_BOX
810        get_content_area()->pack_start(m_descriptionLabel, Gtk::PACK_SHRINK);
811        get_content_area()->pack_start(m_tableDimCombo, Gtk::PACK_SHRINK);
812        get_content_area()->pack_start(m_scrolledWindow);
813        get_content_area()->pack_start(m_labelOrder, Gtk::PACK_SHRINK);
814        get_content_area()->pack_start(m_iconView, Gtk::PACK_SHRINK);
815        get_content_area()->pack_start(m_buttonBox, Gtk::PACK_SHRINK);
816    #else
817      get_vbox()->pack_start(m_descriptionLabel, Gtk::PACK_SHRINK);      get_vbox()->pack_start(m_descriptionLabel, Gtk::PACK_SHRINK);
818      get_vbox()->pack_start(m_tableDimCombo, Gtk::PACK_SHRINK);      get_vbox()->pack_start(m_tableDimCombo, Gtk::PACK_SHRINK);
819      get_vbox()->pack_start(m_scrolledWindow);      get_vbox()->pack_start(m_scrolledWindow);
820        get_vbox()->pack_start(m_labelOrder, Gtk::PACK_SHRINK);
821        get_vbox()->pack_start(m_iconView, Gtk::PACK_SHRINK);
822      get_vbox()->pack_start(m_buttonBox, Gtk::PACK_SHRINK);      get_vbox()->pack_start(m_buttonBox, Gtk::PACK_SHRINK);
823    #endif
824    
825  #if GTKMM_MAJOR_VERSION >= 3  #if GTKMM_MAJOR_VERSION >= 3
826      m_descriptionLabel.set_line_wrap();      m_descriptionLabel.set_line_wrap();
# Line 872  CombineInstrumentsDialog::CombineInstrum Line 896  CombineInstrumentsDialog::CombineInstrum
896          row[m_columns.m_col_instr] = instr;          row[m_columns.m_col_instr] = instr;
897      }      }
898    
899        m_refOrderModel = Gtk::ListStore::create(m_orderColumns);
900        m_iconView.set_model(m_refOrderModel);
901        m_iconView.set_tooltip_text(_("Use drag & drop to change the order."));
902        m_iconView.set_markup_column(1);
903        m_iconView.set_selection_mode(Gtk::SELECTION_SINGLE);
904        // force background to retain white also on selections
905        // (this also fixes a bug with GTK 2 which often causes visibility issue
906        //  with the text of the selected item)
907        {
908    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
909            Gdk::Color white;
910    #else
911            Gdk::RGBA white;
912    #endif
913            white.set("#ffffff");
914            GtkWidget* widget = (GtkWidget*) m_iconView.gobj();
915    #if GTK_MAJOR_VERSION < 3
916            gtk_widget_modify_base(widget, GTK_STATE_SELECTED, white.gobj());
917            gtk_widget_modify_base(widget, GTK_STATE_ACTIVE, white.gobj());
918            gtk_widget_modify_bg(widget, GTK_STATE_SELECTED, white.gobj());
919            gtk_widget_modify_bg(widget, GTK_STATE_ACTIVE, white.gobj());
920    #endif
921        }
922    
923        m_labelOrder.set_text(_("Order of the instruments to be combined:"));
924    
925        // establish drag&drop within the instrument tree view, allowing to reorder
926        // the sequence of instruments within the gig file
927        {
928            std::vector<Gtk::TargetEntry> drag_target_instrument;
929            drag_target_instrument.push_back(Gtk::TargetEntry("gig::Instrument"));
930            m_iconView.drag_source_set(drag_target_instrument);
931            m_iconView.drag_dest_set(drag_target_instrument);
932            m_iconView.signal_drag_begin().connect(
933                sigc::mem_fun(*this, &CombineInstrumentsDialog::on_order_drag_begin)
934            );
935            m_iconView.signal_drag_data_get().connect(
936                sigc::mem_fun(*this, &CombineInstrumentsDialog::on_order_drag_data_get)
937            );
938            m_iconView.signal_drag_data_received().connect(
939                sigc::mem_fun(*this, &CombineInstrumentsDialog::on_order_drop_drag_data_received)
940            );
941        }
942    
943      m_buttonBox.set_layout(Gtk::BUTTONBOX_END);      m_buttonBox.set_layout(Gtk::BUTTONBOX_END);
944    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24)
945        m_buttonBox.set_margin(5);
946    #else
947      m_buttonBox.set_border_width(5);      m_buttonBox.set_border_width(5);
948    #endif
949      m_buttonBox.pack_start(m_cancelButton, Gtk::PACK_SHRINK);      m_buttonBox.pack_start(m_cancelButton, Gtk::PACK_SHRINK);
950      m_buttonBox.pack_start(m_OKButton, Gtk::PACK_SHRINK);      m_buttonBox.pack_start(m_OKButton, Gtk::PACK_SHRINK);
951      m_buttonBox.show();      m_buttonBox.show();
# Line 890  CombineInstrumentsDialog::CombineInstrum Line 962  CombineInstrumentsDialog::CombineInstrum
962          sigc::mem_fun(*this, &CombineInstrumentsDialog::combineSelectedInstruments)          sigc::mem_fun(*this, &CombineInstrumentsDialog::combineSelectedInstruments)
963      );      );
964    
965    #if HAS_GTKMM_SHOW_ALL_CHILDREN
966      show_all_children();      show_all_children();
967    #endif
968    
969        Settings::singleton()->showTooltips.get_proxy().signal_changed().connect(
970            sigc::mem_fun(*this, &CombineInstrumentsDialog::on_show_tooltips_changed)
971        );
972        on_show_tooltips_changed();
973    
974      // 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
975      if (gig->pVersion->major < 3) {      if (gig->pVersion->major < 3) {
# Line 903  CombineInstrumentsDialog::CombineInstrum Line 982  CombineInstrumentsDialog::CombineInstrum
982          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_WARNING);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_WARNING);
983          msg.run();          msg.run();
984      }      }
985    
986        // OK button should have focus by default for quick combining with Return key
987        m_OKButton.grab_focus();
988    }
989    
990    void CombineInstrumentsDialog::on_order_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
991    {
992        #if DEBUG_COMBINE_INSTRUMENTS
993        printf("Drag begin\n");
994        #endif
995        first_call_to_drag_data_get = true;
996    }
997    
998    void CombineInstrumentsDialog::on_order_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context,
999                                                           Gtk::SelectionData& selection_data, guint, guint)
1000    {
1001        #if DEBUG_COMBINE_INSTRUMENTS
1002        printf("Drag data get\n");
1003        #endif
1004        if (!first_call_to_drag_data_get) return;
1005        first_call_to_drag_data_get = false;
1006    
1007        // get selected source instrument
1008        gig::Instrument* src = NULL;
1009        {
1010            std::vector<Gtk::TreeModel::Path> rows = m_iconView.get_selected_items();
1011            if (!rows.empty()) {
1012                Gtk::TreeModel::iterator it = m_refOrderModel->get_iter(rows[0]);
1013                if (it) {
1014                    Gtk::TreeModel::Row row = *it;
1015                    src = row[m_orderColumns.m_col_instr];
1016                }
1017            }
1018        }
1019        if (!src) {
1020            printf("Drag data get: !src\n");
1021            return;
1022        }
1023        #if DEBUG_COMBINE_INSTRUMENTS
1024        printf("src=%ld\n", (size_t)src);
1025        #endif
1026    
1027        // pass the source gig::Instrument as pointer
1028        selection_data.set(selection_data.get_target(), 0/*unused*/, (const guchar*)&src,
1029                           sizeof(src)/*length of data in bytes*/);
1030    }
1031    
1032    void CombineInstrumentsDialog::on_order_drop_drag_data_received(
1033        const Glib::RefPtr<Gdk::DragContext>& context, int x, int y,
1034        const Gtk::SelectionData& selection_data, guint, guint time)
1035    {
1036        #if DEBUG_COMBINE_INSTRUMENTS
1037        printf("Drag data received\n");
1038        #endif
1039        if (!selection_data.get_data()) {
1040            printf("selection_data.get_data() == NULL\n");
1041            return;
1042        }
1043    
1044        gig::Instrument* src = *((gig::Instrument**) selection_data.get_data());
1045        if (!src || selection_data.get_length() != sizeof(gig::Instrument*)) {
1046            printf("!src\n");
1047            return;
1048        }
1049        #if DEBUG_COMBINE_INSTRUMENTS
1050        printf("src=%ld\n", (size_t)src);
1051        #endif
1052    
1053        gig::Instrument* dst = NULL;
1054        {
1055            Gtk::TreeModel::Path path = m_iconView.get_path_at_pos(x, y);
1056            if (!path) return;
1057    
1058            Gtk::TreeModel::iterator iter = m_refOrderModel->get_iter(path);
1059            if (!iter) return;
1060            Gtk::TreeModel::Row row = *iter;
1061            dst = row[m_orderColumns.m_col_instr];
1062        }
1063        if (!dst) {
1064            printf("!dst\n");
1065            return;
1066        }
1067    
1068        #if DEBUG_COMBINE_INSTRUMENTS
1069        printf("dragdrop received src='%s' dst='%s'\n", src->pInfo->Name.c_str(), dst->pInfo->Name.c_str());
1070        #endif
1071    
1072        // swap the two items
1073        typedef Gtk::TreeModel::Children Children;
1074        Children children = m_refOrderModel->children();
1075        Children::iterator itSrc, itDst;
1076        int i = 0, iSrc = -1, iDst = -1;
1077        for (Children::iterator iter = children.begin();
1078             iter != children.end(); ++iter, ++i)
1079        {
1080            Gtk::TreeModel::Row row = *iter;
1081            if (row[m_orderColumns.m_col_instr] == src) {
1082                itSrc = iter;
1083                iSrc  = i;
1084            } else if (row[m_orderColumns.m_col_instr] == dst) {
1085                itDst = iter;
1086                iDst  = i;
1087            }
1088        }
1089        if (itSrc && itDst) {
1090            // swap elements
1091            m_refOrderModel->iter_swap(itSrc, itDst);
1092            // update markup
1093            Gtk::TreeModel::Row rowSrc = *itSrc;
1094            Gtk::TreeModel::Row rowDst = *itDst;
1095            {
1096                Glib::ustring name = rowSrc[m_orderColumns.m_col_name];
1097                Glib::ustring markup =
1098                    "<span foreground='black' background='white'>" + ToString(iDst+1) + ".</span>\n<span foreground='green' background='white'>" + name + "</span>";
1099                rowSrc[m_orderColumns.m_col_markup] = markup;
1100            }
1101            {
1102                Glib::ustring name = rowDst[m_orderColumns.m_col_name];
1103                Glib::ustring markup =
1104                    "<span foreground='black' background='white'>" + ToString(iSrc+1) + ".</span>\n<span foreground='green' background='white'>" + name + "</span>";
1105                rowDst[m_orderColumns.m_col_markup] = markup;
1106            }
1107        }
1108  }  }
1109    
1110  void CombineInstrumentsDialog::setSelectedInstruments(const std::set<int>& instrumentIndeces) {  void CombineInstrumentsDialog::setSelectedInstruments(const std::set<int>& instrumentIndeces) {
# Line 916  void CombineInstrumentsDialog::setSelect Line 1118  void CombineInstrumentsDialog::setSelect
1118          if (instrumentIndeces.count(index))          if (instrumentIndeces.count(index))
1119              m_treeView.get_selection()->select(iter);              m_treeView.get_selection()->select(iter);
1120      }      }
1121        // hack: OK button lost focus after doing the above, it should have focus by default for quick combining with Return key
1122        m_OKButton.grab_focus();
1123  }  }
1124    
1125  void CombineInstrumentsDialog::combineSelectedInstruments() {  void CombineInstrumentsDialog::combineSelectedInstruments() {
1126      std::vector<gig::Instrument*> instruments;      std::vector<gig::Instrument*> instruments;
1127      std::vector<Gtk::TreeModel::Path> v = m_treeView.get_selection()->get_selected_rows();      {
1128      for (uint i = 0; i < v.size(); ++i) {          typedef Gtk::TreeModel::Children Children;
1129          Gtk::TreeModel::iterator it = m_refTreeModel->get_iter(v[i]);          int i = 0;
1130          Gtk::TreeModel::Row row = *it;          Children selection = m_refOrderModel->children();
1131          Glib::ustring name = row[m_columns.m_col_name];          for (Children::iterator it = selection.begin();
1132          gig::Instrument* instrument = row[m_columns.m_col_instr];               it != selection.end(); ++it, ++i)
1133          #if DEBUG_COMBINE_INSTRUMENTS          {
1134          printf("Selection '%s' 0x%lx\n\n", name.c_str(), int64_t((void*)instrument));              Gtk::TreeModel::Row row = *it;
1135          #endif              Glib::ustring name = row[m_orderColumns.m_col_name];
1136          instruments.push_back(instrument);              gig::Instrument* instrument = row[m_orderColumns.m_col_instr];
1137                #if DEBUG_COMBINE_INSTRUMENTS
1138                printf("Selection %d. '%s' %p\n\n", (i+1), name.c_str(), instrument));
1139                #endif
1140                instruments.push_back(instrument);
1141            }
1142      }      }
1143    
1144      g_warnings.clear();      g_warnings.clear();
# Line 946  void CombineInstrumentsDialog::combineSe Line 1155  void CombineInstrumentsDialog::combineSe
1155              mainDimension = static_cast<gig::dimension_t>(iTypeID);              mainDimension = static_cast<gig::dimension_t>(iTypeID);
1156          }          }
1157    
1158          // now start the actual cobination task ...          // now start the actual combination task ...
1159          combineInstruments(instruments, m_gig, m_newCombinedInstrument, mainDimension);          combineInstruments(instruments, m_gig, m_newCombinedInstrument, mainDimension);
1160      } catch (RIFF::Exception e) {;      } catch (RIFF::Exception e) {;
1161          Gtk::MessageDialog msg(*this, e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, e.Message, false, Gtk::MESSAGE_ERROR);
# Line 986  void CombineInstrumentsDialog::combineSe Line 1195  void CombineInstrumentsDialog::combineSe
1195  void CombineInstrumentsDialog::onSelectionChanged() {  void CombineInstrumentsDialog::onSelectionChanged() {
1196      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();
1197      m_OKButton.set_sensitive(v.size() >= 2);      m_OKButton.set_sensitive(v.size() >= 2);
1198    
1199        typedef Gtk::TreeModel::Children Children;
1200    
1201        // update horizontal selection list (icon view) ...
1202    
1203        // remove items which are not part of the new selection anymore
1204        {
1205            Children allOrdered = m_refOrderModel->children();
1206            for (Children::iterator itOrder = allOrdered.begin();
1207                 itOrder != allOrdered.end(); )
1208            {
1209                Gtk::TreeModel::Row rowOrder = *itOrder;
1210                gig::Instrument* instr = rowOrder[m_orderColumns.m_col_instr];
1211                for (uint i = 0; i < v.size(); ++i) {
1212                    Gtk::TreeModel::iterator itSel = m_refTreeModel->get_iter(v[i]);
1213                    Gtk::TreeModel::Row rowSel = *itSel;
1214                    if (rowSel[m_columns.m_col_instr] == instr)
1215                        goto nextOrderedItem;
1216                }
1217                goto removeOrderedItem;
1218            nextOrderedItem:
1219                ++itOrder;
1220                continue;
1221            removeOrderedItem:
1222                // postfix increment here to avoid iterator invalidation
1223                m_refOrderModel->erase(itOrder++);
1224            }
1225        }
1226    
1227        // add items newly added to the selection
1228        for (uint i = 0; i < v.size(); ++i) {
1229            Gtk::TreeModel::iterator itSel = m_refTreeModel->get_iter(v[i]);
1230            Gtk::TreeModel::Row rowSel = *itSel;
1231            gig::Instrument* instr = rowSel[m_columns.m_col_instr];
1232            Children allOrdered = m_refOrderModel->children();
1233            for (Children::iterator itOrder = allOrdered.begin();
1234                 itOrder != allOrdered.end(); ++itOrder)
1235            {
1236                Gtk::TreeModel::Row rowOrder = *itOrder;
1237                if (rowOrder[m_orderColumns.m_col_instr] == instr)
1238                    goto nextSelectionItem;
1239            }
1240            goto addNewSelectionItem;
1241        nextSelectionItem:
1242            continue;
1243        addNewSelectionItem:
1244            Glib::ustring name = gig_to_utf8(instr->pInfo->Name);
1245            Gtk::TreeModel::iterator iterOrder = m_refOrderModel->append();
1246            Gtk::TreeModel::Row rowOrder = *iterOrder;
1247            rowOrder[m_orderColumns.m_col_name] = name;
1248            rowOrder[m_orderColumns.m_col_instr] = instr;
1249        }
1250    
1251        // update markup
1252        {
1253            int i = 0;
1254            Children allOrdered = m_refOrderModel->children();
1255            for (Children::iterator itOrder = allOrdered.begin();
1256                 itOrder != allOrdered.end(); ++itOrder, ++i)
1257            {
1258                Gtk::TreeModel::Row rowOrder = *itOrder;
1259                Glib::ustring name = rowOrder[m_orderColumns.m_col_name];
1260                Glib::ustring markup =
1261                    "<span foreground='black' background='white'>" + ToString(i+1) + ".</span>\n<span foreground='green' background='white'>" + name + "</span>";
1262                rowOrder[m_orderColumns.m_col_markup] = markup;
1263            }
1264        }
1265    }
1266    
1267    void CombineInstrumentsDialog::on_show_tooltips_changed() {
1268        const bool b = Settings::singleton()->showTooltips;
1269    
1270        m_treeView.set_has_tooltip(b);
1271        m_iconView.set_has_tooltip(b);
1272    
1273        set_has_tooltip(b);
1274  }  }
1275    
1276  bool CombineInstrumentsDialog::fileWasChanged() const {  bool CombineInstrumentsDialog::fileWasChanged() const {

Legend:
Removed from v.3299  
changed lines
  Added in v.3762

  ViewVC Help
Powered by ViewVC