From 71abf47f0483113ff596302fae8678f5cd9db53f Mon Sep 17 00:00:00 2001 From: Nodir Temirkhodjaev Date: Thu, 4 Apr 2024 20:07:27 +0300 Subject: [PATCH] UI: Options: Edit Hot Key Shortcuts --- src/ui/form/opt/pages/optionspage.cpp | 82 +++++++++++++++++++++++++-- src/ui/form/opt/pages/optionspage.h | 12 ++++ src/ui/form/tray/trayicon.cpp | 10 +++- src/ui/rpc/confappmanagerrpc.cpp | 4 +- src/ui/user/iniuser.cpp | 27 ++++++++- src/ui/user/iniuser.h | 12 +++- src/ui/util/variantutil.h | 3 +- 7 files changed, 138 insertions(+), 12 deletions(-) diff --git a/src/ui/form/opt/pages/optionspage.cpp b/src/ui/form/opt/pages/optionspage.cpp index d325429b..017f65af 100644 --- a/src/ui/form/opt/pages/optionspage.cpp +++ b/src/ui/form/opt/pages/optionspage.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,13 @@ void OptionsPage::onResetToDefault() m_cbHotKeysEnabled->setChecked(false); m_cbHotKeysGlobal->setChecked(true); + // Reset Shortcuts + for (int i = 0; i < HotKey::listCount; ++i) { + const auto &key = HotKey::list[i]; + iniUser()->setHotKeyValue(key, HotKey::defaultValue(key)); + } + refreshEditShortcut(); + m_cbHomeAutoShowMenu->setChecked(false); m_cbSplashVisible->setChecked(true); m_cbTrayShowIcon->setChecked(true); @@ -216,6 +224,10 @@ void OptionsPage::onRetranslateUi() m_cbHotKeysEnabled->setText(tr("Enabled")); m_cbHotKeysGlobal->setText(tr("Global")); + m_labelHotKey->setText(tr("Hot Key:")); + m_labelShortcut->setText(tr("Shortcut:")); + retranslateComboHotKey(); + refreshEditShortcut(); m_cbHomeAutoShowMenu->setText(tr("Auto-Show Menu")); m_cbSplashVisible->setText(tr("Show Splash screen on startup")); @@ -293,16 +305,33 @@ void OptionsPage::retranslateEditPassword() settings()->hasPassword() ? tr("Installed") : tr("Not Installed")); } +void OptionsPage::retranslateComboHotKey() +{ + // Sync with TrayIcon::retranslateUi() & HotKey::list[] + QStringList list = { TrayIcon::tr("My Fort"), TrayIcon::tr("Programs"), TrayIcon::tr("Options"), + TrayIcon::tr("Rules"), TrayIcon::tr("Zones"), TrayIcon::tr("Statistics"), + TrayIcon::tr("Traffic Graph"), TrayIcon::tr("Filter Enabled"), + TrayIcon::tr("Block All Traffic"), TrayIcon::tr("Block Internet Traffic") }; + + const auto filterMode = tr("Filter Mode:"); + for (const auto &filterModeName : FirewallConf::filterModeNames()) { + list.append(filterMode + ' ' + filterModeName); + } + + list.append({ TrayIcon::tr("App Group Modifier"), TrayIcon::tr("Quit") }); + + const int currentIndex = qMax(m_comboHotKey->currentIndex(), 0); + + ControlUtil::setComboBoxTexts(m_comboHotKey, list, currentIndex); +} + void OptionsPage::retranslateComboTrayEvent() { // Sync with TrayIcon::ClickType const QStringList list = { tr("Single Click"), tr("Ctrl + Single Click"), tr("Alt + Single Click"), tr("Double Click"), tr("Middle Click"), tr("Right Click") }; - int currentIndex = m_comboTrayEvent->currentIndex(); - if (currentIndex < 0) { - currentIndex = 0; - } + const int currentIndex = qMax(m_comboTrayEvent->currentIndex(), 0); ControlUtil::setComboBoxTexts(m_comboTrayEvent, list, currentIndex); } @@ -707,14 +736,59 @@ void OptionsPage::setupHotKeysBox() ctrl()->setIniUserEdited(true); }); + // Hot Keys Combo & Edit Rows + auto comboLayout = setupComboHotKeyLayout(); + auto editLayout = setupEditShortcutLayout(); + auto layout = new QVBoxLayout(); layout->addWidget(m_cbHotKeysEnabled); layout->addWidget(m_cbHotKeysGlobal); + layout->addWidget(ControlUtil::createSeparator()); + layout->addLayout(comboLayout); + layout->addLayout(editLayout); m_gbHotKeys = new QGroupBox(); m_gbHotKeys->setLayout(layout); } +void OptionsPage::refreshEditShortcut() +{ + const auto &key = HotKey::list[m_comboHotKey->currentIndex()]; + const auto &defaultValue = HotKey::defaultValue(key); + + m_editShortcut->setKeySequence(iniUser()->hotKeyValue(key, defaultValue)); +} + +QLayout *OptionsPage::setupComboHotKeyLayout() +{ + m_labelHotKey = ControlUtil::createLabel(); + + m_comboHotKey = ControlUtil::createComboBox( + QStringList(), [&](int /*index*/) { refreshEditShortcut(); }); + m_comboHotKey->setFixedWidth(200); + + return ControlUtil::createRowLayout(m_labelHotKey, m_comboHotKey); +} + +QLayout *OptionsPage::setupEditShortcutLayout() +{ + m_labelShortcut = ControlUtil::createLabel(); + + m_editShortcut = new QKeySequenceEdit(); + m_editShortcut->setClearButtonEnabled(true); + m_editShortcut->setFixedWidth(200); + + connect(m_editShortcut, &QKeySequenceEdit::editingFinished, [&] { + const auto &key = HotKey::list[m_comboHotKey->currentIndex()]; + const auto value = m_editShortcut->keySequence().toString(); + + iniUser()->setHotKeyValue(key, value); + ctrl()->setIniUserEdited(); + }); + + return ControlUtil::createRowLayout(m_labelShortcut, m_editShortcut); +} + void OptionsPage::setupHomeBox() { m_cbHomeAutoShowMenu = diff --git a/src/ui/form/opt/pages/optionspage.h b/src/ui/form/opt/pages/optionspage.h index 86cd1af8..a79f50d3 100644 --- a/src/ui/form/opt/pages/optionspage.h +++ b/src/ui/form/opt/pages/optionspage.h @@ -3,6 +3,8 @@ #include "optbasepage.h" +QT_FORWARD_DECLARE_CLASS(QKeySequenceEdit) + class OptionsPage : public OptBasePage { Q_OBJECT @@ -35,6 +37,7 @@ private: void retranslateComboStartMode(); void retranslateComboFilterMode(); void retranslateEditPassword(); + void retranslateComboHotKey(); void retranslateComboTrayEvent(); void retranslateComboTrayAction(); @@ -58,6 +61,9 @@ private: QLayout *setupLangLayout(); void setupComboLanguage(); void setupHotKeysBox(); + void refreshEditShortcut(); + QLayout *setupComboHotKeyLayout(); + QLayout *setupEditShortcutLayout(); void setupHomeBox(); void setupTrayBox(); QLayout *setupTrayMaxGroupsLayout(); @@ -112,12 +118,18 @@ private: QComboBox *m_comboLanguage = nullptr; QCheckBox *m_cbHotKeysEnabled = nullptr; QCheckBox *m_cbHotKeysGlobal = nullptr; + QLabel *m_labelHotKey = nullptr; + QComboBox *m_comboHotKey = nullptr; + QLabel *m_labelShortcut = nullptr; + QKeySequenceEdit *m_editShortcut = nullptr; + QCheckBox *m_cbHomeAutoShowMenu = nullptr; QCheckBox *m_cbSplashVisible = nullptr; QCheckBox *m_cbTrayShowIcon = nullptr; QCheckBox *m_cbTrayAnimateAlert = nullptr; QLabel *m_labelTrayMaxGroups = nullptr; QSpinBox *m_spinTrayMaxGroups = nullptr; + QLabel *m_labelTrayEvent = nullptr; QComboBox *m_comboTrayEvent = nullptr; QLabel *m_labelTrayAction = nullptr; diff --git a/src/ui/form/tray/trayicon.cpp b/src/ui/form/tray/trayicon.cpp index 42cb849a..2535745c 100644 --- a/src/ui/form/tray/trayicon.cpp +++ b/src/ui/form/tray/trayicon.cpp @@ -471,6 +471,14 @@ void TrayIcon::setupTrayMenuOptions() void TrayIcon::setupTrayMenuFilterMode() { + static const char *const filterModeHotKeys[] = { + HotKey::filterModeAutoLearn, + HotKey::filterModeAskToConnect, + HotKey::filterModeBlock, + HotKey::filterModeAllow, + HotKey::filterModeIgnore, + }; + m_filterModeMenu = ControlUtil::createMenu(m_menu); m_filterModeActions = new QActionGroup(m_filterModeMenu); @@ -479,7 +487,7 @@ void TrayIcon::setupTrayMenuFilterMode() const QStringList iconPaths = FirewallConf::filterModeIconPaths(); for (const QString &name : FirewallConf::filterModeNames()) { const QString iconPath = iconPaths.at(index); - const QString hotKey = HotKey::filterModes[index]; + const QString hotKey = filterModeHotKeys[index]; QAction *a = addAction(m_filterModeMenu, iconPath, /*receiver=*/nullptr, /*member=*/nullptr, ActionNone, /*checkable=*/true); diff --git a/src/ui/rpc/confappmanagerrpc.cpp b/src/ui/rpc/confappmanagerrpc.cpp index 3d125356..d4a5fb2e 100644 --- a/src/ui/rpc/confappmanagerrpc.cpp +++ b/src/ui/rpc/confappmanagerrpc.cpp @@ -108,7 +108,7 @@ bool ConfAppManagerRpc::deleteApps(const QVector &appIdList) VariantUtil::vectorToList(appIdList, appIdVarList); QVariantList args; - VariantUtil::addToList(args, appIdVarList); + VariantUtil::addToList(args, QVariant(appIdVarList)); return IoC()->doOnServer(Control::Rpc_ConfAppManager_deleteApps, args); } @@ -125,7 +125,7 @@ bool ConfAppManagerRpc::updateAppsBlocked( VariantUtil::vectorToList(appIdList, appIdVarList); QVariantList args; - VariantUtil::addToList(args, appIdVarList); + VariantUtil::addToList(args, QVariant(appIdVarList)); args << blocked << killProcess; return IoC()->doOnServer(Control::Rpc_ConfAppManager_updateAppsBlocked, args); diff --git a/src/ui/user/iniuser.cpp b/src/ui/user/iniuser.cpp index 721cc535..6fbaf642 100644 --- a/src/ui/user/iniuser.cpp +++ b/src/ui/user/iniuser.cpp @@ -1,14 +1,39 @@ #include "iniuser.h" +#include + namespace HotKey { -const char *const filterModes[] = { +const char *const list[] = { + home, + programs, + options, + rules, + zones, + statistics, + graph, + filter, + blockTraffic, + blockInetTraffic, filterModeAutoLearn, filterModeAskToConnect, filterModeBlock, filterModeAllow, filterModeIgnore, + appGroupModifier, + quit, }; +const int listCount = sizeof(list) / sizeof(list[0]); + +const char *const defaultValue(const char *key) +{ + static QHash g_defaultValuesMap = { + { filter, Default::filter }, + { appGroupModifier, Default::appGroupModifier }, + }; + + return g_defaultValuesMap.value(key, nullptr); +} } diff --git a/src/ui/user/iniuser.h b/src/ui/user/iniuser.h index 53a294ad..9fb7911b 100644 --- a/src/ui/user/iniuser.h +++ b/src/ui/user/iniuser.h @@ -12,11 +12,10 @@ const char *const rules = "rules"; const char *const zones = "zones"; const char *const statistics = "statistics"; const char *const graph = "graph"; + const char *const filter = "filter"; const char *const blockTraffic = "blockTraffic"; const char *const blockInetTraffic = "blockInetTraffic"; -const char *const appGroupModifier = "appGroupModifier"; -const char *const quit = "quit"; const char *const filterModeAutoLearn = "filterModeAutoLearn"; const char *const filterModeAskToConnect = "filterModeAskToConnect"; @@ -24,7 +23,13 @@ const char *const filterModeBlock = "filterModeBlock"; const char *const filterModeAllow = "filterModeAllow"; const char *const filterModeIgnore = "filterModeIgnore"; -extern const char *const filterModes[]; +const char *const appGroupModifier = "appGroupModifier"; +const char *const quit = "quit"; + +extern const char *const list[]; +extern const int listCount; + +const char *const defaultValue(const char *key); namespace Default { const char *const filter = "Ctrl+Alt+Shift+F"; @@ -57,6 +62,7 @@ public: { return valueText("hotKey/" + key, defaultValue); } + void setHotKeyValue(const QString &key, const QString &v) { setValue("hotKey/" + key, v); } bool splashWindowVisible() const { return valueBool("splashWindow/visible", true); } void setSplashWindowVisible(bool on) { setValue("splashWindow/visible", on, true); } diff --git a/src/ui/util/variantutil.h b/src/ui/util/variantutil.h index f33ff625..485c6ce2 100644 --- a/src/ui/util/variantutil.h +++ b/src/ui/util/variantutil.h @@ -14,7 +14,8 @@ public: template static void listToVector(const QVariantList &list, QVector &array); - inline static void addToList(QVariantList &list, const QVariant &v) + template + inline static void addToList(QList &list, const T &v) { list.push_back(v); // append() merges the list, does not insert }