--- gigedit/trunk/src/gigedit/MacrosSetup.cpp 2017/05/08 21:15:16 3159 +++ gigedit/trunk/src/gigedit/MacrosSetup.cpp 2017/05/08 21:31:45 3160 @@ -9,14 +9,21 @@ #include "global.h" #include #include +#include +#include MacrosSetup::MacrosSetup() : + m_modified(false), + m_clipboardContent(NULL), + m_addFromClipboardButton(" " + Glib::ustring(_("From Clipboard")) + " " + UNICODE_PRIMARY_KEY_SYMBOL + "B"), + m_addFromSelectionButton(" " + Glib::ustring(_("From Selection")) + " " + UNICODE_PRIMARY_KEY_SYMBOL + "S"), m_statusLabel("", Gtk::ALIGN_START), - m_deleteButton(Glib::ustring(_("Delete")) + " " + UNICODE_PRIMARY_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL), - 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), + m_inverseDeleteButton(Glib::ustring(_("Inverse Delete")) + " " + UNICODE_ALT_KEY_SYMBOL + UNICODE_ERASE_KEY_SYMBOL), m_applyButton(_("_Apply"), true), m_cancelButton(_("_Cancel"), true), - m_altKeyDown(false) + m_altKeyDown(false), + m_primaryKeyDown(false) { add(m_vbox); @@ -24,6 +31,18 @@ set_default_size(800, 600); + m_addFromClipboardButton.set_image( + *new Gtk::Image(Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON) + ); + m_addFromSelectionButton.set_image( + *new Gtk::Image(Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON) + ); + m_addFromClipboardButton.set_tooltip_text(_("Create a new macro from the content currently available on the clipboard.")); + m_addFromSelectionButton.set_tooltip_text(_("Create a new macro from the currently selected dimension region's parameters currently shown on the main window.")); + m_addHBox.pack_start(m_addFromClipboardButton); + m_addHBox.pack_start(m_addFromSelectionButton); + m_vbox.pack_start(m_addHBox, Gtk::PACK_SHRINK); + // create Macro list treeview (including its data model) m_treeStoreMacros = MacroListTreeStore::create(m_treeModelMacros); m_treeViewMacros.set_model(m_treeStoreMacros); @@ -63,9 +82,9 @@ m_treeViewMacros.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &MacrosSetup::onTreeViewSelectionChanged) ); - /*m_treeViewMacros.signal_key_release_event().connect_notify( + m_treeViewMacros.signal_key_release_event().connect_notify( sigc::mem_fun(*this, &MacrosSetup::onMacroTreeViewKeyRelease) - );*/ + ); m_treeStoreMacros->signal_row_changed().connect( sigc::mem_fun(*this, &MacrosSetup::onMacroTreeViewRowValueChanged) ); @@ -104,6 +123,14 @@ m_vbox.pack_start(m_footerHBox, Gtk::PACK_SHRINK); + m_addFromClipboardButton.signal_clicked().connect( + sigc::mem_fun(*this, &MacrosSetup::onButtonAddFromClipboard) + ); + + m_addFromSelectionButton.signal_clicked().connect( + sigc::mem_fun(*this, &MacrosSetup::onButtonAddFromSelection) + ); + m_applyButton.signal_clicked().connect( sigc::mem_fun(*this, &MacrosSetup::onButtonApply) ); @@ -143,30 +170,80 @@ printf("MacrosSetup destruct\n"); } -void MacrosSetup::setMacros(const std::vector& macros) { +void MacrosSetup::setMacros(const std::vector& macros, + Serialization::Archive* pClipboardContent, + gig::DimensionRegion* pSelectedDimRgn) +{ // copy for non-destructive editing m_macros = macros; + m_clipboardContent = pClipboardContent; + m_selectedDimRgn = pSelectedDimRgn; + reloadTreeView(); } +void MacrosSetup::onButtonAddFromClipboard() { + printf("+fromClipboard\n"); + if (!m_clipboardContent) return; + if (!m_clipboardContent->rootObject()) return; + m_macros.push_back(*m_clipboardContent); + m_modified = true; + reloadTreeView(); +} + +void MacrosSetup::onButtonAddFromSelection() { + printf("+fromSelection\n"); + if (!m_selectedDimRgn) return; + std::string errorText; + try { + Serialization::Archive archive; + archive.serialize(m_selectedDimRgn); + //archive.setName("Unnamed Macro"); + m_macros.push_back(archive); + m_modified = true; + reloadTreeView(); + } catch (Serialization::Exception e) { + errorText = e.Message; + } catch (...) { + errorText = _("Unknown exception while creating macro"); + } + if (!errorText.empty()) { + Glib::ustring txt = _("Couldn't create macro:\n") + errorText; + Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); + msg.run(); + } +} + static Glib::ustring indexToAccKey(uint index) { if (index >= 12) return ""; return "F" + ToString(index+1); } +static int daysAgo(const tm& t) { + time_t now; + time(&now); + tm* pNow = localtime(&now); + if (!pNow) return 0; + if (pNow->tm_year == t.tm_year && + pNow->tm_mon == t.tm_mon && + pNow->tm_mday == t.tm_mday) return 0; + time_t past = mktime((tm*)&t); + return ceil(difftime(now, past)); +} + static Glib::ustring humanShortStr(const tm& t) { + int iDaysAgo = daysAgo(t); char buf[70]; - int daysAgo; - if (daysAgo = 0) { + if (iDaysAgo == 0) { // C-Time specification for a time somewhere today (see 'man strftime()'). if (strftime(buf, sizeof buf, _("%R"), &t)) return buf; - } else if (daysAgo = 1) { + } else if (iDaysAgo == 1) { // C-Time specification for a time somewhere yesterday (see 'man strftime()'). if (strftime(buf, sizeof buf, _("Yesterday %R"), &t)) return buf; - } else if (daysAgo = 2) { + } else if (iDaysAgo == 2) { // C-Time specification for a time somewhere 2 days ago (see 'man strftime()'). if (strftime(buf, sizeof buf, _("2 days ago %R"), &t)) return buf; @@ -189,8 +266,8 @@ Gtk::TreeModel::iterator iter = m_treeStoreMacros->append(); Gtk::TreeModel::Row row = *iter; row[m_treeModelMacros.m_col_key] = indexToAccKey(iMacro); - row[m_treeModelMacros.m_col_name] = gig_to_utf8(macro.name()); - row[m_treeModelMacros.m_col_comment] = gig_to_utf8(macro.comment()); + row[m_treeModelMacros.m_col_name] = macro.name().empty() ? _("Unnamed Macro") : gig_to_utf8(macro.name()); + row[m_treeModelMacros.m_col_comment] = macro.comment().empty() ? _("No comment assigned yet.") : gig_to_utf8(macro.comment()); row[m_treeModelMacros.m_col_created] = humanShortStr(macro.dateTimeCreated()); row[m_treeModelMacros.m_col_modified] = humanShortStr(macro.dateTimeModified()); row[m_treeModelMacros.m_col_index] = iMacro; @@ -210,10 +287,27 @@ m_inverseDeleteButton.set_sensitive(bValidSelection); } +// Cmd key on Mac, Ctrl key on all other OSs +static const guint primaryKeyL = + #if defined(__APPLE__) + GDK_KEY_Meta_L; + #else + GDK_KEY_Control_L; + #endif + +static const guint primaryKeyR = + #if defined(__APPLE__) + GDK_KEY_Meta_R; + #else + GDK_KEY_Control_R; + #endif + bool MacrosSetup::onKeyPressed(GdkEventKey* key) { //printf("key down 0x%x\n", key->keyval); if (key->keyval == GDK_KEY_Alt_L || key->keyval == GDK_KEY_Alt_R) m_altKeyDown = true; + if (key->keyval == primaryKeyL || key->keyval == primaryKeyR) + m_primaryKeyDown = true; return false; } @@ -221,6 +315,12 @@ //printf("key up 0x%x\n", key->keyval); if (key->keyval == GDK_KEY_Alt_L || key->keyval == GDK_KEY_Alt_R) m_altKeyDown = false; + if (key->keyval == primaryKeyL || key->keyval == primaryKeyR) + m_primaryKeyDown = false; + if (m_primaryKeyDown && key->keyval == GDK_KEY_b) + onButtonAddFromClipboard(); + if (m_primaryKeyDown && key->keyval == GDK_KEY_s) + onButtonAddFromSelection(); return false; } @@ -228,7 +328,7 @@ if (key->keyval == GDK_KEY_BackSpace || key->keyval == GDK_KEY_Delete) { if (m_altKeyDown) inverseDeleteSelectedRows(); - else + else if (m_primaryKeyDown) deleteSelectedRows(); } } @@ -243,6 +343,8 @@ int index = row[m_treeModelMacros.m_col_index]; m_macros[index].setName(name); //reloadTreeView(); + m_modified = true; + updateStatus(); } void MacrosSetup::deleteSelectedRows() { @@ -252,6 +354,7 @@ } void MacrosSetup::deleteRows(const std::vector& rows) { + m_modified = !rows.empty(); std::set macros; for (int r = rows.size() - 1; r >= 0; --r) { Gtk::TreeModel::iterator it = m_treeStoreMacros->get_iter(rows[r]); @@ -298,6 +401,10 @@ } void MacrosSetup::updateStatus() { + m_addFromClipboardButton.set_sensitive( + m_clipboardContent && m_clipboardContent->rootObject() + ); + m_addFromSelectionButton.set_sensitive(m_selectedDimRgn); m_applyButton.set_sensitive(isModified()); updateStatusBar(); } @@ -320,7 +427,7 @@ //gchar* msg = g_strdup_printf(_("Apply changes to macro \"%s\" before closing?"), // m_macroOriginal->Name.c_str()); - gchar* msg = g_strdup_printf(_("Apply changes to macro before closing?")); + gchar* msg = g_strdup_printf(_("Apply changes to macro list before closing?")); Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE); g_free(msg); dialog.set_secondary_text(_("If you close without applying, your changes will be lost.")); @@ -352,6 +459,7 @@ } bool MacrosSetup::isModified() const { + if (m_modified) return true; bool bModified = false; for (int i = 0; i < m_macros.size(); ++i) { if (m_macros[i].isModified()) { @@ -377,6 +485,7 @@ // 'modified' state m_macros[i].rawData(); } + m_modified = false; } catch (Serialization::Exception e) { errorText = e.Message; } catch (...) {