/[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 3225 by schoenebeck, Fri May 26 22:10:16 2017 UTC revision 3339 by schoenebeck, Sun Jul 30 18:57:35 2017 UTC
# Line 23  Line 23 
23  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
24  #include <gtkmm/messagedialog.h>  #include <gtkmm/messagedialog.h>
25  #include <gtkmm/label.h>  #include <gtkmm/label.h>
26    #include <gtk/gtkwidget.h> // for gtk_widget_modify_*()
27    
28  Glib::ustring dimTypeAsString(gig::dimension_t d);  Glib::ustring dimTypeAsString(gig::dimension_t d);
29    
# Line 796  CombineInstrumentsDialog::CombineInstrum Line 797  CombineInstrumentsDialog::CombineInstrum
797      get_vbox()->pack_start(m_descriptionLabel, Gtk::PACK_SHRINK);      get_vbox()->pack_start(m_descriptionLabel, Gtk::PACK_SHRINK);
798      get_vbox()->pack_start(m_tableDimCombo, Gtk::PACK_SHRINK);      get_vbox()->pack_start(m_tableDimCombo, Gtk::PACK_SHRINK);
799      get_vbox()->pack_start(m_scrolledWindow);      get_vbox()->pack_start(m_scrolledWindow);
800        get_vbox()->pack_start(m_labelOrder, Gtk::PACK_SHRINK);
801        get_vbox()->pack_start(m_iconView, Gtk::PACK_SHRINK);
802      get_vbox()->pack_start(m_buttonBox, Gtk::PACK_SHRINK);      get_vbox()->pack_start(m_buttonBox, Gtk::PACK_SHRINK);
803    
804  #if GTKMM_MAJOR_VERSION >= 3  #if GTKMM_MAJOR_VERSION >= 3
# Line 840  CombineInstrumentsDialog::CombineInstrum Line 843  CombineInstrumentsDialog::CombineInstrum
843          "Use SHIFT + left click or CTRL + left click to select the instruments "          "Use SHIFT + left click or CTRL + left click to select the instruments "
844          "you want to combine."          "you want to combine."
845      ));      ));
846      m_treeView.append_column("Instrument", m_columns.m_col_name);      m_treeView.append_column(_("Nr"), m_columns.m_col_index);
847      m_treeView.set_headers_visible(false);      m_treeView.append_column(_("Instrument"), m_columns.m_col_name);
848        m_treeView.set_headers_visible(true);
849      m_treeView.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);      m_treeView.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
850      m_treeView.get_selection()->signal_changed().connect(      m_treeView.get_selection()->signal_changed().connect(
851          sigc::mem_fun(*this, &CombineInstrumentsDialog::onSelectionChanged)          sigc::mem_fun(*this, &CombineInstrumentsDialog::onSelectionChanged)
# Line 866  CombineInstrumentsDialog::CombineInstrum Line 870  CombineInstrumentsDialog::CombineInstrum
870          Glib::ustring name(gig_to_utf8(instr->pInfo->Name));          Glib::ustring name(gig_to_utf8(instr->pInfo->Name));
871          Gtk::TreeModel::iterator iter = m_refTreeModel->append();          Gtk::TreeModel::iterator iter = m_refTreeModel->append();
872          Gtk::TreeModel::Row row = *iter;          Gtk::TreeModel::Row row = *iter;
873            row[m_columns.m_col_index] = i;
874          row[m_columns.m_col_name] = name;          row[m_columns.m_col_name] = name;
875          row[m_columns.m_col_instr] = instr;          row[m_columns.m_col_instr] = instr;
876      }      }
877    
878        m_refOrderModel = Gtk::ListStore::create(m_orderColumns);
879        m_iconView.set_model(m_refOrderModel);
880        m_iconView.set_tooltip_text(_("Use drag & drop to change the order."));
881        m_iconView.set_markup_column(1);
882        m_iconView.set_selection_mode(Gtk::SELECTION_SINGLE);
883        // force background to retain white also on selections
884        // (this also fixes a bug with GTK 2 which often causes visibility issue
885        //  with the text of the selected item)
886        {
887            Gdk::Color white;
888            white.set("#ffffff");
889            GtkWidget* widget = (GtkWidget*) m_iconView.gobj();
890            gtk_widget_modify_base(widget, GTK_STATE_SELECTED, white.gobj());
891            gtk_widget_modify_base(widget, GTK_STATE_ACTIVE, white.gobj());
892            gtk_widget_modify_bg(widget, GTK_STATE_SELECTED, white.gobj());
893            gtk_widget_modify_bg(widget, GTK_STATE_ACTIVE, white.gobj());
894        }
895    
896        m_labelOrder.set_text(_("Order of the instruments to be combined:"));
897    
898        // establish drag&drop within the instrument tree view, allowing to reorder
899        // the sequence of instruments within the gig file
900        {
901            std::vector<Gtk::TargetEntry> drag_target_instrument;
902            drag_target_instrument.push_back(Gtk::TargetEntry("gig::Instrument"));
903            m_iconView.drag_source_set(drag_target_instrument);
904            m_iconView.drag_dest_set(drag_target_instrument);
905            m_iconView.signal_drag_begin().connect(
906                sigc::mem_fun(*this, &CombineInstrumentsDialog::on_order_drag_begin)
907            );
908            m_iconView.signal_drag_data_get().connect(
909                sigc::mem_fun(*this, &CombineInstrumentsDialog::on_order_drag_data_get)
910            );
911            m_iconView.signal_drag_data_received().connect(
912                sigc::mem_fun(*this, &CombineInstrumentsDialog::on_order_drop_drag_data_received)
913            );
914        }
915    
916      m_buttonBox.set_layout(Gtk::BUTTONBOX_END);      m_buttonBox.set_layout(Gtk::BUTTONBOX_END);
917      m_buttonBox.set_border_width(5);      m_buttonBox.set_border_width(5);
918      m_buttonBox.pack_start(m_cancelButton, Gtk::PACK_SHRINK);      m_buttonBox.pack_start(m_cancelButton, Gtk::PACK_SHRINK);
# Line 901  CombineInstrumentsDialog::CombineInstrum Line 944  CombineInstrumentsDialog::CombineInstrum
944          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_WARNING);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_WARNING);
945          msg.run();          msg.run();
946      }      }
947    
948        // OK button should have focus by default for quick combining with Return key
949        m_OKButton.grab_focus();
950    }
951    
952    void CombineInstrumentsDialog::on_order_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
953    {
954        printf("Drag begin\n");
955        first_call_to_drag_data_get = true;
956    }
957    
958    void CombineInstrumentsDialog::on_order_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context,
959                                                           Gtk::SelectionData& selection_data, guint, guint)
960    {
961        printf("Drag data get\n");
962        if (!first_call_to_drag_data_get) return;
963        first_call_to_drag_data_get = false;
964    
965        // get selected source instrument
966        gig::Instrument* src = NULL;
967        {
968            std::vector<Gtk::TreeModel::Path> rows = m_iconView.get_selected_items();
969            if (!rows.empty()) {
970                Gtk::TreeModel::iterator it = m_refOrderModel->get_iter(rows[0]);
971                if (it) {
972                    Gtk::TreeModel::Row row = *it;
973                    src = row[m_orderColumns.m_col_instr];
974                }
975            }
976        }
977        if (!src) {
978            printf("Drag data get: !src\n");
979            return;
980        }
981        printf("src=%ld\n", (size_t)src);
982    
983        // pass the source gig::Instrument as pointer
984        selection_data.set(selection_data.get_target(), 0/*unused*/, (const guchar*)&src,
985                           sizeof(src)/*length of data in bytes*/);
986    }
987    
988    void CombineInstrumentsDialog::on_order_drop_drag_data_received(
989        const Glib::RefPtr<Gdk::DragContext>& context, int x, int y,
990        const Gtk::SelectionData& selection_data, guint, guint time)
991    {
992        printf("Drag data received\n");
993        if (&selection_data == NULL) {
994            printf("!selection_data\n");
995            return;
996        }
997        if (!selection_data.get_data()) {
998            printf("selection_data.get_data() == NULL\n");
999            return;
1000        }
1001    
1002        gig::Instrument* src = *((gig::Instrument**) selection_data.get_data());
1003        if (!src || selection_data.get_length() != sizeof(gig::Instrument*)) {
1004            printf("!src\n");
1005            return;
1006        }
1007        printf("src=%d\n", src);
1008    
1009        gig::Instrument* dst = NULL;
1010        {
1011            Gtk::TreeModel::Path path = m_iconView.get_path_at_pos(x, y);
1012            if (!path) return;
1013    
1014            Gtk::TreeModel::iterator iter = m_refOrderModel->get_iter(path);
1015            if (!iter) return;
1016            Gtk::TreeModel::Row row = *iter;
1017            dst = row[m_orderColumns.m_col_instr];
1018        }
1019        if (!dst) {
1020            printf("!dst\n");
1021            return;
1022        }
1023    
1024        printf("dragdrop received src='%s' dst='%s'\n", src->pInfo->Name.c_str(), dst->pInfo->Name.c_str());
1025    
1026        // swap the two items
1027        typedef Gtk::TreeModel::Children Children;
1028        Children children = m_refOrderModel->children();
1029        Children::iterator itSrc, itDst;
1030        int i = 0, iSrc = -1, iDst = -1;
1031        for (Children::iterator iter = children.begin();
1032             iter != children.end(); ++iter, ++i)
1033        {
1034            Gtk::TreeModel::Row row = *iter;
1035            if (row[m_orderColumns.m_col_instr] == src) {
1036                itSrc = iter;
1037                iSrc  = i;
1038            } else if (row[m_orderColumns.m_col_instr] == dst) {
1039                itDst = iter;
1040                iDst  = i;
1041            }
1042        }
1043        if (itSrc && itDst) {
1044            // swap elements
1045            m_refOrderModel->iter_swap(itSrc, itDst);
1046            // update markup
1047            Gtk::TreeModel::Row rowSrc = *itSrc;
1048            Gtk::TreeModel::Row rowDst = *itDst;
1049            {
1050                Glib::ustring name = rowSrc[m_orderColumns.m_col_name];
1051                Glib::ustring markup =
1052                    "<span foreground='black' background='white'>" + ToString(iDst+1) + ".</span>\n<span foreground='green' background='white'>" + name + "</span>";
1053                rowSrc[m_orderColumns.m_col_markup] = markup;
1054            }
1055            {
1056                Glib::ustring name = rowDst[m_orderColumns.m_col_name];
1057                Glib::ustring markup =
1058                    "<span foreground='black' background='white'>" + ToString(iSrc+1) + ".</span>\n<span foreground='green' background='white'>" + name + "</span>";
1059                rowDst[m_orderColumns.m_col_markup] = markup;
1060            }
1061        }
1062    }
1063    
1064    void CombineInstrumentsDialog::setSelectedInstruments(const std::set<int>& instrumentIndeces) {
1065        typedef Gtk::TreeModel::Children Children;
1066        Children children = m_refTreeModel->children();
1067        for (Children::iterator iter = children.begin();
1068             iter != children.end(); ++iter)
1069        {
1070            Gtk::TreeModel::Row row = *iter;
1071            int index = row[m_columns.m_col_index];
1072            if (instrumentIndeces.count(index))
1073                m_treeView.get_selection()->select(iter);
1074        }
1075        // hack: OK button lost focus after doing the above, it should have focus by default for quick combining with Return key
1076        m_OKButton.grab_focus();
1077  }  }
1078    
1079  void CombineInstrumentsDialog::combineSelectedInstruments() {  void CombineInstrumentsDialog::combineSelectedInstruments() {
1080      std::vector<gig::Instrument*> instruments;      std::vector<gig::Instrument*> instruments;
1081      std::vector<Gtk::TreeModel::Path> v = m_treeView.get_selection()->get_selected_rows();      {
1082      for (uint i = 0; i < v.size(); ++i) {          typedef Gtk::TreeModel::Children Children;
1083          Gtk::TreeModel::iterator it = m_refTreeModel->get_iter(v[i]);          int i = 0;
1084          Gtk::TreeModel::Row row = *it;          Children selection = m_refOrderModel->children();
1085          Glib::ustring name = row[m_columns.m_col_name];          for (Children::iterator it = selection.begin();
1086          gig::Instrument* instrument = row[m_columns.m_col_instr];               it != selection.end(); ++it, ++i)
1087          #if DEBUG_COMBINE_INSTRUMENTS          {
1088          printf("Selection '%s' 0x%lx\n\n", name.c_str(), int64_t((void*)instrument));              Gtk::TreeModel::Row row = *it;
1089          #endif              Glib::ustring name = row[m_orderColumns.m_col_name];
1090          instruments.push_back(instrument);              gig::Instrument* instrument = row[m_orderColumns.m_col_instr];
1091                #if DEBUG_COMBINE_INSTRUMENTS
1092                printf("Selection %d. '%s' %p\n\n", (i+1), name.c_str(), instrument));
1093                #endif
1094                instruments.push_back(instrument);
1095            }
1096      }      }
1097    
1098      g_warnings.clear();      g_warnings.clear();
# Line 931  void CombineInstrumentsDialog::combineSe Line 1109  void CombineInstrumentsDialog::combineSe
1109              mainDimension = static_cast<gig::dimension_t>(iTypeID);              mainDimension = static_cast<gig::dimension_t>(iTypeID);
1110          }          }
1111    
1112          // now start the actual cobination task ...          // now start the actual combination task ...
1113          combineInstruments(instruments, m_gig, m_newCombinedInstrument, mainDimension);          combineInstruments(instruments, m_gig, m_newCombinedInstrument, mainDimension);
1114      } catch (RIFF::Exception e) {;      } catch (RIFF::Exception e) {;
1115          Gtk::MessageDialog msg(*this, e.Message, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, e.Message, false, Gtk::MESSAGE_ERROR);
# Line 971  void CombineInstrumentsDialog::combineSe Line 1149  void CombineInstrumentsDialog::combineSe
1149  void CombineInstrumentsDialog::onSelectionChanged() {  void CombineInstrumentsDialog::onSelectionChanged() {
1150      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();
1151      m_OKButton.set_sensitive(v.size() >= 2);      m_OKButton.set_sensitive(v.size() >= 2);
1152    
1153        typedef Gtk::TreeModel::Children Children;
1154    
1155        // update horizontal selection list (icon view) ...
1156    
1157        // remove items which are not part of the new selection anymore
1158        {
1159            Children allOrdered = m_refOrderModel->children();
1160            for (Children::iterator itOrder = allOrdered.begin();
1161                 itOrder != allOrdered.end(); ++itOrder)
1162            {
1163                Gtk::TreeModel::Row rowOrder = *itOrder;
1164                gig::Instrument* instr = rowOrder[m_orderColumns.m_col_instr];
1165                for (uint i = 0; i < v.size(); ++i) {
1166                    Gtk::TreeModel::iterator itSel = m_refTreeModel->get_iter(v[i]);
1167                    Gtk::TreeModel::Row rowSel = *itSel;
1168                    if (rowSel[m_columns.m_col_instr] == instr)
1169                        goto nextOrderedItem;
1170                }
1171                goto removeOrderedItem;
1172            nextOrderedItem:
1173                continue;
1174            removeOrderedItem:
1175                m_refOrderModel->erase(itOrder);
1176            }
1177        }
1178    
1179        // add items newly added to the selection
1180        for (uint i = 0; i < v.size(); ++i) {
1181            Gtk::TreeModel::iterator itSel = m_refTreeModel->get_iter(v[i]);
1182            Gtk::TreeModel::Row rowSel = *itSel;
1183            gig::Instrument* instr = rowSel[m_columns.m_col_instr];
1184            Children allOrdered = m_refOrderModel->children();
1185            for (Children::iterator itOrder = allOrdered.begin();
1186                 itOrder != allOrdered.end(); ++itOrder)
1187            {
1188                Gtk::TreeModel::Row rowOrder = *itOrder;
1189                if (rowOrder[m_orderColumns.m_col_instr] == instr)
1190                    goto nextSelectionItem;
1191            }
1192            goto addNewSelectionItem;
1193        nextSelectionItem:
1194            continue;
1195        addNewSelectionItem:
1196            Glib::ustring name = gig_to_utf8(instr->pInfo->Name);
1197            Gtk::TreeModel::iterator iterOrder = m_refOrderModel->append();
1198            Gtk::TreeModel::Row rowOrder = *iterOrder;
1199            rowOrder[m_orderColumns.m_col_name] = name;
1200            rowOrder[m_orderColumns.m_col_instr] = instr;
1201        }
1202    
1203        // update markup
1204        {
1205            int i = 0;
1206            Children allOrdered = m_refOrderModel->children();
1207            for (Children::iterator itOrder = allOrdered.begin();
1208                 itOrder != allOrdered.end(); ++itOrder, ++i)
1209            {
1210                Gtk::TreeModel::Row rowOrder = *itOrder;
1211                Glib::ustring name = rowOrder[m_orderColumns.m_col_name];
1212                Glib::ustring markup =
1213                    "<span foreground='black' background='white'>" + ToString(i+1) + ".</span>\n<span foreground='green' background='white'>" + name + "</span>";
1214                rowOrder[m_orderColumns.m_col_markup] = markup;
1215            }
1216        }
1217  }  }
1218    
1219  bool CombineInstrumentsDialog::fileWasChanged() const {  bool CombineInstrumentsDialog::fileWasChanged() const {

Legend:
Removed from v.3225  
changed lines
  Added in v.3339

  ViewVC Help
Powered by ViewVC