From 518342b919a4568728e47a98404295564d5069b1 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Fri, 4 Jul 2014 20:16:24 -0700 Subject: [PATCH] Make the hotkey code a bit less bloated --- libaegisub/common/hotkey.cpp | 155 +++++++-------- libaegisub/include/libaegisub/hotkey.h | 38 ++-- src/hotkey.cpp | 256 +++++++++++-------------- src/hotkey_data_view_model.cpp | 11 +- tests/tests/hotkey.cpp | 35 ++-- 5 files changed, 225 insertions(+), 270 deletions(-) diff --git a/libaegisub/common/hotkey.cpp b/libaegisub/common/hotkey.cpp index f420f5d7a..6f33034ab 100644 --- a/libaegisub/common/hotkey.cpp +++ b/libaegisub/common/hotkey.cpp @@ -12,36 +12,33 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -/// @file hotkey.cpp -/// @brief Hotkey handler -/// @ingroup hotkey menu event window - #include "libaegisub/hotkey.h" #include "libaegisub/cajun/writer.h" #include "libaegisub/io.h" #include "libaegisub/json.h" #include "libaegisub/log.h" +#include "libaegisub/split.h" #include -#include -#include +#include #include -namespace agi { - namespace hotkey { +namespace agi { namespace hotkey { +namespace { +struct combo_cmp { + bool operator()(const Combo *a, const Combo *b) { + return a->Str() < b->Str(); + } -std::string Combo::Str() const { - return boost::algorithm::join(key_map, "-"); -} + bool operator()(const Combo *a, std::string const& b) { + return a->Str() < b; + } -std::string Combo::StrMenu() const { - return Str(); -} - -void Hotkey::ComboInsert(Combo const& combo) { - str_map.insert(make_pair(combo.Str(), combo)); - cmd_map.insert(make_pair(combo.CmdName(), combo)); + bool operator()(std::string const& a, const Combo *b) { + return a < b->Str(); + } +}; } Hotkey::Hotkey(fs::path const& file, std::pair default_config) @@ -52,85 +49,84 @@ Hotkey::Hotkey(fs::path const& file, std::pair default_con auto root = json_util::file(config_file, default_config); for (auto const& hotkey_context : static_cast(root)) BuildHotkey(hotkey_context.first, hotkey_context.second); + UpdateStrMap(); } void Hotkey::BuildHotkey(std::string const& context, json::Object const& hotkeys) { for (auto const& command : hotkeys) { - const json::Array& command_hotkeys = command.second; + json::Array const& command_hotkeys = command.second; for (json::Object const& hotkey : command_hotkeys) { - std::vector keys; - - auto it = hotkey.find("modifiers"); - if (it == end(hotkey)) { + auto mod_it = hotkey.find("modifiers"); + if (mod_it == end(hotkey)) { LOG_E("agi/hotkey/load") << "Hotkey for command '" << command.first << "' is missing modifiers"; continue; } - - json::Array const& arr_mod = it->second; - keys.reserve(arr_mod.size() + 1); - copy(arr_mod.begin(), arr_mod.end(), back_inserter(keys)); - - it = hotkey.find("key"); - if (it == end(hotkey)) { + auto key_it = hotkey.find("key"); + if (key_it == end(hotkey)) { LOG_E("agi/hotkey/load") << "Hotkey for command '" << command.first << "' is missing the key"; continue; } - keys.push_back(it->second); - ComboInsert(Combo(context, command.first, keys)); + std::string key_str; + json::Array const& arr_mod = mod_it->second; + for (std::string const& mod : arr_mod) { + key_str += mod; + key_str += '-'; + } + key_str += static_cast(key_it->second); + + cmd_map.insert(make_pair(command.first, Combo(context, command.first, std::move(key_str)))); } } } -std::string Hotkey::Scan(const std::string &context, const std::string &str, bool always) const { - std::string local, dfault; +std::string Hotkey::Scan(std::string const& context, std::string const& str, bool always) const { + const std::string *local = nullptr, *dfault = nullptr; - HotkeyMap::const_iterator index, end; - for (std::tie(index, end) = str_map.equal_range(str); index != end; ++index) { - std::string const& ctext = index->second.Context(); + std::vector::const_iterator index, end; + for (std::tie(index, end) = boost::equal_range(str_map, str, combo_cmp()); index != end; ++index) { + std::string const& ctext = (*index)->Context(); if (always && ctext == "Always") { - LOG_D("agi/hotkey/found") << "Found: " << str << " Context (req/found): " << context << "/Always Command: " << index->second.CmdName(); - return index->second.CmdName(); + LOG_D("agi/hotkey/found") << "Found: " << str << " Context (req/found): " << context << "/Always Command: " << (*index)->CmdName(); + return (*index)->CmdName(); } if (ctext == "Default") - dfault = index->second.CmdName(); + dfault = &(*index)->CmdName(); else if (ctext == context) - local = index->second.CmdName(); + local = &(*index)->CmdName(); } - if (!local.empty()) { - LOG_D("agi/hotkey/found") << "Found: " << str << " Context: " << context << " Command: " << local; - return local; + if (local) { + LOG_D("agi/hotkey/found") << "Found: " << str << " Context: " << context << " Command: " << *local; + return *local; } - if (!dfault.empty()) { - LOG_D("agi/hotkey/found") << "Found: " << str << " Context (req/found): " << context << "/Default Command: " << dfault; - return dfault; + if (dfault) { + LOG_D("agi/hotkey/found") << "Found: " << str << " Context (req/found): " << context << "/Default Command: " << *dfault; + return *dfault; } return ""; } -bool Hotkey::HasHotkey(const std::string &context, const std::string &str) const { - HotkeyMap::const_iterator index, end; - for (std::tie(index, end) = str_map.equal_range(str); index != end; ++index) { - std::string const& ctext = index->second.Context(); - - if (ctext == context) +bool Hotkey::HasHotkey(std::string const& context, std::string const& str) const { + std::vector::const_iterator index, end; + for (std::tie(index, end) = boost::equal_range(str_map, str, combo_cmp()); index != end; ++index) { + if (context == (*index)->Context()) return true; } return false; } -std::vector Hotkey::GetHotkeys(const std::string &context, const std::string &command) const { +std::vector Hotkey::GetHotkeys(std::string const& context, std::string const& command) const { std::vector ret; HotkeyMap::const_iterator it, end; for (std::tie(it, end) = cmd_map.equal_range(command); it != end; ++it) { - std::string ctext = it->second.Context(); + std::string const& ctext = it->second.Context(); if (ctext == "Always" || ctext == "Default" || ctext == context) - ret.emplace_back(it->second.StrMenu()); + ret.emplace_back(it->second.Str()); } sort(ret.begin(), ret.end()); @@ -139,16 +135,16 @@ std::vector Hotkey::GetHotkeys(const std::string &context, const st return ret; } -std::string Hotkey::GetHotkey(const std::string &context, const std::string &command) const { +std::string Hotkey::GetHotkey(std::string const& context, std::string const& command) const { std::string ret; HotkeyMap::const_iterator it, end; for (std::tie(it, end) = cmd_map.equal_range(command); it != end; ++it) { - std::string ctext = it->second.Context(); - if (ctext == context) return it->second.StrMenu(); + std::string const& ctext = it->second.Context(); + if (ctext == context) return it->second.Str(); if (ctext == "Default") - ret = it->second.StrMenu(); + ret = it->second.Str(); else if (ret.empty() && ctext == "Always") - ret = it->second.StrMenu(); + ret = it->second.Str(); } return ret; } @@ -156,16 +152,21 @@ std::string Hotkey::GetHotkey(const std::string &context, const std::string &com void Hotkey::Flush() { json::Object root; - for (auto const& combo : str_map | boost::adaptors::map_values) { + for (auto const& combo : str_map) { + auto keys = combo->Str(); + if (keys.empty()) continue; + json::Object hotkey; - if (combo.Get().size()) { - hotkey["key"] = combo.Get().back(); - json::Array& modifiers = hotkey["modifiers"]; - modifiers.insert(modifiers.end(), combo.Get().begin(), combo.Get().end() - 1); + json::Array& modifiers = hotkey["modifiers"]; + for (auto tok : agi::Split(keys, '-')) { + if (end(tok) == end(keys)) + hotkey.insert(make_pair("key", agi::str(tok))); + else + modifiers.push_back(agi::str(tok)); } - json::Object& context = root[combo.Context()]; - json::Array& combo_array = context[combo.CmdName()]; + json::Object& context = root[combo->Context()]; + json::Array& combo_array = context[combo->CmdName()]; combo_array.push_back(std::move(hotkey)); } @@ -173,16 +174,20 @@ void Hotkey::Flush() { JsonWriter::Write(root, file.Get()); } -void Hotkey::SetHotkeyMap(HotkeyMap const& new_map) { - cmd_map = new_map; - +void Hotkey::UpdateStrMap() { str_map.clear(); - for (auto const& combo : cmd_map | boost::adaptors::map_values) - str_map.insert(make_pair(combo.Str(), combo)); + str_map.reserve(cmd_map.size()); + for (auto const& combo : cmd_map) + str_map.push_back(&combo.second); + sort(begin(str_map), end(str_map), combo_cmp()); +} + +void Hotkey::SetHotkeyMap(HotkeyMap new_map) { + cmd_map = std::move(new_map); + UpdateStrMap(); Flush(); HotkeysChanged(); } - } // namespace toolbar -} // namespace agi +} } diff --git a/libaegisub/include/libaegisub/hotkey.h b/libaegisub/include/libaegisub/hotkey.h index 8b2b3fc26..017578739 100644 --- a/libaegisub/include/libaegisub/hotkey.h +++ b/libaegisub/include/libaegisub/hotkey.h @@ -12,10 +12,6 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -/// @file hotkey.h -/// @brief Hotkey handler -/// @ingroup hotkey menu event window - #include #include #include @@ -36,39 +32,31 @@ namespace agi { /// A Combo represents a linear sequence of characters set in an std::vector. /// This makes up a single combination, or "Hotkey". class Combo { - std::vector key_map; + std::string keys; std::string cmd_name; std::string context; public: /// Constructor /// @param ctx Context /// @param cmd Command name - Combo(std::string ctx, std::string cmd, std::vector keys) - : key_map(std::move(keys)) + Combo(std::string ctx, std::string cmd, std::string keys) + : keys(std::move(keys)) , cmd_name(std::move(cmd)) , context(std::move(ctx)) { } /// String representation of the Combo - std::string Str() const; - - /// String suitable for usage in a menu. - std::string StrMenu() const; - - /// Get the literal combo map. - /// @return ComboMap (std::vector) of linear key sequence. - const std::vector& Get() const { return key_map; } + std::string Str() const { return keys; } /// Command name triggered by the combination. /// @return Command name - const std::string& CmdName() const { return cmd_name; } + std::string const& CmdName() const { return cmd_name; } /// Context this Combo is triggered in. - const std::string& Context() const { return context; } + std::string const& Context() const { return context; } }; - /// @class Hotkey /// Holds the map of Combo instances and handles searching for matching key sequences. class Hotkey { @@ -76,22 +64,20 @@ public: /// Map to hold Combo instances typedef std::multimap HotkeyMap; private: - HotkeyMap str_map; ///< String representation -> Combo - HotkeyMap cmd_map; ///< Command name -> Combo - const agi::fs::path config_file; ///< Default user config location. + HotkeyMap cmd_map; ///< Command name -> Combo + std::vector str_map; ///< Sorted by string representation + const agi::fs::path config_file; ///< Default user config location. /// Build hotkey map. /// @param context Context being parsed. /// @param object json::Object holding items for context being parsed. void BuildHotkey(std::string const& context, const json::Object& object); - /// Insert Combo into HotkeyMap instance. - /// @param combo Combo to insert. - void ComboInsert(Combo const& combo); - /// Write active Hotkey configuration to disk. void Flush(); + void UpdateStrMap(); + /// Announce that the loaded hotkeys have been changed agi::signal::Signal<> HotkeysChanged; public: @@ -129,7 +115,7 @@ public: HotkeyMap const& GetHotkeyMap() const { return cmd_map; } /// Replace the loaded hotkeys with a new set - void SetHotkeyMap(HotkeyMap const& new_map); + void SetHotkeyMap(HotkeyMap new_map); DEFINE_SIGNAL_ADDERS(HotkeysChanged, AddHotkeyChangeListener) }; diff --git a/src/hotkey.cpp b/src/hotkey.cpp index aa333739f..c5e788ae8 100644 --- a/src/hotkey.cpp +++ b/src/hotkey.cpp @@ -12,10 +12,6 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -/// @file hotkey.cpp -/// @brief Hotkey handler -/// @ingroup hotkey menu event window - #include #include "include/aegisub/hotkey.h" @@ -33,42 +29,40 @@ #include namespace { - const char *added_hotkeys_7035[][5] = { - { "audio/play/line", "Audio", "R", nullptr, nullptr }, - { nullptr } + const char *added_hotkeys_7035[][3] = { + {"audio/play/line", "Audio", "R"}, + {nullptr} }; - const char *added_hotkeys_7070[][5] = { - { "edit/color/primary", "Subtitle Edit Box", "Alt", "1", nullptr }, - { "edit/color/secondary", "Subtitle Edit Box", "Alt", "2", nullptr }, - { "edit/color/outline", "Subtitle Edit Box", "Alt", "3", nullptr }, - { "edit/color/shadow", "Subtitle Edit Box", "Alt", "4", nullptr }, - { nullptr } + const char *added_hotkeys_7070[][3] = { + {"edit/color/primary", "Subtitle Edit Box", "Alt-1"}, + {"edit/color/secondary", "Subtitle Edit Box", "Alt-2"}, + {"edit/color/outline", "Subtitle Edit Box", "Alt-3"}, + {"edit/color/shadow", "Subtitle Edit Box", "Alt-4"}, + {nullptr} }; - const char *added_hotkeys_shift_back[][5] = { - { "edit/line/duplicate/shift_back", "Default", "Ctrl", "Shift", "D" }, - { nullptr } + const char *added_hotkeys_shift_back[][3] = { + {"edit/line/duplicate/shift_back", "Default", "Ctrl-Shift-D"}, + {nullptr} }; - void migrate_hotkeys(const char *added[][5]) { - agi::hotkey::Hotkey::HotkeyMap hk_map = hotkey::inst->GetHotkeyMap(); + void migrate_hotkeys(const char *added[][3]) { + auto hk_map = hotkey::inst->GetHotkeyMap(); + bool changed = false; for (size_t i = 0; added[i] && added[i][0]; ++i) { - std::vector keys; - for (size_t j = 2; j < 5; ++j) { - if (added[i][j]) - keys.emplace_back(added[i][j]); - } - agi::hotkey::Combo combo(added[i][1], added[i][0], keys); + agi::hotkey::Combo combo(added[i][1], added[i][0], added[i][2]); if (hotkey::inst->HasHotkey(combo.Context(), combo.Str())) continue; - hk_map.insert(make_pair(std::string(added[i][0]), combo)); + hk_map.insert(make_pair(std::string(added[i][0]), std::move(combo))); + changed = true; } - hotkey::inst->SetHotkeyMap(hk_map); + if (changed) + hotkey::inst->SetHotkeyMap(std::move(hk_map)); } } @@ -100,18 +94,18 @@ void init() { if (boost::find(migrations, "duplicate -> split") == end(migrations)) { auto hk_map = hotkey::inst->GetHotkeyMap(); for (auto const& hotkey : boost::make_iterator_range(hk_map.equal_range("edit/line/duplicate/shift"))) { - auto combo = agi::hotkey::Combo(hotkey.second.Context(), "edit/line/split/before", hotkey.second.Get()); + auto combo = agi::hotkey::Combo(hotkey.second.Context(), "edit/line/split/before", hotkey.second.Str()); hk_map.insert({combo.CmdName(), combo}); } for (auto const& hotkey : boost::make_iterator_range(hk_map.equal_range("edit/line/duplicate/shift_back"))) { - auto combo = agi::hotkey::Combo(hotkey.second.Context(), "edit/line/split/after", hotkey.second.Get()); + auto combo = agi::hotkey::Combo(hotkey.second.Context(), "edit/line/split/after", hotkey.second.Str()); hk_map.insert({combo.CmdName(), combo}); } hk_map.erase("edit/line/duplicate/shift"); hk_map.erase("edit/line/duplicate/shift_back"); - hotkey::inst->SetHotkeyMap(hk_map); + hotkey::inst->SetHotkeyMap(std::move(hk_map)); migrations.emplace_back("duplicate -> split"); } @@ -122,20 +116,95 @@ void clear() { delete inst; } -static std::vector keycode_names; - -static void init_keycode_names(); - -static std::string const& keycode_name(int code) { - if (keycode_names.empty()) - init_keycode_names(); - - if (static_cast(code) > keycode_names.size()) { - static std::string str; - return str; +static const char *keycode_name(int code) { + switch (code) { + case WXK_BACK: return "Backspace"; + case WXK_TAB: return "Tab"; + case WXK_RETURN: return "Enter"; + case WXK_ESCAPE: return "Escape"; + case WXK_SPACE: return "Space"; + case WXK_DELETE: return "Delete"; + case WXK_SHIFT: return "Shift"; + case WXK_ALT: return "Alt"; + case WXK_CONTROL: return "Control"; + case WXK_PAUSE: return "Pause"; + case WXK_END: return "End"; + case WXK_HOME: return "Home"; + case WXK_LEFT: return "Left"; + case WXK_UP: return "Up"; + case WXK_RIGHT: return "Right"; + case WXK_DOWN: return "Down"; + case WXK_PRINT: return "Print"; + case WXK_INSERT: return "Insert"; + case WXK_NUMPAD0: return "KP_0"; + case WXK_NUMPAD1: return "KP_1"; + case WXK_NUMPAD2: return "KP_2"; + case WXK_NUMPAD3: return "KP_3"; + case WXK_NUMPAD4: return "KP_4"; + case WXK_NUMPAD5: return "KP_5"; + case WXK_NUMPAD6: return "KP_6"; + case WXK_NUMPAD7: return "KP_7"; + case WXK_NUMPAD8: return "KP_8"; + case WXK_NUMPAD9: return "KP_9"; + case WXK_MULTIPLY: return "Asterisk"; + case WXK_ADD: return "Plus"; + case WXK_SUBTRACT: return "Hyphen"; + case WXK_DECIMAL: return "Period"; + case WXK_DIVIDE: return "Slash"; + case WXK_F1: return "F1"; + case WXK_F2: return "F2"; + case WXK_F3: return "F3"; + case WXK_F4: return "F4"; + case WXK_F5: return "F5"; + case WXK_F6: return "F6"; + case WXK_F7: return "F7"; + case WXK_F8: return "F8"; + case WXK_F9: return "F9"; + case WXK_F10: return "F10"; + case WXK_F11: return "F11"; + case WXK_F12: return "F12"; + case WXK_F13: return "F13"; + case WXK_F14: return "F14"; + case WXK_F15: return "F15"; + case WXK_F16: return "F16"; + case WXK_F17: return "F17"; + case WXK_F18: return "F18"; + case WXK_F19: return "F19"; + case WXK_F20: return "F20"; + case WXK_F21: return "F21"; + case WXK_F22: return "F22"; + case WXK_F23: return "F23"; + case WXK_F24: return "F24"; + case WXK_NUMLOCK: return "Num_Lock"; + case WXK_SCROLL: return "Scroll_Lock"; + case WXK_PAGEUP: return "PageUp"; + case WXK_PAGEDOWN: return "PageDown"; + case WXK_NUMPAD_SPACE: return "KP_Space"; + case WXK_NUMPAD_TAB: return "KP_Tab"; + case WXK_NUMPAD_ENTER: return "KP_Enter"; + case WXK_NUMPAD_F1: return "KP_F1"; + case WXK_NUMPAD_F2: return "KP_F2"; + case WXK_NUMPAD_F3: return "KP_F3"; + case WXK_NUMPAD_F4: return "KP_F4"; + case WXK_NUMPAD_HOME: return "KP_Home"; + case WXK_NUMPAD_LEFT: return "KP_Left"; + case WXK_NUMPAD_UP: return "KP_Up"; + case WXK_NUMPAD_RIGHT: return "KP_Right"; + case WXK_NUMPAD_DOWN: return "KP_Down"; + case WXK_NUMPAD_PAGEUP: return "KP_PageUp"; + case WXK_NUMPAD_PAGEDOWN: return "KP_PageDown"; + case WXK_NUMPAD_END: return "KP_End"; + case WXK_NUMPAD_BEGIN: return "KP_Begin"; + case WXK_NUMPAD_INSERT: return "KP_insert"; + case WXK_NUMPAD_DELETE: return "KP_Delete"; + case WXK_NUMPAD_EQUAL: return "KP_Equal"; + case WXK_NUMPAD_MULTIPLY: return "KP_Multiply"; + case WXK_NUMPAD_ADD: return "KP_Add"; + case WXK_NUMPAD_SUBTRACT: return "KP_Subtract"; + case WXK_NUMPAD_DECIMAL: return "KP_Decimal"; + case WXK_NUMPAD_DIVIDE: return "KP_Divide"; + default: return ""; } - - return keycode_names[code]; } std::string keypress_to_str(int key_code, int modifier) { @@ -146,7 +215,10 @@ std::string keypress_to_str(int key_code, int modifier) { if ((modifier & wxMOD_SHIFT) != 0) combo.append("Shift-"); } - combo += keycode_name(key_code); + if (key_code < 127) + combo += (char)key_code; + else + combo += keycode_name(key_code); return combo; } @@ -186,102 +258,4 @@ std::string get_hotkey_str_first(std::string const& context, std::string const& return inst->GetHotkey(context, command); } -static inline void set_kc(std::vector &vec, int code, std::string const& str) { - if (static_cast(code) >= vec.size()) vec.resize(code * 2, ""); - vec[code] = str; -} - -static void init_keycode_names() { - char str[] = { 0, 0 }; - for (char i = 33; i < 127; ++i) { - str[0] = i; - set_kc(keycode_names, i, str); - } - set_kc(keycode_names, WXK_BACK, "Backspace"); - set_kc(keycode_names, WXK_TAB, "Tab"); - set_kc(keycode_names, WXK_RETURN, "Enter"); - set_kc(keycode_names, WXK_ESCAPE, "Escape"); - set_kc(keycode_names, WXK_SPACE, "Space"); - set_kc(keycode_names, WXK_DELETE, "Delete"); - set_kc(keycode_names, WXK_SHIFT, "Shift"); - set_kc(keycode_names, WXK_ALT, "Alt"); - set_kc(keycode_names, WXK_CONTROL, "Control"); - set_kc(keycode_names, WXK_PAUSE, "Pause"); - set_kc(keycode_names, WXK_END, "End"); - set_kc(keycode_names, WXK_HOME, "Home"); - set_kc(keycode_names, WXK_LEFT, "Left"); - set_kc(keycode_names, WXK_UP, "Up"); - set_kc(keycode_names, WXK_RIGHT, "Right"); - set_kc(keycode_names, WXK_DOWN, "Down"); - set_kc(keycode_names, WXK_PRINT, "Print"); - set_kc(keycode_names, WXK_INSERT, "Insert"); - set_kc(keycode_names, WXK_NUMPAD0, "KP_0"); - set_kc(keycode_names, WXK_NUMPAD1, "KP_1"); - set_kc(keycode_names, WXK_NUMPAD2, "KP_2"); - set_kc(keycode_names, WXK_NUMPAD3, "KP_3"); - set_kc(keycode_names, WXK_NUMPAD4, "KP_4"); - set_kc(keycode_names, WXK_NUMPAD5, "KP_5"); - set_kc(keycode_names, WXK_NUMPAD6, "KP_6"); - set_kc(keycode_names, WXK_NUMPAD7, "KP_7"); - set_kc(keycode_names, WXK_NUMPAD8, "KP_8"); - set_kc(keycode_names, WXK_NUMPAD9, "KP_9"); - set_kc(keycode_names, WXK_MULTIPLY, "Asterisk"); - set_kc(keycode_names, WXK_ADD, "Plus"); - set_kc(keycode_names, WXK_SUBTRACT, "Hyphen"); - set_kc(keycode_names, WXK_DECIMAL, "Period"); - set_kc(keycode_names, WXK_DIVIDE, "Slash"); - set_kc(keycode_names, WXK_F1, "F1"); - set_kc(keycode_names, WXK_F2, "F2"); - set_kc(keycode_names, WXK_F3, "F3"); - set_kc(keycode_names, WXK_F4, "F4"); - set_kc(keycode_names, WXK_F5, "F5"); - set_kc(keycode_names, WXK_F6, "F6"); - set_kc(keycode_names, WXK_F7, "F7"); - set_kc(keycode_names, WXK_F8, "F8"); - set_kc(keycode_names, WXK_F9, "F9"); - set_kc(keycode_names, WXK_F10, "F10"); - set_kc(keycode_names, WXK_F11, "F11"); - set_kc(keycode_names, WXK_F12, "F12"); - set_kc(keycode_names, WXK_F13, "F13"); - set_kc(keycode_names, WXK_F14, "F14"); - set_kc(keycode_names, WXK_F15, "F15"); - set_kc(keycode_names, WXK_F16, "F16"); - set_kc(keycode_names, WXK_F17, "F17"); - set_kc(keycode_names, WXK_F18, "F18"); - set_kc(keycode_names, WXK_F19, "F19"); - set_kc(keycode_names, WXK_F20, "F20"); - set_kc(keycode_names, WXK_F21, "F21"); - set_kc(keycode_names, WXK_F22, "F22"); - set_kc(keycode_names, WXK_F23, "F23"); - set_kc(keycode_names, WXK_F24, "F24"); - set_kc(keycode_names, WXK_NUMLOCK, "Num_Lock"); - set_kc(keycode_names, WXK_SCROLL, "Scroll_Lock"); - set_kc(keycode_names, WXK_PAGEUP, "PageUp"); - set_kc(keycode_names, WXK_PAGEDOWN, "PageDown"); - set_kc(keycode_names, WXK_NUMPAD_SPACE, "KP_Space"); - set_kc(keycode_names, WXK_NUMPAD_TAB, "KP_Tab"); - set_kc(keycode_names, WXK_NUMPAD_ENTER, "KP_Enter"); - set_kc(keycode_names, WXK_NUMPAD_F1, "KP_F1"); - set_kc(keycode_names, WXK_NUMPAD_F2, "KP_F2"); - set_kc(keycode_names, WXK_NUMPAD_F3, "KP_F3"); - set_kc(keycode_names, WXK_NUMPAD_F4, "KP_F4"); - set_kc(keycode_names, WXK_NUMPAD_HOME, "KP_Home"); - set_kc(keycode_names, WXK_NUMPAD_LEFT, "KP_Left"); - set_kc(keycode_names, WXK_NUMPAD_UP, "KP_Up"); - set_kc(keycode_names, WXK_NUMPAD_RIGHT, "KP_Right"); - set_kc(keycode_names, WXK_NUMPAD_DOWN, "KP_Down"); - set_kc(keycode_names, WXK_NUMPAD_PAGEUP, "KP_PageUp"); - set_kc(keycode_names, WXK_NUMPAD_PAGEDOWN, "KP_PageDown"); - set_kc(keycode_names, WXK_NUMPAD_END, "KP_End"); - set_kc(keycode_names, WXK_NUMPAD_BEGIN, "KP_Begin"); - set_kc(keycode_names, WXK_NUMPAD_INSERT, "KP_insert"); - set_kc(keycode_names, WXK_NUMPAD_DELETE, "KP_Delete"); - set_kc(keycode_names, WXK_NUMPAD_EQUAL, "KP_Equal"); - set_kc(keycode_names, WXK_NUMPAD_MULTIPLY, "KP_Multiply"); - set_kc(keycode_names, WXK_NUMPAD_ADD, "KP_Add"); - set_kc(keycode_names, WXK_NUMPAD_SUBTRACT, "KP_Subtract"); - set_kc(keycode_names, WXK_NUMPAD_DECIMAL, "KP_Decimal"); - set_kc(keycode_names, WXK_NUMPAD_DIVIDE, "KP_Divide"); -} - } // namespace hotkey diff --git a/src/hotkey_data_view_model.cpp b/src/hotkey_data_view_model.cpp index 5d913fca5..968ab3742 100644 --- a/src/hotkey_data_view_model.cpp +++ b/src/hotkey_data_view_model.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -111,11 +110,7 @@ public: bool SetValue(wxVariant const& variant, unsigned int col) override { if (col == 0) { - std::vector keys; - auto str = from_wx(variant.GetString()); - for (auto tok : agi::Split(str, '-')) - keys.emplace_back(begin(tok), end(tok)); - combo = Combo(combo.Context(), combo.CmdName(), keys); + combo = Combo(combo.Context(), combo.CmdName(), from_wx(variant.GetString())); cmd_str = combo.Str(); return true; } @@ -123,7 +118,7 @@ public: wxDataViewIconText text; text << variant; cmd_name = from_wx(text.GetText()); - combo = Combo(combo.Context(), cmd_name, combo.Get()); + combo = Combo(combo.Context(), cmd_name, combo.Str()); return true; } return false; @@ -307,7 +302,7 @@ wxDataViewItem HotkeyDataViewModel::New(wxDataViewItem item) { HotkeyModelCategory *ctx = static_cast(item.GetID()); wxVariant name; ctx->GetValue(name, 0); - return ctx->AddChild(Combo(from_wx(name.GetString()), "", std::vector())); + return ctx->AddChild(Combo(from_wx(name.GetString()), "", "")); } void HotkeyDataViewModel::Delete(wxDataViewItem const& item) { diff --git a/tests/tests/hotkey.cpp b/tests/tests/hotkey.cpp index 48e3cd6be..0645c79cf 100644 --- a/tests/tests/hotkey.cpp +++ b/tests/tests/hotkey.cpp @@ -17,15 +17,13 @@ #include #include -#include - using namespace agi::hotkey; -static const char simple_valid[] = "{" - "\"Always\":{\"cmd1\":[{\"modifiers\":[\"Ctrl\"], \"key\":\"C\"}]}," - "\"Default\":{\"cmd1\":[{\"modifiers\":[\"Alt\"], \"key\":\"C\"}], \"cmd2\":[{\"modifiers\":[\"Ctrl\"], \"key\":\"C\"}]}," - "\"Other\":{\"cmd1\":[{\"modifiers\":[\"Shift\"], \"key\":\"C\"}], \"cmd3\":[{\"modifiers\":[], \"key\":\"Q\"}]}" -"}"; +static const char simple_valid[] = R"raw({ + "Always":{"cmd1":[{"modifiers":["Ctrl"], "key":"C"}]}, + "Default":{"cmd1":[{"modifiers":["Alt"], "key":"C"}], "cmd2":[{"modifiers":["Ctrl"], "key":"C"}]}, + "Other":{"cmd1":[{"modifiers":["Shift"], "key":"C"}], "cmd3":[{"modifiers":[], "key":"Q"}]} +})raw"; TEST(lagi_hotkey, simple_valid_default) { EXPECT_NO_THROW(Hotkey("", simple_valid)); @@ -137,20 +135,18 @@ TEST(lagi_hotkey, get_hotkeys) { EXPECT_EQ(0, h.GetHotkeys("Nonexistent", "cmd4").size()); } +TEST(lagi_hotkey, has_hotkey) { + Hotkey h("", simple_valid); + EXPECT_TRUE(h.HasHotkey("Always", "Ctrl-C")); + EXPECT_FALSE(h.HasHotkey("Always", "Alt-C")); +} + TEST(lagi_hotkey, get_hotkeys_dedups) { Hotkey h("", "{\"Always\":{\"cmd1\":[{\"modifiers\":[\"Ctrl\"], \"key\":\"C\"}]},\"Default\":{\"cmd1\":[{\"modifiers\":[\"Ctrl\"], \"key\":\"C\"}]}}"); EXPECT_EQ(1, h.GetHotkeys("Always", "cmd1").size()); } -static void insert_combo(Hotkey::HotkeyMap &hm, const char *ctx, const char *cmd, int N, ...) { - std::vector keys(N); - - va_list argp; - va_start(argp, N); - for (int i = 0; i < N; ++i) - keys[i] = va_arg(argp, const char *); - va_end(argp); - +static void insert_combo(Hotkey::HotkeyMap &hm, const char *ctx, const char *cmd, const char *keys) { hm.insert(make_pair(std::string(cmd), Combo(ctx, cmd, keys))); } @@ -162,8 +158,8 @@ TEST(lagi_hotkey, set_hotkey_map) { Hotkey::HotkeyMap hm = h.GetHotkeyMap(); EXPECT_EQ(0, hm.size()); - insert_combo(hm, "Always", "cmd1", 1, "C"); - insert_combo(hm, "Default", "cmd2", 2, "Shift", "C"); + insert_combo(hm, "Always", "cmd1", "C"); + insert_combo(hm, "Default", "cmd2", "Shift-C"); bool listener_called = false; h.AddHotkeyChangeListener([&] { listener_called = true; }); @@ -189,8 +185,7 @@ TEST(lagi_hotkey, combo_stuff) { ASSERT_EQ(1, std::distance(it, end)); Combo c = it->second; - EXPECT_STREQ("Ctrl-C", c.StrMenu().c_str()); + EXPECT_STREQ("Ctrl-C", c.Str().c_str()); EXPECT_STREQ("cmd2", c.CmdName().c_str()); EXPECT_STREQ("Default", c.Context().c_str()); - EXPECT_EQ(2, c.Get().size()); }