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

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

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

revision 3161 by schoenebeck, Mon May 8 22:25:46 2017 UTC revision 3366 by schoenebeck, Wed Nov 15 16:21:20 2017 UTC
# Line 6  Line 6 
6  */  */
7    
8  #include "MacrosSetup.h"  #include "MacrosSetup.h"
9    #include "compat.h"
10  #include "global.h"  #include "global.h"
11  #include <assert.h>  #include <assert.h>
12  #include <set>  #include <set>
13  #include <math.h>  #include <math.h>
14  #include <gtkmm/stock.h>  #if HAS_GTKMM_STOCK
15    # include <gtkmm/stock.h>
16    #endif
17    #include "MacroEditor.h"
18    
19  MacrosSetup::MacrosSetup() :  MacrosSetup::MacrosSetup() :
20      m_modified(false),      m_modified(false),
21      m_clipboardContent(NULL),      m_clipboardContent(NULL),
22      m_addFromClipboardButton("  " + Glib::ustring(_("From Clipboard")) + "  " + UNICODE_PRIMARY_KEY_SYMBOL + "B"),      m_addFromClipboardButton("  " + Glib::ustring(_("From Clipboard")) + "  " + UNICODE_PRIMARY_KEY_SYMBOL + "B"),
23      m_addFromSelectionButton("  " + Glib::ustring(_("From Selection")) + "  " + UNICODE_PRIMARY_KEY_SYMBOL + "S"),      m_addFromSelectionButton("  " + Glib::ustring(_("From Selection")) + "  " + UNICODE_PRIMARY_KEY_SYMBOL + "S"),
24    #if HAS_GTKMM_STOCK
25        m_buttonUp(Gtk::Stock::GO_UP),
26        m_buttonDown(Gtk::Stock::GO_DOWN),
27        m_buttonEdit(Gtk::Stock::EDIT),
28    #else
29        m_buttonUp(_("Up"), true),
30        m_buttonDown(_("Down"), true),
31        m_buttonEdit(_("Edit"), true),
32    #endif
33        m_buttonDuplicate(_("Duplicate")),
34      m_statusLabel("",  Gtk::ALIGN_START),      m_statusLabel("",  Gtk::ALIGN_START),
35      m_deleteButton(Glib::ustring(_("Delete")) + "  " + UNICODE_PRIMARY_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL),      m_labelComment(_("Comment"), Gtk::ALIGN_START),
36      m_inverseDeleteButton(Glib::ustring(_("Inverse Delete")) + "  " + UNICODE_ALT_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL),      m_deleteButton("  " + Glib::ustring(_("Delete")) + "  " + UNICODE_PRIMARY_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL),
37      m_applyButton(_("_Apply"), true),      m_inverseDeleteButton("  " + Glib::ustring(_("Inverse Delete")) + "  " + UNICODE_ALT_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL),
38    #if HAS_GTKMM_STOCK
39        m_applyButton(Gtk::Stock::APPLY),
40        m_cancelButton(Gtk::Stock::CANCEL),
41    #else
42        m_applyButton(_("Apply"), true),
43      m_cancelButton(_("_Cancel"), true),      m_cancelButton(_("_Cancel"), true),
44    #endif
45      m_altKeyDown(false),      m_altKeyDown(false),
46      m_primaryKeyDown(false)      m_primaryKeyDown(false)
47  {  {
# Line 29  MacrosSetup::MacrosSetup() : Line 49  MacrosSetup::MacrosSetup() :
49    
50      set_title(_("Setup Macros"));      set_title(_("Setup Macros"));
51    
52      set_default_size(800, 600);  #if !HAS_GTKMM_STOCK
53        // see : https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
54        m_buttonUp.set_icon_name("go-up");
55        m_buttonDown.set_icon_name("go-down");
56        m_buttonEdit.set_icon_name("insert-text");
57    #endif
58    
59        if (!Settings::singleton()->autoRestoreWindowDimension) {
60            set_default_size(680, 500);
61            set_position(Gtk::WIN_POS_CENTER);
62        }
63    
64    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION >= 12)
65        m_labelIntro.set_margin_start(10);
66        m_labelIntro.set_margin_end(10);
67    #else
68        m_labelIntro.set_padding(10, 10);
69    #endif
70    
71    #if GTKMM_MAJOR_VERSION >= 3
72        m_labelIntro.set_line_wrap();
73    #endif
74        m_labelIntro.set_text(
75            _("A macro is a list of parameters and corresponding values which "
76              "should be applied to the instrument editor when the macro is "
77              "triggered by the user. A macro is triggered either by selecting "
78              "the macro from the \"Macro\" menu, or by hitting the macro's "
79              "respective keyboard accelerator (F1 to F12), or by applying a "
80              "previously copied macro from the clipboard.")
81        );
82        m_vbox.pack_start(m_labelIntro, Gtk::PACK_SHRINK);
83    
84    #if HAS_GTKMM_STOCK
85      m_addFromClipboardButton.set_image(      m_addFromClipboardButton.set_image(
86          *new Gtk::Image(Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)          *new Gtk::Image(Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)
87      );      );
88      m_addFromSelectionButton.set_image(      m_addFromSelectionButton.set_image(
89          *new Gtk::Image(Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)          *new Gtk::Image(Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)
90      );      );
91        m_buttonDuplicate.set_image(
92            *new Gtk::Image(Gtk::Stock::COPY, Gtk::ICON_SIZE_BUTTON)
93        );
94        m_deleteButton.set_image(
95            *new Gtk::Image(Gtk::Stock::DELETE, Gtk::ICON_SIZE_BUTTON)
96        );
97        m_inverseDeleteButton.set_image(
98            *new Gtk::Image(Gtk::Stock::DELETE, Gtk::ICON_SIZE_BUTTON)
99        );
100    #else // since GTKMM 3.90 ...
101        // see : https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
102        m_addFromClipboardButton.set_icon_name("list-add");
103        m_addFromSelectionButton.set_icon_name("list-add");
104        m_buttonDuplicate.set_icon_name("edit-copy");
105        m_deleteButton.set_icon_name("edit-delete");
106        m_inverseDeleteButton.set_icon_name("edit-delete");
107    #endif
108      m_addFromClipboardButton.set_tooltip_text(_("Create a new macro from the content currently available on the clipboard."));      m_addFromClipboardButton.set_tooltip_text(_("Create a new macro from the content currently available on the clipboard."));
109      m_addFromSelectionButton.set_tooltip_text(_("Create a new macro from the currently selected dimension region's parameters currently shown on the main window."));      m_addFromSelectionButton.set_tooltip_text(_("Create a new macro from the currently selected dimension region's parameters currently shown on the main window."));
110      m_addHBox.pack_start(m_addFromClipboardButton);      m_buttonDuplicate.set_tooltip_text(_("Duplicate the selected macro(s). The new macro(s) will be appended to the end of the list."));
111      m_addHBox.pack_start(m_addFromSelectionButton);      m_buttonUp.set_tooltip_text(
112            _("Move the selected macro up in the list, which changes its order of "
113              "appearance in the main window's \"Macro\" menu and changes to which "
114              "keyboard accelerator key (F1 to F12) the macro is assigned to."));
115        m_buttonDown.set_tooltip_text(
116            _("Move the selected macro down in the list, which changes its order of "
117              "appearance in the main window's \"Macro\" menu and changes to which "
118              "keyboard accelerator key (F1 to F12) the macro is assigned to."));
119        m_buttonEdit.set_tooltip_text(_("Open the Macro Editor for the selected macro."));
120        m_deleteButton.set_tooltip_text(_("Delete the selected macros."));
121        m_inverseDeleteButton.set_tooltip_text(_("Delete all macros except the selected ones."));
122        m_addHBox.pack_start(m_addFromClipboardButton, Gtk::PACK_EXPAND_WIDGET/*, 15*/);
123        m_addHBox.pack_start(m_addFromSelectionButton, Gtk::PACK_EXPAND_WIDGET/*, 15*/);
124      m_vbox.pack_start(m_addHBox, Gtk::PACK_SHRINK);      m_vbox.pack_start(m_addHBox, Gtk::PACK_SHRINK);
125    
126        m_vbox.pack_start(m_mainHBox);
127        m_vbox.set_spacing(5);
128    
129      // create Macro list treeview (including its data model)      // create Macro list treeview (including its data model)
130      m_treeStoreMacros = MacroListTreeStore::create(m_treeModelMacros);      m_treeStoreMacros = MacroListTreeStore::create(m_treeModelMacros);
131      m_treeViewMacros.set_model(m_treeStoreMacros);      m_treeViewMacros.set_model(m_treeStoreMacros);
132      m_treeViewMacros.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);      m_treeViewMacros.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
133      //m_treeViewMacro.set_tooltip_text(_(""));      //m_treeViewMacro.set_tooltip_text(_(""));
134      m_treeViewMacros.append_column(_("Key"), m_treeModelMacros.m_col_key);      m_treeViewMacros.append_column(_("Key"), m_treeModelMacros.m_col_key);
135      m_treeViewMacros.append_column_editable(_("Name"), m_treeModelMacros.m_col_name);      m_treeViewMacros.append_column_editable(_("Macro Name"), m_treeModelMacros.m_col_name);
136      m_treeViewMacros.append_column(_("Created"), m_treeModelMacros.m_col_created);      m_treeViewMacros.append_column(_("Created"), m_treeModelMacros.m_col_created);
137      m_treeViewMacros.append_column(_("Modified"), m_treeModelMacros.m_col_modified);      m_treeViewMacros.append_column(_("Modified"), m_treeModelMacros.m_col_modified);
138      m_treeViewMacros.set_tooltip_column(m_treeModelMacros.m_col_comment.index());      m_treeViewMacros.set_tooltip_column(m_treeModelMacros.m_col_comment.index());
# Line 82  MacrosSetup::MacrosSetup() : Line 165  MacrosSetup::MacrosSetup() :
165      m_treeViewMacros.get_selection()->signal_changed().connect(      m_treeViewMacros.get_selection()->signal_changed().connect(
166          sigc::mem_fun(*this, &MacrosSetup::onTreeViewSelectionChanged)          sigc::mem_fun(*this, &MacrosSetup::onTreeViewSelectionChanged)
167      );      );
168    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION > 91 || (GTKMM_MINOR_VERSION == 91 && GTKMM_MICRO_VERSION >= 2))) // GTKMM >= 3.91.2
169        m_treeViewMacros.signal_key_release_event().connect(
170    #else
171      m_treeViewMacros.signal_key_release_event().connect_notify(      m_treeViewMacros.signal_key_release_event().connect_notify(
172    #endif
173          sigc::mem_fun(*this, &MacrosSetup::onMacroTreeViewKeyRelease)          sigc::mem_fun(*this, &MacrosSetup::onMacroTreeViewKeyRelease)
174      );      );
175      m_treeStoreMacros->signal_row_changed().connect(      m_treeStoreMacros->signal_row_changed().connect(
176          sigc::mem_fun(*this, &MacrosSetup::onMacroTreeViewRowValueChanged)          sigc::mem_fun(*this, &MacrosSetup::onMacroTreeViewRowValueChanged)
177      );      );
178      m_ignoreTreeViewValueChange = false;      m_ignoreTreeViewValueChange = false;
179        m_ignoreCommentTextViewChange = false;
180    
181      m_scrolledWindow.add(m_treeViewMacros);      m_scrolledWindow.add(m_treeViewMacros);
182      m_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);      m_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
183      m_vbox.pack_start(m_scrolledWindow);      m_mainHBox.pack_start(m_scrolledWindow);
184    
185        m_rvbox.set_spacing(5);
186    
187        m_mainHBox.pack_start(m_rvbox, Gtk::PACK_SHRINK);
188        m_mainHBox.set_spacing(5),
189        m_rvbox.set_spacing(5);
190        m_rvbox.pack_start(m_buttonDuplicate, Gtk::PACK_SHRINK);
191        m_rvbox.pack_start(m_detailsButtonBox, Gtk::PACK_SHRINK);
192    
193        //m_textViewComment.set_left_margin(3);
194        //m_textViewComment.set_right_margin(3);
195        m_textViewComment.set_indent(2);
196        m_textViewComment.set_tooltip_text(
197            _("Write arbitrary comments for the selected macro which help you to "
198              "remember the purpose of your macro. The comment will be shown as "
199              "tooltip in the main window's \"Macro\" menu for example.")
200        );
201        m_scrolledWindowComment.add(m_textViewComment);
202        m_scrolledWindowComment.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
203        m_labelComment.set_markup(
204            "<b>" + m_labelComment.get_text() + "</b>"
205        );
206        m_rvbox.pack_start(m_labelComment, Gtk::PACK_SHRINK);
207        m_rvbox.pack_start(m_scrolledWindowComment);
208    
209        m_detailsButtonBox.pack_start(m_buttonUp);
210        m_detailsButtonBox.pack_start(m_buttonDown);
211        m_detailsButtonBox.pack_start(m_buttonEdit);
212    
213      m_buttonBoxL.set_layout(Gtk::BUTTONBOX_START);      m_buttonBoxL.set_layout(Gtk::BUTTONBOX_START);
214      m_buttonBoxL.pack_start(m_deleteButton);      m_buttonBoxL.pack_start(m_deleteButton);
215      m_buttonBoxL.pack_start(m_inverseDeleteButton);      m_buttonBoxL.pack_start(m_inverseDeleteButton);
216      m_deleteButton.set_sensitive(false);      m_deleteButton.set_sensitive(false);
217      m_inverseDeleteButton.set_sensitive(false);      m_inverseDeleteButton.set_sensitive(false);
218        m_buttonDuplicate.set_sensitive(false);
219        m_buttonUp.set_sensitive(false);
220        m_buttonDown.set_sensitive(false);
221    
222      m_buttonBox.set_layout(Gtk::BUTTONBOX_END);      m_buttonBox.set_layout(Gtk::BUTTONBOX_END);
223      m_buttonBox.pack_start(m_applyButton);      m_buttonBox.pack_start(m_applyButton);
# Line 107  MacrosSetup::MacrosSetup() : Line 226  MacrosSetup::MacrosSetup() :
226      m_applyButton.set_sensitive(false);      m_applyButton.set_sensitive(false);
227      m_applyButton.grab_focus();      m_applyButton.grab_focus();
228    
229  #if GTKMM_MAJOR_VERSION >= 3  #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION >= 12)
230        m_statusLabel.set_margin_start(6);
231        m_statusLabel.set_margin_end(6);
232    #elif GTKMM_MAJOR_VERSION >= 3
233      m_statusLabel.set_margin_left(6);      m_statusLabel.set_margin_left(6);
234      m_statusLabel.set_margin_right(6);      m_statusLabel.set_margin_right(6);
235  #else  #else
# Line 115  MacrosSetup::MacrosSetup() : Line 237  MacrosSetup::MacrosSetup() :
237  #endif  #endif
238    
239      m_statusHBox.pack_start(m_statusLabel);      m_statusHBox.pack_start(m_statusLabel);
240    #if HAS_GTKMM_SHOW_ALL_CHILDREN
241      m_statusHBox.show_all_children();      m_statusHBox.show_all_children();
242    #endif
243    
244      m_footerHBox.pack_start(m_buttonBoxL, Gtk::PACK_SHRINK);      m_footerHBox.pack_start(m_buttonBoxL, Gtk::PACK_SHRINK);
245      m_footerHBox.pack_start(m_statusHBox);      m_footerHBox.pack_start(m_statusHBox);
# Line 131  MacrosSetup::MacrosSetup() : Line 255  MacrosSetup::MacrosSetup() :
255          sigc::mem_fun(*this, &MacrosSetup::onButtonAddFromSelection)          sigc::mem_fun(*this, &MacrosSetup::onButtonAddFromSelection)
256      );      );
257    
258        m_buttonUp.signal_clicked().connect(
259            sigc::mem_fun(*this, &MacrosSetup::onButtonUp)
260        );
261    
262        m_buttonDown.signal_clicked().connect(
263            sigc::mem_fun(*this, &MacrosSetup::onButtonDown)
264        );
265    
266        m_buttonEdit.signal_clicked().connect(
267            sigc::mem_fun(*this, &MacrosSetup::onButtonEdit)
268        );
269    
270        m_buttonDuplicate.signal_clicked().connect(
271            sigc::mem_fun(*this, &MacrosSetup::onButtonDuplicate)
272        );
273    
274        m_textViewComment.get_buffer()->signal_changed().connect(
275            sigc::mem_fun(*this, &MacrosSetup::onCommentTextViewChanged)
276        );
277    
278      m_applyButton.signal_clicked().connect(      m_applyButton.signal_clicked().connect(
279          sigc::mem_fun(*this, &MacrosSetup::onButtonApply)          sigc::mem_fun(*this, &MacrosSetup::onButtonApply)
280      );      );
# Line 152  MacrosSetup::MacrosSetup() : Line 296  MacrosSetup::MacrosSetup() :
296      );      );
297    
298      signal_delete_event().connect(      signal_delete_event().connect(
299    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION > 91 || (GTKMM_MINOR_VERSION == 91 && GTKMM_MICRO_VERSION >= 2))) // GTKMM >= 3.91.2
300          sigc::mem_fun(*this, &MacrosSetup::onWindowDelete)          sigc::mem_fun(*this, &MacrosSetup::onWindowDelete)
301    #else
302            sigc::mem_fun(*this, &MacrosSetup::onWindowDeleteP)
303    #endif
304      );      );
305    
306      signal_key_press_event().connect(      signal_key_press_event().connect(
# Line 162  MacrosSetup::MacrosSetup() : Line 310  MacrosSetup::MacrosSetup() :
310          sigc::mem_fun(*this, &MacrosSetup::onKeyReleased)          sigc::mem_fun(*this, &MacrosSetup::onKeyReleased)
311      );      );
312    
313    #if HAS_GTKMM_SHOW_ALL_CHILDREN
314      show_all_children();      show_all_children();
315    #endif
316      updateStatus();      updateStatus();
317  }  }
318    
# Line 215  void MacrosSetup::onButtonAddFromSelecti Line 365  void MacrosSetup::onButtonAddFromSelecti
365      }      }
366  }  }
367    
368    void MacrosSetup::moveByDir(int d) {
369        if (d < -1 || d > 1) return;
370        int index = getSelectedMacroIndex();
371        if (index < 0) return;
372        if (d == -1 && index == 0) return;
373        if (d == +1 && index >= m_macros.size() - 1) return;
374    
375        // swap macros
376        std::swap(m_macros[index + d], m_macros[index]);
377    
378        // swap tree view rows
379        Gtk::TreePath p1(ToString(index + d));
380        Gtk::TreePath p2(ToString(index));
381        Gtk::TreeModel::iterator it1 = m_treeStoreMacros->get_iter(p1);
382        Gtk::TreeModel::iterator it2 = m_treeStoreMacros->get_iter(p2);
383        m_treeStoreMacros->iter_swap(it1, it2);
384        int idx1 = (*it1)[m_treeModelMacros.m_col_index];
385        int idx2 = (*it2)[m_treeModelMacros.m_col_index];
386        (*it1)[m_treeModelMacros.m_col_index] = idx2;
387        (*it2)[m_treeModelMacros.m_col_index] = idx1;
388        Glib::ustring s1 = (*it1)[m_treeModelMacros.m_col_key];
389        Glib::ustring s2 = (*it2)[m_treeModelMacros.m_col_key];
390        (*it1)[m_treeModelMacros.m_col_key] = s2;
391        (*it2)[m_treeModelMacros.m_col_key] = s1;
392    
393        m_modified = true;
394    }
395    
396    void MacrosSetup::onButtonUp() {
397        moveByDir(-1);
398    }
399    
400    void MacrosSetup::onButtonDown() {
401        moveByDir(+1);
402    }
403    
404    void MacrosSetup::onButtonDuplicate() {
405        Glib::RefPtr<Gtk::TreeSelection> sel = m_treeViewMacros.get_selection();
406        std::vector<Gtk::TreeModel::Path> rows = sel->get_selected_rows();
407        duplicateRows(rows);
408    }
409    
410    void MacrosSetup::onButtonEdit() {
411        Serialization::Archive* macro = getSelectedMacro();
412        if (!macro) return;
413    
414        m_modifiedBeforeMacroEditor = isModified();
415    
416        MacroEditor* editor = new MacroEditor();
417        editor->setMacro(macro, false);
418        editor->signal_changes_applied().connect(
419            sigc::mem_fun(*this, &MacrosSetup::onMacroEditorAppliedChanges)
420        );
421        editor->show();
422    }
423    
424    void MacrosSetup::onMacroEditorAppliedChanges() {
425        // so that the user does not need to click on a Apply buttons twice
426        if (!m_modifiedBeforeMacroEditor)
427            onButtonApply();
428        updateStatus();
429    }
430    
431    void MacrosSetup::onCommentTextViewChanged() {
432        if (m_ignoreCommentTextViewChange) return;
433        //printf("textChanged\n");
434        Serialization::Archive* macro = getSelectedMacro();
435        if (!macro) return;
436        macro->setComment(
437            m_textViewComment.get_buffer()->get_text()
438        );
439        updateStatus();
440    }
441    
442    int MacrosSetup::getSelectedMacroIndex() const {
443        std::vector<Gtk::TreeModel::Path> v = m_treeViewMacros.get_selection()->get_selected_rows();
444        if (v.empty()) return -1;
445        Gtk::TreeModel::iterator it = m_treeStoreMacros->get_iter(v[0]);
446        if (!it) return -1;
447        const Gtk::TreeModel::Row& row = *it;
448        int index = row[m_treeModelMacros.m_col_index];
449        if (index < 0 || index >= m_macros.size()) return -1;
450        return index;
451    }
452    
453    Serialization::Archive* MacrosSetup::getSelectedMacro() {
454        int index = getSelectedMacroIndex();
455        if (index < 0) return NULL;
456        return &m_macros[index];
457    }
458    
459  static Glib::ustring indexToAccKey(uint index) {  static Glib::ustring indexToAccKey(uint index) {
460      if (index >= 12) return "";      if (index >= 12) return "";
461      return "F" + ToString(index+1);      return "F" + ToString(index+1);
# Line 267  void MacrosSetup::reloadTreeView() { Line 508  void MacrosSetup::reloadTreeView() {
508          Gtk::TreeModel::Row row = *iter;          Gtk::TreeModel::Row row = *iter;
509          row[m_treeModelMacros.m_col_key] = indexToAccKey(iMacro);          row[m_treeModelMacros.m_col_key] = indexToAccKey(iMacro);
510          row[m_treeModelMacros.m_col_name] = macro.name().empty() ? _("Unnamed Macro") : gig_to_utf8(macro.name());          row[m_treeModelMacros.m_col_name] = macro.name().empty() ? _("Unnamed Macro") : gig_to_utf8(macro.name());
511          row[m_treeModelMacros.m_col_comment] = macro.comment().empty() ? _("No comment assigned yet.") : gig_to_utf8(macro.comment());          row[m_treeModelMacros.m_col_comment] = macro.comment().empty() ? _("No comment assigned to this macro yet.") : gig_to_utf8(macro.comment());
512          row[m_treeModelMacros.m_col_created] = humanShortStr(macro.dateTimeCreated());          row[m_treeModelMacros.m_col_created] = humanShortStr(macro.dateTimeCreated());
513          row[m_treeModelMacros.m_col_modified] = humanShortStr(macro.dateTimeModified());          row[m_treeModelMacros.m_col_modified] = humanShortStr(macro.dateTimeModified());
514          row[m_treeModelMacros.m_col_index] = iMacro;          row[m_treeModelMacros.m_col_index] = iMacro;
# Line 285  void MacrosSetup::onTreeViewSelectionCha Line 526  void MacrosSetup::onTreeViewSelectionCha
526      const bool bValidSelection = !v.empty();      const bool bValidSelection = !v.empty();
527      m_deleteButton.set_sensitive(bValidSelection);      m_deleteButton.set_sensitive(bValidSelection);
528      m_inverseDeleteButton.set_sensitive(bValidSelection);      m_inverseDeleteButton.set_sensitive(bValidSelection);
529        m_buttonEdit.set_sensitive(bValidSelection);
530        m_buttonDuplicate.set_sensitive(bValidSelection);
531        m_buttonUp.set_sensitive(bValidSelection);
532        m_buttonDown.set_sensitive(bValidSelection);
533    
534        // update comment text view
535        std::string sComment;
536        Serialization::Archive* macro = getSelectedMacro();
537        if (macro)
538            sComment = macro->comment();
539        m_ignoreCommentTextViewChange = true;
540        m_textViewComment.get_buffer()->set_text(sComment);
541        m_ignoreCommentTextViewChange = false;
542        m_textViewComment.set_sensitive(bValidSelection);
543  }  }
544    
545  // Cmd key on Mac, Ctrl key on all other OSs  // Cmd key on Mac, Ctrl key on all other OSs
# Line 302  static const guint primaryKeyR = Line 557  static const guint primaryKeyR =
557      GDK_KEY_Control_R;      GDK_KEY_Control_R;
558      #endif      #endif
559    
560    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION > 91 || (GTKMM_MINOR_VERSION == 91 && GTKMM_MICRO_VERSION >= 2))) // GTKMM >= 3.91.2
561    bool MacrosSetup::onKeyPressed(Gdk::EventKey& _key) {
562        GdkEventKey* key = _key.gobj();
563    #else
564  bool MacrosSetup::onKeyPressed(GdkEventKey* key) {  bool MacrosSetup::onKeyPressed(GdkEventKey* key) {
565    #endif
566      //printf("key down 0x%x\n", key->keyval);      //printf("key down 0x%x\n", key->keyval);
567      if (key->keyval == GDK_KEY_Alt_L || key->keyval == GDK_KEY_Alt_R)      if (key->keyval == GDK_KEY_Alt_L || key->keyval == GDK_KEY_Alt_R)
568          m_altKeyDown = true;          m_altKeyDown = true;
# Line 311  bool MacrosSetup::onKeyPressed(GdkEventK Line 571  bool MacrosSetup::onKeyPressed(GdkEventK
571      return false;      return false;
572  }  }
573    
574    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION > 91 || (GTKMM_MINOR_VERSION == 91 && GTKMM_MICRO_VERSION >= 2))) // GTKMM >= 3.91.2
575    bool MacrosSetup::onKeyReleased(Gdk::EventKey& _key) {
576        GdkEventKey* key = _key.gobj();
577    #else
578  bool MacrosSetup::onKeyReleased(GdkEventKey* key) {  bool MacrosSetup::onKeyReleased(GdkEventKey* key) {
579    #endif
580      //printf("key up 0x%x\n", key->keyval);      //printf("key up 0x%x\n", key->keyval);
581      if (key->keyval == GDK_KEY_Alt_L || key->keyval == GDK_KEY_Alt_R)      if (key->keyval == GDK_KEY_Alt_L || key->keyval == GDK_KEY_Alt_R)
582          m_altKeyDown = false;          m_altKeyDown = false;
# Line 324  bool MacrosSetup::onKeyReleased(GdkEvent Line 589  bool MacrosSetup::onKeyReleased(GdkEvent
589      return false;      return false;
590  }  }
591    
592    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION > 91 || (GTKMM_MINOR_VERSION == 91 && GTKMM_MICRO_VERSION >= 2))) // GTKMM >= 3.91.2
593    bool MacrosSetup::onMacroTreeViewKeyRelease(Gdk::EventKey& _key) {
594        GdkEventKey* key = _key.gobj();
595    #else
596  void MacrosSetup::onMacroTreeViewKeyRelease(GdkEventKey* key) {  void MacrosSetup::onMacroTreeViewKeyRelease(GdkEventKey* key) {
597    #endif
598      if (key->keyval == GDK_KEY_BackSpace || key->keyval == GDK_KEY_Delete) {      if (key->keyval == GDK_KEY_BackSpace || key->keyval == GDK_KEY_Delete) {
599          if (m_altKeyDown)          if (m_altKeyDown)
600              inverseDeleteSelectedRows();              inverseDeleteSelectedRows();
601          else if (m_primaryKeyDown)          else if (m_primaryKeyDown)
602              deleteSelectedRows();              deleteSelectedRows();
603      }      }
604    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION > 91 || (GTKMM_MINOR_VERSION == 91 && GTKMM_MICRO_VERSION >= 2))) // GTKMM >= 3.91.2
605        return false;
606    #endif
607  }  }
608    
609  void MacrosSetup::onMacroTreeViewRowValueChanged(const Gtk::TreeModel::Path& path,  void MacrosSetup::onMacroTreeViewRowValueChanged(const Gtk::TreeModel::Path& path,
# Line 353  void MacrosSetup::deleteSelectedRows() { Line 626  void MacrosSetup::deleteSelectedRows() {
626      deleteRows(rows);      deleteRows(rows);
627  }  }
628    
629    void MacrosSetup::duplicateRows(const std::vector<Gtk::TreeModel::Path>& rows) {
630        if (!rows.empty()) m_modified = true;
631        bool bError = false;
632        for (int r = 0; r < rows.size(); ++r) {
633            Gtk::TreeModel::iterator it = m_treeStoreMacros->get_iter(rows[r]);
634            if (!it) continue;
635            Gtk::TreeModel::Row row = *it;
636            int index = row[m_treeModelMacros.m_col_index];
637            if (index < 0 || index >= m_macros.size()) continue;
638    
639            Serialization::Archive clone = m_macros[index];
640            if (!endsWith(clone.name(), "COPY", true)) {
641                clone.setName(
642                    (clone.name().empty()) ? "Unnamed COPY" : (clone.name() + " COPY")
643                );
644            }
645            try {
646                // enforce re-encoding the abstract object model and resetting the
647                // 'modified' state
648                clone.rawData();
649            } catch (Serialization::Exception e) {
650                bError = true;
651                e.PrintMessage();
652                continue;
653            } catch (...) {
654                bError = true;
655                std::cerr << "Unknown exception while cloning macro." << std::endl;
656                continue;
657            }
658            // finally add new cloned macro
659            m_macros.push_back(clone);
660        }
661        reloadTreeView();
662        if (bError) {
663            Glib::ustring txt = _("At least one of the macros could not be cloned due to an error (check console output).");
664            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
665            msg.run();
666        }
667    }
668    
669  void MacrosSetup::deleteRows(const std::vector<Gtk::TreeModel::Path>& rows) {  void MacrosSetup::deleteRows(const std::vector<Gtk::TreeModel::Path>& rows) {
670      m_modified = !rows.empty();      if (!rows.empty()) m_modified = true;
671      std::set<int> macros;      std::set<int> macros;
672      for (int r = rows.size() - 1; r >= 0; --r) {      for (int r = rows.size() - 1; r >= 0; --r) {
673          Gtk::TreeModel::iterator it = m_treeStoreMacros->get_iter(rows[r]);          Gtk::TreeModel::iterator it = m_treeStoreMacros->get_iter(rows[r]);
# Line 401  void MacrosSetup::inverseDeleteSelectedR Line 714  void MacrosSetup::inverseDeleteSelectedR
714  }  }
715    
716  void MacrosSetup::updateStatus() {  void MacrosSetup::updateStatus() {
717        bool bValidSelection = !m_treeViewMacros.get_selection()->get_selected_rows().empty();
718      m_addFromClipboardButton.set_sensitive(      m_addFromClipboardButton.set_sensitive(
719          m_clipboardContent && m_clipboardContent->rootObject()          m_clipboardContent && m_clipboardContent->rootObject()
720      );      );
721      m_addFromSelectionButton.set_sensitive(m_selectedDimRgn);      m_addFromSelectionButton.set_sensitive(m_selectedDimRgn);
722        m_buttonEdit.set_sensitive(bValidSelection);
723        m_buttonDuplicate.set_sensitive(bValidSelection);
724        m_buttonUp.set_sensitive(bValidSelection);
725        m_buttonDown.set_sensitive(bValidSelection);
726      m_applyButton.set_sensitive(isModified());      m_applyButton.set_sensitive(isModified());
727        m_textViewComment.set_sensitive(bValidSelection);
728      updateStatusBar();      updateStatusBar();
729  }  }
730    
# Line 419  sigc::signal<void, const std::vector<Ser Line 738  sigc::signal<void, const std::vector<Ser
738  {  {
739      return m_macros_changed;      return m_macros_changed;
740  }  }
741        
742    #if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION > 91 || (GTKMM_MINOR_VERSION == 91 && GTKMM_MICRO_VERSION >= 2))) // GTKMM >= 3.91.2
743    bool MacrosSetup::onWindowDelete(Gdk::Event& e) {
744        return onWindowDeleteP(NULL);
745    }
746    #endif
747    
748  bool MacrosSetup::onWindowDelete(GdkEventAny* e) {  bool MacrosSetup::onWindowDeleteP(GdkEventAny* /*e*/) {
749      //printf("onWindowDelete\n");      //printf("onWindowDelete\n");
750    
751      if (!isModified()) return false; // propagate event further (which will close this window)      if (!isModified()) return false; // propagate event further (which will close this window)
# Line 471  bool MacrosSetup::isModified() const { Line 796  bool MacrosSetup::isModified() const {
796  }  }
797    
798  void MacrosSetup::onButtonCancel() {  void MacrosSetup::onButtonCancel() {
799      bool dropEvent = onWindowDelete(NULL);      bool dropEvent = onWindowDeleteP(NULL);
800      if (dropEvent) return;      if (dropEvent) return;
801      hide();      hide();
802  }  }

Legend:
Removed from v.3161  
changed lines
  Added in v.3366

  ViewVC Help
Powered by ViewVC