/[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 3154 by schoenebeck, Sat May 6 13:46:14 2017 UTC revision 3184 by schoenebeck, Wed May 17 12:28:39 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(_("Delete")),      m_deleteButton(Glib::ustring(_("Delete")) + " " + UNICODE_PRIMARY_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL),
16      m_inverseDeleteButton(_("Inverse Delete")),      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        m_primaryKeyDown(false)
21  {  {
22      add(m_vbox);      add(m_vbox);
23    
24      set_default_size(800, 600);      set_default_size(800, 600);
25    
26        m_labelIntro.set_padding(10, 10);
27    #if GTKMM_MAJOR_VERSION >= 3
28        m_labelIntro.set_line_wrap();
29    #endif
30        m_labelIntro.set_text(
31            _("A macro is a list of parameters and corresponding values which "
32              "should be applied to the instrument editor when the macro is "
33              "triggered by the user. Only the parameters listed here will be "
34              "applied to the instrument editor when this macro is triggered, all "
35              "other ones remain untouched. So simply delete parameters here which "
36              "you don't want to be modified by this macro. Double click on a "
37              "value to change it.")
38        );
39        m_vbox.pack_start(m_labelIntro, Gtk::PACK_SHRINK);
40    
41      // create Macro treeview (including its data model)      // create Macro treeview (including its data model)
42      m_treeStoreMacro = MacroTreeStore::create(m_treeModelMacro);      m_treeStoreMacro = MacroTreeStore::create(m_treeModelMacro);
43      m_treeViewMacro.set_model(m_treeStoreMacro);      m_treeViewMacro.set_model(m_treeStoreMacro);
# Line 28  MacroEditor::MacroEditor() : Line 45  MacroEditor::MacroEditor() :
45      //m_treeViewMacro.set_tooltip_text(_(""));      //m_treeViewMacro.set_tooltip_text(_(""));
46      m_treeViewMacro.append_column(_("Key"), m_treeModelMacro.m_col_name);      m_treeViewMacro.append_column(_("Key"), m_treeModelMacro.m_col_name);
47      m_treeViewMacro.append_column(_("Type"), m_treeModelMacro.m_col_type);      m_treeViewMacro.append_column(_("Type"), m_treeModelMacro.m_col_type);
48      m_treeViewMacro.append_column_editable(_("Value"), m_treeModelMacro.m_col_value);      //m_treeViewMacro.append_column_editable(_("Value"), m_treeModelMacro.m_col_value);
49        //m_treeViewMacro.append_column(_("Value"), m_valueCellRenderer);
50        Gtk::TreeViewColumn* valueColumn = new Gtk::TreeViewColumn(_("Value"));
51        valueColumn->pack_start(m_valueCellRenderer);
52        m_treeViewMacro.append_column(*valueColumn);
53        // m_valueCellRenderer.property_model() = m_comboBoxModel;
54        // m_valueCellRenderer.property_text_column() = 0;
55        //m_valueCellRenderer.property_editable() = true;
56        {
57            Gtk::TreeView::Column* column = valueColumn;// m_treeViewMacro.get_column(2);
58            //column->set_renderer(m_valueCellRenderer, m_treeModelMacro.m_col_value);
59            column->add_attribute(m_valueCellRenderer.property_text(),
60                                  m_treeModelMacro.m_col_value);
61            //column->add_attribute(m_valueCellRenderer.property_has_entry(),
62            //                      m_treeModelMacro.m_col_allowTextEntry);
63            column->add_attribute(m_valueCellRenderer.property_editable(),
64                                  m_treeModelMacro.m_col_editable);
65            column->add_attribute(m_valueCellRenderer.property_model(),
66                                  m_treeModelMacro.m_col_options);
67        }
68        m_valueCellRenderer.property_text_column() = 0;
69        m_valueCellRenderer.signal_edited().connect(
70            sigc::mem_fun(*this, &MacroEditor::onValueCellEdited)
71        );
72    
73      {      {
74          Gtk::TreeViewColumn* column = m_treeViewMacro.get_column(1);          Gtk::TreeViewColumn* column = m_treeViewMacro.get_column(1);
75          Gtk::CellRendererText* cellrenderer =          Gtk::CellRendererText* cellrenderer =
76              dynamic_cast<Gtk::CellRendererText*>(column->get_first_cell());              dynamic_cast<Gtk::CellRendererText*>(column->get_first_cell());
77          cellrenderer->property_foreground().set_value("#bababa");          cellrenderer->property_foreground().set_value("#bababa");
78      }      }
     /*{  
         Gtk::TreeViewColumn* column = m_treeViewMacro.get_column(0);  
         Gtk::CellRendererText* cellrenderer =  
             dynamic_cast<Gtk::CellRendererText*>(column->get_first_cell());  
         column->add_attribute(  
             cellrenderer->property_foreground(), m_SamplesModel.m_color  
         );  
     }*/  
     /*{  
         Gtk::TreeViewColumn* column = m_treeViewMacro.get_column(1);  
         Gtk::CellRendererText* cellrenderer =  
             dynamic_cast<Gtk::CellRendererText*>(column->get_first_cell());  
         column->add_attribute(  
             cellrenderer->property_foreground(), m_SamplesModel.m_color  
         );  
     }*/  
79      m_treeViewMacro.set_headers_visible(true);      m_treeViewMacro.set_headers_visible(true);
80      m_treeViewMacro.get_selection()->signal_changed().connect(      m_treeViewMacro.get_selection()->signal_changed().connect(
81          sigc::mem_fun(*this, &MacroEditor::onTreeViewSelectionChanged)          sigc::mem_fun(*this, &MacroEditor::onTreeViewSelectionChanged)
# Line 120  MacroEditor::MacroEditor() : Line 145  MacroEditor::MacroEditor() :
145          sigc::mem_fun(*this, &MacroEditor::onWindowDelete)          sigc::mem_fun(*this, &MacroEditor::onWindowDelete)
146      );      );
147    
148        signal_key_press_event().connect(
149            sigc::mem_fun(*this, &MacroEditor::onKeyPressed)
150        );
151        signal_key_release_event().connect(
152            sigc::mem_fun(*this, &MacroEditor::onKeyReleased)
153        );
154    
155        m_deleteButton.set_tooltip_text(_("Delete the selected parameters from this macro."));
156        m_inverseDeleteButton.set_tooltip_text(_("Delete all parameters from this macro except the selected ones."));
157    
158      show_all_children();      show_all_children();
159      updateStatus();      updateStatus();
160  }  }
# Line 128  MacroEditor::~MacroEditor() { Line 163  MacroEditor::~MacroEditor() {
163      printf("MacroEditor destruct\n");      printf("MacroEditor destruct\n");
164  }  }
165    
166  void MacroEditor::setMacro(Serialization::Archive* macro) {  void MacroEditor::setMacro(Serialization::Archive* macro, bool isClipboard) {
167      m_macroOriginal = macro;      m_macroOriginal = macro;
168      if (!macro) {      if (!macro) {
169          set_title(_("No Macro"));          set_title(_("No Macro"));
170          return;          return;
171      }      }
172    
173      //set_title(std::string(_("Macro Editor:")) + " \"" + macro->name() + "\"");      if (isClipboard)
174      set_title(std::string(_("Macro Editor:")));          set_title(std::string(_("Macro Editor:")) + " " + _("Clipboard Content"));
175        else {
176            if (macro->name().empty())
177                set_title(std::string(_("Macro Editor:")) + " " + _("Unnamed Macro"));
178            else
179                set_title(std::string(_("Macro Editor:")) + " \"" + macro->name() + "\"");
180        }
181    
182      // copy for non-destructive editing      // copy for non-destructive editing
183      m_macro = *macro;      m_macro = *macro;
# Line 144  void MacroEditor::setMacro(Serialization Line 185  void MacroEditor::setMacro(Serialization
185      reloadTreeView();      reloadTreeView();
186  }  }
187    
188    sigc::signal<void>& MacroEditor::signal_changes_applied() {
189        return m_changes_applied;
190    }
191    
192    Glib::RefPtr<Gtk::ListStore> MacroEditor::createComboOptions(const char** options) {
193        Glib::RefPtr<Gtk::ListStore> refOptions = Gtk::ListStore::create(m_comboOptionsModel);
194        for (size_t i = 0; options[i]; ++i)
195            (*refOptions->append())[m_comboOptionsModel.m_col_choice] = options[i];
196        return refOptions;
197    }
198    
199  void MacroEditor::buildTreeView(const Gtk::TreeModel::Row& parentRow, const Serialization::Object& parentObject) {  void MacroEditor::buildTreeView(const Gtk::TreeModel::Row& parentRow, const Serialization::Object& parentObject) {
200      for (int iMember = 0; iMember < parentObject.members().size(); ++iMember) {      for (int iMember = 0; iMember < parentObject.members().size(); ++iMember) {
201          const Serialization::Member& member = parentObject.members()[iMember];          const Serialization::Member& member = parentObject.members()[iMember];
# Line 153  void MacroEditor::buildTreeView(const Gt Line 205  void MacroEditor::buildTreeView(const Gt
205          row[m_treeModelMacro.m_col_name] = gig_to_utf8(member.name());          row[m_treeModelMacro.m_col_name] = gig_to_utf8(member.name());
206          row[m_treeModelMacro.m_col_type] = gig_to_utf8(member.type().asLongDescr());          row[m_treeModelMacro.m_col_type] = gig_to_utf8(member.type().asLongDescr());
207          row[m_treeModelMacro.m_col_uid]  = object.uid();          row[m_treeModelMacro.m_col_uid]  = object.uid();
208            row[m_treeModelMacro.m_col_allowTextEntry] = false;
209    
210          if (object.type().isClass()) {          if (object.type().isClass()) {
211              row[m_treeModelMacro.m_col_value] = "(class)";              row[m_treeModelMacro.m_col_value] = "(class)";
212                row[m_treeModelMacro.m_col_editable] = false;
213              buildTreeView(row, object);              buildTreeView(row, object);
214            } else if (object.type().isEnum()) {
215                const char* key = gig::enumKey(
216                    object.type().customTypeName(), m_macro.valueAsInt(object)
217                );
218                row[m_treeModelMacro.m_col_value] = key ? key : m_macro.valueAsString(object);
219                row[m_treeModelMacro.m_col_editable] = true;
220                const char** allKeys = gig::enumKeys(object.type().customTypeName());
221                if (allKeys) {
222                    Glib::RefPtr<Gtk::ListStore> refOptions = createComboOptions(allKeys);
223                    row[m_treeModelMacro.m_col_options] = refOptions;
224                }
225          } else {          } else {
226              row[m_treeModelMacro.m_col_value] = m_macro.valueAsString(object);              row[m_treeModelMacro.m_col_value] = m_macro.valueAsString(object);
227                row[m_treeModelMacro.m_col_editable] = true;
228          }          }
229      }      }
230  }  }
# Line 175  void MacroEditor::reloadTreeView() { Line 242  void MacroEditor::reloadTreeView() {
242      rowRoot[m_treeModelMacro.m_col_type]  = gig_to_utf8(rootObject.type().asLongDescr());      rowRoot[m_treeModelMacro.m_col_type]  = gig_to_utf8(rootObject.type().asLongDescr());
243      rowRoot[m_treeModelMacro.m_col_value] = "";      rowRoot[m_treeModelMacro.m_col_value] = "";
244      rowRoot[m_treeModelMacro.m_col_uid]   = rootObject.uid();      rowRoot[m_treeModelMacro.m_col_uid]   = rootObject.uid();
245        rowRoot[m_treeModelMacro.m_col_allowTextEntry] = false;
246        rowRoot[m_treeModelMacro.m_col_editable] = false;
247    
248      buildTreeView(rowRoot, rootObject);      buildTreeView(rowRoot, rootObject);
249    
# Line 192  void MacroEditor::onTreeViewSelectionCha Line 261  void MacroEditor::onTreeViewSelectionCha
261      m_inverseDeleteButton.set_sensitive(bValidSelection);      m_inverseDeleteButton.set_sensitive(bValidSelection);
262  }  }
263    
264    // Cmd key on Mac, Ctrl key on all other OSs
265    static const guint primaryKeyL =
266        #if defined(__APPLE__)
267        GDK_KEY_Meta_L;
268        #else
269        GDK_KEY_Control_L;
270        #endif
271    
272    static const guint primaryKeyR =
273        #if defined(__APPLE__)
274        GDK_KEY_Meta_R;
275        #else
276        GDK_KEY_Control_R;
277        #endif
278    
279    bool MacroEditor::onKeyPressed(GdkEventKey* key) {
280        //printf("key down 0x%x\n", key->keyval);
281        if (key->keyval == GDK_KEY_Alt_L || key->keyval == GDK_KEY_Alt_R)
282            m_altKeyDown = true;
283        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
284            m_primaryKeyDown = true;
285        return false;
286    }
287    
288    bool MacroEditor::onKeyReleased(GdkEventKey* key) {
289        //printf("key up 0x%x\n", key->keyval);
290        if (key->keyval == GDK_KEY_Alt_L || key->keyval == GDK_KEY_Alt_R)
291            m_altKeyDown = false;
292        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
293            m_primaryKeyDown = false;
294        return false;
295    }
296    
297  void MacroEditor::onMacroTreeViewKeyRelease(GdkEventKey* key) {  void MacroEditor::onMacroTreeViewKeyRelease(GdkEventKey* key) {
298      if (key->keyval == GDK_KEY_BackSpace || key->keyval == GDK_KEY_Delete)      if (key->keyval == GDK_KEY_BackSpace || key->keyval == GDK_KEY_Delete) {
299          deleteSelectedRows();          if (m_altKeyDown)
300                inverseDeleteSelectedRows();
301            else if (m_primaryKeyDown)
302                deleteSelectedRows();
303        }
304    }
305    
306    void MacroEditor::onValueCellEdited(const Glib::ustring& sPath, const Glib::ustring& text) {
307        Gtk::TreePath path(sPath);
308        Gtk::TreeModel::iterator iter = m_treeStoreMacro->get_iter(path);
309        onMacroTreeViewRowValueChangedImpl(path, iter, text);
310  }  }
311    
312  void MacroEditor::onMacroTreeViewRowValueChanged(const Gtk::TreeModel::Path& path,  void MacroEditor::onMacroTreeViewRowValueChanged(const Gtk::TreeModel::Path& path,
313                                                   const Gtk::TreeModel::iterator& iter)                                                   const Gtk::TreeModel::iterator& iter)
314  {  {
315        if (!iter) return;
316        Gtk::TreeModel::Row row = *iter;
317        Glib::ustring value = row[m_treeModelMacro.m_col_value];
318        onMacroTreeViewRowValueChangedImpl(path, iter, value);
319    }
320    
321    void MacroEditor::onMacroTreeViewRowValueChangedImpl(const Gtk::TreeModel::Path& path,
322                                                         const Gtk::TreeModel::iterator& iter,
323                                                         const Glib::ustring& value)
324    {
325      if (m_ignoreTreeViewValueChange) return;      if (m_ignoreTreeViewValueChange) return;
326      if (!iter) return;      if (!iter) return;
327      Gtk::TreeModel::Row row = *iter;      Gtk::TreeModel::Row row = *iter;
     Glib::ustring value    = row[m_treeModelMacro.m_col_value];  
328      Serialization::UID uid = row[m_treeModelMacro.m_col_uid];      Serialization::UID uid = row[m_treeModelMacro.m_col_uid];
329      Serialization::String gigvalue(gig_from_utf8(value));      Serialization::String gigvalue(gig_from_utf8(value));
330      Serialization::Object& object = m_macro.objectByUID(uid);      Serialization::Object& object = m_macro.objectByUID(uid);
331      std::string errorText;      std::string errorText;
332      try {      try {
333          m_macro.setAutoValue(object, gigvalue);          if (object.type().isEnum() &&
334                gig::enumKey(object.type().customTypeName(), gigvalue))
335            {
336                size_t iValue = gig::enumValue(gigvalue);
337                m_macro.setAutoValue(object, ToString(iValue));
338                // no auto correct here yet (due to numeric vs. textual values)
339                if (row[m_treeModelMacro.m_col_value] != value)
340                    row[m_treeModelMacro.m_col_value] = value;
341            } else {
342                m_macro.setAutoValue(object, gigvalue);
343                // potentially auto correct (i.e. when type is bool, user entered 5 -> yields 1)
344                if (row[m_treeModelMacro.m_col_value] != m_macro.valueAsString(object))
345                    row[m_treeModelMacro.m_col_value] = m_macro.valueAsString(object);
346            }
347            updateStatus();
348      } catch (Serialization::Exception e) {      } catch (Serialization::Exception e) {
349          errorText = e.Message;          errorText = e.Message;
350      } catch (...) {      } catch (...) {
# Line 225  void MacroEditor::onMacroTreeViewRowValu Line 360  void MacroEditor::onMacroTreeViewRowValu
360  void MacroEditor::deleteSelectedRows() {  void MacroEditor::deleteSelectedRows() {
361      Glib::RefPtr<Gtk::TreeSelection> sel = m_treeViewMacro.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_treeViewMacro.get_selection();
362      std::vector<Gtk::TreeModel::Path> rows = sel->get_selected_rows();      std::vector<Gtk::TreeModel::Path> rows = sel->get_selected_rows();
363        deleteRows(rows);
364    }
365    
366    void MacroEditor::deleteRows(const std::vector<Gtk::TreeModel::Path>& rows) {
367      for (int r = rows.size() - 1; r >= 0; --r) {      for (int r = rows.size() - 1; r >= 0; --r) {
368          Gtk::TreeModel::iterator it = m_treeStoreMacro->get_iter(rows[r]);          Gtk::TreeModel::iterator it = m_treeStoreMacro->get_iter(rows[r]);
369          if (!it) continue;          if (!it) continue;
# Line 244  void MacroEditor::deleteSelectedRows() { Line 383  void MacroEditor::deleteSelectedRows() {
383      reloadTreeView();      reloadTreeView();
384  }  }
385    
386    static bool _onEachTreeRow(const Gtk::TreeModel::Path& input, std::vector<Gtk::TreeModel::Path>* output) {
387        output->push_back(input);
388        return false; // continue walking the tree
389    }
390    
391  void MacroEditor::inverseDeleteSelectedRows() {  void MacroEditor::inverseDeleteSelectedRows() {
392        // get all rows of tree view
393        std::vector<Gtk::TreeModel::Path> rows;
394        m_treeViewMacro.get_model()->foreach_path(
395            sigc::bind(
396                sigc::ptr_fun(&_onEachTreeRow),
397                &rows
398            )
399        );
400    
401        // erase all entries from "rows" which are currently selected
402        std::vector<Gtk::TreeModel::Path> vSelected = m_treeViewMacro.get_selection()->get_selected_rows();
403        for (int i = rows.size() - 1; i >= 0; --i) {
404            bool bIsSelected = std::find(vSelected.begin(), vSelected.end(),
405                                         rows[i]) != vSelected.end();
406            if (bIsSelected)
407                rows.erase(rows.begin() + i);
408        }
409    
410        // delete those 'inverse' selected rows
411        deleteRows(rows);
412  }  }
413    
414  void MacroEditor::updateStatus() {  void MacroEditor::updateStatus() {
# Line 307  void MacroEditor::onButtonCancel() { Line 471  void MacroEditor::onButtonCancel() {
471  }  }
472    
473  void MacroEditor::onButtonApply() {  void MacroEditor::onButtonApply() {
474      //m_macro.encode();      std::string errorText;
475      *m_macroOriginal = m_macro;      try {
476            // enforce re-encoding the abstract object model and resetting the
477            // 'modified' state
478            m_macro.rawData();
479            // replace actual effective Archive object which is effectively used
480            // for macro apply operations
481            *m_macroOriginal = m_macro;
482        } catch (Serialization::Exception e) {
483            errorText = e.Message;
484        } catch (...) {
485            errorText = _("Unknown exception while applying macro changes");
486        }
487        if (!errorText.empty()) {
488            Glib::ustring txt = _("Couldn't apply macro changes:\n") + errorText;
489            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
490            msg.run();
491        }
492        updateStatus();
493        m_changes_applied.emit();
494  }  }
495    
496  void MacroEditor::onWindowHide() {  void MacroEditor::onWindowHide() {

Legend:
Removed from v.3154  
changed lines
  Added in v.3184

  ViewVC Help
Powered by ViewVC