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

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

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

revision 3151 by schoenebeck, Fri May 5 18:44:59 2017 UTC revision 3162 by schoenebeck, Tue May 9 14:35:23 2017 UTC
# Line 12  Line 12 
12  MacroEditor::MacroEditor() :  MacroEditor::MacroEditor() :
13      m_macroOriginal(NULL),      m_macroOriginal(NULL),
14      m_statusLabel("",  Gtk::ALIGN_START),      m_statusLabel("",  Gtk::ALIGN_START),
15        m_deleteButton(Glib::ustring(_("Delete")) + " " + UNICODE_PRIMARY_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL),
16        m_inverseDeleteButton(Glib::ustring(_("Inverse Delete")) + " " + UNICODE_ALT_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL),
17      m_applyButton(_("_Apply"), true),      m_applyButton(_("_Apply"), true),
18      m_cancelButton(_("_Cancel"), true)      m_cancelButton(_("_Cancel"), true),
19        m_altKeyDown(false)
20  {  {
21      add(m_vbox);      add(m_vbox);
22    
23      set_default_size(800, 600);      set_default_size(800, 600);
24    
25        //FIXME: Commented out since Gtk::Label is a disaster when it comes to multi line content.
26        /*m_labelIntro.set_text(
27            _("A macro is a list of parameters and corresponding values which "
28              "should be applied to the instrument editor when the macro is "
29              "triggered by the user. A macro is triggered either by selecting "
30              "the macro from the \"Macro\" menu, or by hitting the macro's "
31              "respective keyboard accelerator (F1 to F12).")
32        );
33        m_labelIntro.set_line_wrap();
34        m_vbox.pack_start(m_labelIntro, Gtk::PACK_SHRINK);*/
35    
36      // create Macro treeview (including its data model)      // create Macro treeview (including its data model)
37      m_treeStoreMacro = MacroTreeStore::create(m_treeModelMacro);      m_treeStoreMacro = MacroTreeStore::create(m_treeModelMacro);
38      m_treeViewMacro.set_model(m_treeStoreMacro);      m_treeViewMacro.set_model(m_treeStoreMacro);
# Line 27  MacroEditor::MacroEditor() : Line 41  MacroEditor::MacroEditor() :
41      m_treeViewMacro.append_column(_("Key"), m_treeModelMacro.m_col_name);      m_treeViewMacro.append_column(_("Key"), m_treeModelMacro.m_col_name);
42      m_treeViewMacro.append_column(_("Type"), m_treeModelMacro.m_col_type);      m_treeViewMacro.append_column(_("Type"), m_treeModelMacro.m_col_type);
43      m_treeViewMacro.append_column_editable(_("Value"), m_treeModelMacro.m_col_value);      m_treeViewMacro.append_column_editable(_("Value"), m_treeModelMacro.m_col_value);
44        {
45            Gtk::TreeViewColumn* column = m_treeViewMacro.get_column(1);
46            Gtk::CellRendererText* cellrenderer =
47                dynamic_cast<Gtk::CellRendererText*>(column->get_first_cell());
48            cellrenderer->property_foreground().set_value("#bababa");
49        }
50      /*{      /*{
51          Gtk::TreeViewColumn* column = m_treeViewMacro.get_column(0);          Gtk::TreeViewColumn* column = m_treeViewMacro.get_column(0);
52          Gtk::CellRendererText* cellrenderer =          Gtk::CellRendererText* cellrenderer =
# Line 44  MacroEditor::MacroEditor() : Line 64  MacroEditor::MacroEditor() :
64          );          );
65      }*/      }*/
66      m_treeViewMacro.set_headers_visible(true);      m_treeViewMacro.set_headers_visible(true);
67      /*m_treeViewMacro.signal_button_press_event().connect_notify(      m_treeViewMacro.get_selection()->signal_changed().connect(
68          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_button_release)          sigc::mem_fun(*this, &MacroEditor::onTreeViewSelectionChanged)
69      );*/      );
70      /*m_refSamplesTreeModel->signal_row_changed().connect(      m_treeViewMacro.signal_key_release_event().connect_notify(
71          sigc::mem_fun(*this, &MainWindow::sample_name_changed)          sigc::mem_fun(*this, &MacroEditor::onMacroTreeViewKeyRelease)
72      );*/      );
73        m_treeStoreMacro->signal_row_changed().connect(
74            sigc::mem_fun(*this, &MacroEditor::onMacroTreeViewRowValueChanged)
75        );
76        m_ignoreTreeViewValueChange = false;
77    
78      m_scrolledWindow.add(m_treeViewMacro);      m_scrolledWindow.add(m_treeViewMacro);
79      m_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);      m_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
80      m_vbox.pack_start(m_scrolledWindow);      m_vbox.pack_start(m_scrolledWindow);
81    
82        m_buttonBoxL.set_layout(Gtk::BUTTONBOX_START);
83        m_buttonBoxL.pack_start(m_deleteButton);
84        m_buttonBoxL.pack_start(m_inverseDeleteButton);
85        m_deleteButton.set_sensitive(false);
86        m_inverseDeleteButton.set_sensitive(false);
87    
88      m_buttonBox.set_layout(Gtk::BUTTONBOX_END);      m_buttonBox.set_layout(Gtk::BUTTONBOX_END);
89      m_buttonBox.pack_start(m_applyButton);      m_buttonBox.pack_start(m_applyButton);
90      m_buttonBox.pack_start(m_cancelButton);      m_buttonBox.pack_start(m_cancelButton);
# Line 72  MacroEditor::MacroEditor() : Line 102  MacroEditor::MacroEditor() :
102      m_statusHBox.pack_start(m_statusLabel);      m_statusHBox.pack_start(m_statusLabel);
103      m_statusHBox.show_all_children();      m_statusHBox.show_all_children();
104    
105        m_footerHBox.pack_start(m_buttonBoxL, Gtk::PACK_SHRINK);
106      m_footerHBox.pack_start(m_statusHBox);      m_footerHBox.pack_start(m_statusHBox);
107      m_footerHBox.pack_start(m_buttonBox, Gtk::PACK_SHRINK);      m_footerHBox.pack_start(m_buttonBox, Gtk::PACK_SHRINK);
108    
# Line 85  MacroEditor::MacroEditor() : Line 116  MacroEditor::MacroEditor() :
116          sigc::mem_fun(*this, &MacroEditor::onButtonCancel)          sigc::mem_fun(*this, &MacroEditor::onButtonCancel)
117      );      );
118    
119        m_deleteButton.signal_clicked().connect(
120            sigc::mem_fun(*this, &MacroEditor::deleteSelectedRows)
121        );
122    
123        m_inverseDeleteButton.signal_clicked().connect(
124            sigc::mem_fun(*this, &MacroEditor::inverseDeleteSelectedRows)
125        );
126    
127      signal_hide().connect(      signal_hide().connect(
128          sigc::mem_fun(*this, &MacroEditor::onWindowHide)          sigc::mem_fun(*this, &MacroEditor::onWindowHide)
129      );      );
# Line 93  MacroEditor::MacroEditor() : Line 132  MacroEditor::MacroEditor() :
132          sigc::mem_fun(*this, &MacroEditor::onWindowDelete)          sigc::mem_fun(*this, &MacroEditor::onWindowDelete)
133      );      );
134    
135        signal_key_press_event().connect(
136            sigc::mem_fun(*this, &MacroEditor::onKeyPressed)
137        );
138        signal_key_release_event().connect(
139            sigc::mem_fun(*this, &MacroEditor::onKeyReleased)
140        );
141    
142      show_all_children();      show_all_children();
143      updateStatus();      updateStatus();
144  }  }
# Line 101  MacroEditor::~MacroEditor() { Line 147  MacroEditor::~MacroEditor() {
147      printf("MacroEditor destruct\n");      printf("MacroEditor destruct\n");
148  }  }
149    
150  void MacroEditor::setMacro(Serialization::Archive* macro) {  void MacroEditor::setMacro(Serialization::Archive* macro, bool isClipboard) {
151      m_macroOriginal = macro;      m_macroOriginal = macro;
152      if (!macro) {      if (!macro) {
153          set_title(_("No Macro"));          set_title(_("No Macro"));
154          return;          return;
155      }      }
156    
157      //set_title(std::string(_("Macro Editor:")) + " \"" + macro->name() + "\"");      if (isClipboard)
158      set_title(std::string(_("Macro Editor:")));          set_title(std::string(_("Macro Editor:")) + " " + _("Clipboard Content"));
159        else {
160            if (macro->name().empty())
161                set_title(std::string(_("Macro Editor:")) + " " + _("Unnamed Macro"));
162            else
163                set_title(std::string(_("Macro Editor:")) + " \"" + macro->name() + "\"");
164        }
165    
166      // copy for non-destructive editing      // copy for non-destructive editing
167      m_macro = *macro;      m_macro = *macro;
# Line 117  void MacroEditor::setMacro(Serialization Line 169  void MacroEditor::setMacro(Serialization
169      reloadTreeView();      reloadTreeView();
170  }  }
171    
172    sigc::signal<void>& MacroEditor::signal_changes_applied() {
173        return m_changes_applied;
174    }
175    
176  void MacroEditor::buildTreeView(const Gtk::TreeModel::Row& parentRow, const Serialization::Object& parentObject) {  void MacroEditor::buildTreeView(const Gtk::TreeModel::Row& parentRow, const Serialization::Object& parentObject) {
177      for (int iMember = 0; iMember < parentObject.members().size(); ++iMember) {      for (int iMember = 0; iMember < parentObject.members().size(); ++iMember) {
178          const Serialization::Member& member = parentObject.members()[iMember];          const Serialization::Member& member = parentObject.members()[iMember];
# Line 136  void MacroEditor::buildTreeView(const Gt Line 192  void MacroEditor::buildTreeView(const Gt
192  }  }
193    
194  void MacroEditor::reloadTreeView() {  void MacroEditor::reloadTreeView() {
195        m_ignoreTreeViewValueChange = true;
196    
197      m_treeStoreMacro->clear();      m_treeStoreMacro->clear();
198    
199      const Serialization::Object& rootObject = m_macro.rootObject();      const Serialization::Object& rootObject = m_macro.rootObject();
# Line 152  void MacroEditor::reloadTreeView() { Line 210  void MacroEditor::reloadTreeView() {
210      m_treeViewMacro.expand_all();      m_treeViewMacro.expand_all();
211    
212      updateStatus();      updateStatus();
213    
214        m_ignoreTreeViewValueChange = false;
215    }
216    
217    void MacroEditor::onTreeViewSelectionChanged() {
218        std::vector<Gtk::TreeModel::Path> v = m_treeViewMacro.get_selection()->get_selected_rows();
219        const bool bValidSelection = !v.empty();
220        m_deleteButton.set_sensitive(bValidSelection);
221        m_inverseDeleteButton.set_sensitive(bValidSelection);
222    }
223    
224    bool MacroEditor::onKeyPressed(GdkEventKey* key) {
225        //printf("key down 0x%x\n", key->keyval);
226        if (key->keyval == GDK_KEY_Alt_L || key->keyval == GDK_KEY_Alt_R)
227            m_altKeyDown = true;
228        return false;
229    }
230    
231    bool MacroEditor::onKeyReleased(GdkEventKey* key) {
232        //printf("key up 0x%x\n", key->keyval);
233        if (key->keyval == GDK_KEY_Alt_L || key->keyval == GDK_KEY_Alt_R)
234            m_altKeyDown = false;
235        return false;
236    }
237    
238    void MacroEditor::onMacroTreeViewKeyRelease(GdkEventKey* key) {
239        if (key->keyval == GDK_KEY_BackSpace || key->keyval == GDK_KEY_Delete) {
240            if (m_altKeyDown)
241                inverseDeleteSelectedRows();
242            else
243                deleteSelectedRows();
244        }
245    }
246    
247    void MacroEditor::onMacroTreeViewRowValueChanged(const Gtk::TreeModel::Path& path,
248                                                     const Gtk::TreeModel::iterator& iter)
249    {
250        if (m_ignoreTreeViewValueChange) return;
251        if (!iter) return;
252        Gtk::TreeModel::Row row = *iter;
253        Glib::ustring value    = row[m_treeModelMacro.m_col_value];
254        Serialization::UID uid = row[m_treeModelMacro.m_col_uid];
255        Serialization::String gigvalue(gig_from_utf8(value));
256        Serialization::Object& object = m_macro.objectByUID(uid);
257        std::string errorText;
258        try {
259            m_macro.setAutoValue(object, gigvalue);
260        } catch (Serialization::Exception e) {
261            errorText = e.Message;
262        } catch (...) {
263            errorText = _("Unknown exception during object value change");
264        }
265        if (!errorText.empty()) {
266            Glib::ustring txt = _("Couldn't change value:\n") + errorText;
267            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
268            msg.run();
269        }
270    }
271    
272    void MacroEditor::deleteSelectedRows() {
273        Glib::RefPtr<Gtk::TreeSelection> sel = m_treeViewMacro.get_selection();
274        std::vector<Gtk::TreeModel::Path> rows = sel->get_selected_rows();
275        deleteRows(rows);
276    }
277    
278    void MacroEditor::deleteRows(const std::vector<Gtk::TreeModel::Path>& rows) {
279        for (int r = rows.size() - 1; r >= 0; --r) {
280            Gtk::TreeModel::iterator it = m_treeStoreMacro->get_iter(rows[r]);
281            if (!it) continue;
282            Gtk::TreeModel::Row row = *it;
283            Serialization::UID uid = row[m_treeModelMacro.m_col_uid];
284            if (uid == m_macro.rootObject().uid()) continue; // prohibit deleting root object
285            Gtk::TreeModel::iterator itParent = row.parent();
286            if (!itParent) continue;
287            Gtk::TreeModel::Row rowParent = *itParent;
288            Serialization::UID uidParent = rowParent[m_treeModelMacro.m_col_uid];
289            //Serialization::Object& object = m_macro.objectByUID(uid);
290            Serialization::Object& parentObject = m_macro.objectByUID(uidParent);
291            const Serialization::Member& member = parentObject.memberByUID(uid);
292            m_macro.removeMember(parentObject, member);
293            //m_macro.remove(object);
294        }
295        reloadTreeView();
296    }
297    
298    static bool _onEachTreeRow(const Gtk::TreeModel::Path& input, std::vector<Gtk::TreeModel::Path>* output) {
299        output->push_back(input);
300        return false; // continue walking the tree
301    }
302    
303    void MacroEditor::inverseDeleteSelectedRows() {
304        // get all rows of tree view
305        std::vector<Gtk::TreeModel::Path> rows;
306        m_treeViewMacro.get_model()->foreach_path(
307            sigc::bind(
308                sigc::ptr_fun(&_onEachTreeRow),
309                &rows
310            )
311        );
312    
313        // erase all entries from "rows" which are currently selected
314        std::vector<Gtk::TreeModel::Path> vSelected = m_treeViewMacro.get_selection()->get_selected_rows();
315        for (int i = rows.size() - 1; i >= 0; --i) {
316            bool bIsSelected = std::find(vSelected.begin(), vSelected.end(),
317                                         rows[i]) != vSelected.end();
318            if (bIsSelected)
319                rows.erase(rows.begin() + i);
320        }
321    
322        // delete those 'inverse' selected rows
323        deleteRows(rows);
324  }  }
325    
326  void MacroEditor::updateStatus() {  void MacroEditor::updateStatus() {
# Line 214  void MacroEditor::onButtonCancel() { Line 383  void MacroEditor::onButtonCancel() {
383  }  }
384    
385  void MacroEditor::onButtonApply() {  void MacroEditor::onButtonApply() {
386      //m_macro.encode();      std::string errorText;
387      *m_macroOriginal = m_macro;      try {
388            // enforce re-encoding the abstract object model and resetting the
389            // 'modified' state
390            m_macro.rawData();
391            // replace actual effective Archive object which is effectively used
392            // for macro apply operations
393            *m_macroOriginal = m_macro;
394        } catch (Serialization::Exception e) {
395            errorText = e.Message;
396        } catch (...) {
397            errorText = _("Unknown exception while applying macro changes");
398        }
399        if (!errorText.empty()) {
400            Glib::ustring txt = _("Couldn't apply macro changes:\n") + errorText;
401            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
402            msg.run();
403        }
404        updateStatus();
405        m_changes_applied.emit();
406  }  }
407    
408  void MacroEditor::onWindowHide() {  void MacroEditor::onWindowHide() {

Legend:
Removed from v.3151  
changed lines
  Added in v.3162

  ViewVC Help
Powered by ViewVC