/[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 3157 by schoenebeck, Mon May 8 17:30:10 2017 UTC revision 3160 by schoenebeck, Mon May 8 21:31:45 2017 UTC
# Line 9  Line 9 
9  #include "global.h"  #include "global.h"
10  #include <assert.h>  #include <assert.h>
11  #include <set>  #include <set>
12    #include <math.h>
13    #include <gtkmm/stock.h>
14    
15  MacrosSetup::MacrosSetup() :  MacrosSetup::MacrosSetup() :
16        m_modified(false),
17        m_clipboardContent(NULL),
18        m_addFromClipboardButton("  " + Glib::ustring(_("From Clipboard")) + "  " + UNICODE_PRIMARY_KEY_SYMBOL + "B"),
19        m_addFromSelectionButton("  " + Glib::ustring(_("From Selection")) + "  " + UNICODE_PRIMARY_KEY_SYMBOL + "S"),
20      m_statusLabel("",  Gtk::ALIGN_START),      m_statusLabel("",  Gtk::ALIGN_START),
21      m_deleteButton(Glib::ustring(_("Delete")) + " " + UNICODE_PRIMARY_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL),      m_deleteButton(Glib::ustring(_("Delete")) + "  " + UNICODE_PRIMARY_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL),
22      m_inverseDeleteButton(Glib::ustring(_("Inverse Delete")) + " " + UNICODE_ALT_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL),      m_inverseDeleteButton(Glib::ustring(_("Inverse Delete")) + "  " + UNICODE_ALT_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL),
23      m_applyButton(_("_Apply"), true),      m_applyButton(_("_Apply"), true),
24      m_cancelButton(_("_Cancel"), true),      m_cancelButton(_("_Cancel"), true),
25      m_altKeyDown(false)      m_altKeyDown(false),
26        m_primaryKeyDown(false)
27  {  {
28      add(m_vbox);      add(m_vbox);
29    
# Line 24  MacrosSetup::MacrosSetup() : Line 31  MacrosSetup::MacrosSetup() :
31    
32      set_default_size(800, 600);      set_default_size(800, 600);
33    
34        m_addFromClipboardButton.set_image(
35            *new Gtk::Image(Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)
36        );
37        m_addFromSelectionButton.set_image(
38            *new Gtk::Image(Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)
39        );
40        m_addFromClipboardButton.set_tooltip_text(_("Create a new macro from the content currently available on the clipboard."));
41        m_addFromSelectionButton.set_tooltip_text(_("Create a new macro from the currently selected dimension region's parameters currently shown on the main window."));
42        m_addHBox.pack_start(m_addFromClipboardButton);
43        m_addHBox.pack_start(m_addFromSelectionButton);
44        m_vbox.pack_start(m_addHBox, Gtk::PACK_SHRINK);
45    
46      // create Macro list treeview (including its data model)      // create Macro list treeview (including its data model)
47      m_treeStoreMacros = MacroListTreeStore::create(m_treeModelMacros);      m_treeStoreMacros = MacroListTreeStore::create(m_treeModelMacros);
48      m_treeViewMacros.set_model(m_treeStoreMacros);      m_treeViewMacros.set_model(m_treeStoreMacros);
# Line 63  MacrosSetup::MacrosSetup() : Line 82  MacrosSetup::MacrosSetup() :
82      m_treeViewMacros.get_selection()->signal_changed().connect(      m_treeViewMacros.get_selection()->signal_changed().connect(
83          sigc::mem_fun(*this, &MacrosSetup::onTreeViewSelectionChanged)          sigc::mem_fun(*this, &MacrosSetup::onTreeViewSelectionChanged)
84      );      );
85      /*m_treeViewMacros.signal_key_release_event().connect_notify(      m_treeViewMacros.signal_key_release_event().connect_notify(
86          sigc::mem_fun(*this, &MacrosSetup::onMacroTreeViewKeyRelease)          sigc::mem_fun(*this, &MacrosSetup::onMacroTreeViewKeyRelease)
87      );*/      );
88      m_treeStoreMacros->signal_row_changed().connect(      m_treeStoreMacros->signal_row_changed().connect(
89          sigc::mem_fun(*this, &MacrosSetup::onMacroTreeViewRowValueChanged)          sigc::mem_fun(*this, &MacrosSetup::onMacroTreeViewRowValueChanged)
90      );      );
# Line 104  MacrosSetup::MacrosSetup() : Line 123  MacrosSetup::MacrosSetup() :
123    
124      m_vbox.pack_start(m_footerHBox, Gtk::PACK_SHRINK);      m_vbox.pack_start(m_footerHBox, Gtk::PACK_SHRINK);
125    
126        m_addFromClipboardButton.signal_clicked().connect(
127            sigc::mem_fun(*this, &MacrosSetup::onButtonAddFromClipboard)
128        );
129    
130        m_addFromSelectionButton.signal_clicked().connect(
131            sigc::mem_fun(*this, &MacrosSetup::onButtonAddFromSelection)
132        );
133    
134      m_applyButton.signal_clicked().connect(      m_applyButton.signal_clicked().connect(
135          sigc::mem_fun(*this, &MacrosSetup::onButtonApply)          sigc::mem_fun(*this, &MacrosSetup::onButtonApply)
136      );      );
# Line 143  MacrosSetup::~MacrosSetup() { Line 170  MacrosSetup::~MacrosSetup() {
170      printf("MacrosSetup destruct\n");      printf("MacrosSetup destruct\n");
171  }  }
172    
173  void MacrosSetup::setMacros(const std::vector<Serialization::Archive>& macros) {  void MacrosSetup::setMacros(const std::vector<Serialization::Archive>& macros,
174                                Serialization::Archive* pClipboardContent,
175                                gig::DimensionRegion* pSelectedDimRgn)
176    {
177      // copy for non-destructive editing      // copy for non-destructive editing
178      m_macros = macros;      m_macros = macros;
179    
180        m_clipboardContent = pClipboardContent;
181        m_selectedDimRgn = pSelectedDimRgn;
182    
183      reloadTreeView();      reloadTreeView();
184  }  }
185    
186    void MacrosSetup::onButtonAddFromClipboard() {
187        printf("+fromClipboard\n");
188        if (!m_clipboardContent) return;
189        if (!m_clipboardContent->rootObject()) return;
190        m_macros.push_back(*m_clipboardContent);
191        m_modified = true;
192        reloadTreeView();
193    }
194    
195    void MacrosSetup::onButtonAddFromSelection() {
196        printf("+fromSelection\n");
197        if (!m_selectedDimRgn) return;
198        std::string errorText;
199        try {
200            Serialization::Archive archive;
201            archive.serialize(m_selectedDimRgn);
202            //archive.setName("Unnamed Macro");
203            m_macros.push_back(archive);
204            m_modified = true;
205            reloadTreeView();
206        } catch (Serialization::Exception e) {
207            errorText = e.Message;
208        } catch (...) {
209            errorText = _("Unknown exception while creating macro");
210        }
211        if (!errorText.empty()) {
212            Glib::ustring txt = _("Couldn't create macro:\n") + errorText;
213            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
214            msg.run();
215        }
216    }
217    
218  static Glib::ustring indexToAccKey(uint index) {  static Glib::ustring indexToAccKey(uint index) {
219      if (index >= 12) return "";      if (index >= 12) return "";
220      return "F" + ToString(index+1);      return "F" + ToString(index+1);
221  }  }
222    
223    static int daysAgo(const tm& t) {
224        time_t now;
225        time(&now);
226        tm* pNow = localtime(&now);
227        if (!pNow) return 0;
228        if (pNow->tm_year == t.tm_year &&
229            pNow->tm_mon  == t.tm_mon &&
230            pNow->tm_mday == t.tm_mday) return 0;
231        time_t past = mktime((tm*)&t);
232        return ceil(difftime(now, past));
233    }
234    
235  static Glib::ustring humanShortStr(const tm& t) {  static Glib::ustring humanShortStr(const tm& t) {
236        int iDaysAgo = daysAgo(t);
237      char buf[70];      char buf[70];
238      int daysAgo;      if (iDaysAgo == 0) {
     if (daysAgo = 0) {  
239          // C-Time specification for a time somewhere today (see 'man strftime()').          // C-Time specification for a time somewhere today (see 'man strftime()').
240          if (strftime(buf, sizeof buf, _("%R"), &t))          if (strftime(buf, sizeof buf, _("%R"), &t))
241              return buf;              return buf;
242      } else if (daysAgo = 1) {      } else if (iDaysAgo == 1) {
243          // C-Time specification for a time somewhere yesterday (see 'man strftime()').          // C-Time specification for a time somewhere yesterday (see 'man strftime()').
244          if (strftime(buf, sizeof buf, _("Yesterday %R"), &t))          if (strftime(buf, sizeof buf, _("Yesterday %R"), &t))
245              return buf;              return buf;
246      } else if (daysAgo = 2) {      } else if (iDaysAgo == 2) {
247          // C-Time specification for a time somewhere 2 days ago (see 'man strftime()').          // C-Time specification for a time somewhere 2 days ago (see 'man strftime()').
248          if (strftime(buf, sizeof buf, _("2 days ago %R"), &t))          if (strftime(buf, sizeof buf, _("2 days ago %R"), &t))
249              return buf;              return buf;
# Line 189  void MacrosSetup::reloadTreeView() { Line 266  void MacrosSetup::reloadTreeView() {
266          Gtk::TreeModel::iterator iter = m_treeStoreMacros->append();          Gtk::TreeModel::iterator iter = m_treeStoreMacros->append();
267          Gtk::TreeModel::Row row = *iter;          Gtk::TreeModel::Row row = *iter;
268          row[m_treeModelMacros.m_col_key] = indexToAccKey(iMacro);          row[m_treeModelMacros.m_col_key] = indexToAccKey(iMacro);
269          row[m_treeModelMacros.m_col_name] = gig_to_utf8(macro.name());          row[m_treeModelMacros.m_col_name] = macro.name().empty() ? _("Unnamed Macro") : gig_to_utf8(macro.name());
270          row[m_treeModelMacros.m_col_comment] = gig_to_utf8(macro.comment());          row[m_treeModelMacros.m_col_comment] = macro.comment().empty() ? _("No comment assigned yet.") : gig_to_utf8(macro.comment());
271          row[m_treeModelMacros.m_col_created] = humanShortStr(macro.dateTimeCreated());          row[m_treeModelMacros.m_col_created] = humanShortStr(macro.dateTimeCreated());
272          row[m_treeModelMacros.m_col_modified] = humanShortStr(macro.dateTimeModified());          row[m_treeModelMacros.m_col_modified] = humanShortStr(macro.dateTimeModified());
273          row[m_treeModelMacros.m_col_index] = iMacro;          row[m_treeModelMacros.m_col_index] = iMacro;
# Line 210  void MacrosSetup::onTreeViewSelectionCha Line 287  void MacrosSetup::onTreeViewSelectionCha
287      m_inverseDeleteButton.set_sensitive(bValidSelection);      m_inverseDeleteButton.set_sensitive(bValidSelection);
288  }  }
289    
290    // Cmd key on Mac, Ctrl key on all other OSs
291    static const guint primaryKeyL =
292        #if defined(__APPLE__)
293        GDK_KEY_Meta_L;
294        #else
295        GDK_KEY_Control_L;
296        #endif
297    
298    static const guint primaryKeyR =
299        #if defined(__APPLE__)
300        GDK_KEY_Meta_R;
301        #else
302        GDK_KEY_Control_R;
303        #endif
304    
305  bool MacrosSetup::onKeyPressed(GdkEventKey* key) {  bool MacrosSetup::onKeyPressed(GdkEventKey* key) {
306      //printf("key down 0x%x\n", key->keyval);      //printf("key down 0x%x\n", key->keyval);
307      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)
308          m_altKeyDown = true;          m_altKeyDown = true;
309        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
310            m_primaryKeyDown = true;
311      return false;      return false;
312  }  }
313    
# Line 221  bool MacrosSetup::onKeyReleased(GdkEvent Line 315  bool MacrosSetup::onKeyReleased(GdkEvent
315      //printf("key up 0x%x\n", key->keyval);      //printf("key up 0x%x\n", key->keyval);
316      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)
317          m_altKeyDown = false;          m_altKeyDown = false;
318        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
319            m_primaryKeyDown = false;
320        if (m_primaryKeyDown && key->keyval == GDK_KEY_b)
321            onButtonAddFromClipboard();
322        if (m_primaryKeyDown && key->keyval == GDK_KEY_s)
323            onButtonAddFromSelection();
324      return false;      return false;
325  }  }
326    
# Line 228  void MacrosSetup::onMacroTreeViewKeyRele Line 328  void MacrosSetup::onMacroTreeViewKeyRele
328      if (key->keyval == GDK_KEY_BackSpace || key->keyval == GDK_KEY_Delete) {      if (key->keyval == GDK_KEY_BackSpace || key->keyval == GDK_KEY_Delete) {
329          if (m_altKeyDown)          if (m_altKeyDown)
330              inverseDeleteSelectedRows();              inverseDeleteSelectedRows();
331          else          else if (m_primaryKeyDown)
332              deleteSelectedRows();              deleteSelectedRows();
333      }      }
334  }  }
# Line 243  void MacrosSetup::onMacroTreeViewRowValu Line 343  void MacrosSetup::onMacroTreeViewRowValu
343      int index = row[m_treeModelMacros.m_col_index];      int index = row[m_treeModelMacros.m_col_index];
344      m_macros[index].setName(name);      m_macros[index].setName(name);
345      //reloadTreeView();      //reloadTreeView();
346        m_modified = true;
347        updateStatus();
348  }  }
349    
350  void MacrosSetup::deleteSelectedRows() {  void MacrosSetup::deleteSelectedRows() {
# Line 252  void MacrosSetup::deleteSelectedRows() { Line 354  void MacrosSetup::deleteSelectedRows() {
354  }  }
355    
356  void MacrosSetup::deleteRows(const std::vector<Gtk::TreeModel::Path>& rows) {  void MacrosSetup::deleteRows(const std::vector<Gtk::TreeModel::Path>& rows) {
357        m_modified = !rows.empty();
358      std::set<int> macros;      std::set<int> macros;
359      for (int r = rows.size() - 1; r >= 0; --r) {      for (int r = rows.size() - 1; r >= 0; --r) {
360          Gtk::TreeModel::iterator it = m_treeStoreMacros->get_iter(rows[r]);          Gtk::TreeModel::iterator it = m_treeStoreMacros->get_iter(rows[r]);
# Line 298  void MacrosSetup::inverseDeleteSelectedR Line 401  void MacrosSetup::inverseDeleteSelectedR
401  }  }
402    
403  void MacrosSetup::updateStatus() {  void MacrosSetup::updateStatus() {
404        m_addFromClipboardButton.set_sensitive(
405            m_clipboardContent && m_clipboardContent->rootObject()
406        );
407        m_addFromSelectionButton.set_sensitive(m_selectedDimRgn);
408      m_applyButton.set_sensitive(isModified());      m_applyButton.set_sensitive(isModified());
409      updateStatusBar();      updateStatusBar();
410  }  }
# Line 320  bool MacrosSetup::onWindowDelete(GdkEven Line 427  bool MacrosSetup::onWindowDelete(GdkEven
427    
428      //gchar* msg = g_strdup_printf(_("Apply changes to macro \"%s\" before closing?"),      //gchar* msg = g_strdup_printf(_("Apply changes to macro \"%s\" before closing?"),
429      //                             m_macroOriginal->Name.c_str());      //                             m_macroOriginal->Name.c_str());
430      gchar* msg = g_strdup_printf(_("Apply changes to macro before closing?"));      gchar* msg = g_strdup_printf(_("Apply changes to macro list before closing?"));
431      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
432      g_free(msg);      g_free(msg);
433      dialog.set_secondary_text(_("If you close without applying, your changes will be lost."));      dialog.set_secondary_text(_("If you close without applying, your changes will be lost."));
# Line 352  bool MacrosSetup::onWindowDelete(GdkEven Line 459  bool MacrosSetup::onWindowDelete(GdkEven
459  }  }
460    
461  bool MacrosSetup::isModified() const {  bool MacrosSetup::isModified() const {
462        if (m_modified) return true;
463      bool bModified = false;      bool bModified = false;
464      for (int i = 0; i < m_macros.size(); ++i) {      for (int i = 0; i < m_macros.size(); ++i) {
465          if (m_macros[i].isModified()) {          if (m_macros[i].isModified()) {
# Line 377  void MacrosSetup::onButtonApply() { Line 485  void MacrosSetup::onButtonApply() {
485              // 'modified' state              // 'modified' state
486              m_macros[i].rawData();              m_macros[i].rawData();
487          }          }
488            m_modified = false;
489      } catch (Serialization::Exception e) {      } catch (Serialization::Exception e) {
490          errorText = e.Message;          errorText = e.Message;
491      } catch (...) {      } catch (...) {

Legend:
Removed from v.3157  
changed lines
  Added in v.3160

  ViewVC Help
Powered by ViewVC