UI: Tray: Refresh edited menu hot keys

This commit is contained in:
Nodir Temirkhodjaev 2024-04-05 12:28:06 +03:00
parent 71abf47f04
commit 10ee20bf37
9 changed files with 113 additions and 74 deletions

View File

@ -754,9 +754,8 @@ void OptionsPage::setupHotKeysBox()
void OptionsPage::refreshEditShortcut()
{
const auto &key = HotKey::list[m_comboHotKey->currentIndex()];
const auto &defaultValue = HotKey::defaultValue(key);
m_editShortcut->setKeySequence(iniUser()->hotKeyValue(key, defaultValue));
m_editShortcut->setKeySequence(iniUser()->hotKeyValue(key));
}
QLayout *OptionsPage::setupComboHotKeyLayout()

View File

@ -27,6 +27,8 @@
namespace {
constexpr int MaxFKeyCount = 12;
const QString eventSingleClick = QStringLiteral("singleClick");
const QString eventCtrlSingleClick = QStringLiteral("ctrlSingleClick");
const QString eventAltSingleClick = QStringLiteral("altSingleClick");
@ -279,8 +281,9 @@ void TrayIcon::updateTrayMenu(bool onlyFlags)
updateTrayMenuFlags();
updateTrayIconShape();
updateHotKeys();
updateClickActions();
updateActionHotKeys();
updateHotKeys();
}
void TrayIcon::quitProgram()
@ -372,11 +375,11 @@ void TrayIcon::setupTrayMenu()
m_homeAction = addAction(
m_menu, ":/icons/fort.png", windowManager(), SLOT(showHomeWindow()), ActionShowHome);
addHotKey(m_homeAction, iniUser()->hotKeyValue(HotKey::home));
addHotKey(m_homeAction, HotKey::home);
m_programsAction = addAction(m_menu, ":/icons/application.png", windowManager(),
SLOT(showProgramsWindow()), ActionShowPrograms);
addHotKey(m_programsAction, iniUser()->hotKeyValue(HotKey::programs));
addHotKey(m_programsAction, HotKey::programs);
m_programsOrAlertAction = addAction(
m_menu, QString(), this, SLOT(showProgramsOrAlertWindow()), ActionShowProgramsOrAlert);
@ -387,27 +390,26 @@ void TrayIcon::setupTrayMenu()
m_statisticsAction = addAction(m_menu, ":/icons/chart_bar.png", windowManager(),
SLOT(showStatisticsWindow()), ActionShowStatistics);
addHotKey(m_statisticsAction, iniUser()->hotKeyValue(HotKey::statistics));
addHotKey(m_statisticsAction, HotKey::statistics);
m_graphAction = addAction(m_menu, ":/icons/action_log.png", windowManager(),
SLOT(switchGraphWindow()), ActionShowTrafficGraph, /*checkable=*/true,
windowManager()->isWindowOpen(WindowGraph));
addHotKey(m_graphAction, iniUser()->hotKeyValue(HotKey::graph));
addHotKey(m_graphAction, HotKey::graph);
m_menu->addSeparator();
m_filterEnabledAction = addAction(m_menu, QString(), this, SLOT(switchTrayFlag(bool)),
ActionSwitchFilterEnabled, /*checkable=*/true);
addHotKey(
m_filterEnabledAction, iniUser()->hotKeyValue(HotKey::filter, HotKey::Default::filter));
addHotKey(m_filterEnabledAction, HotKey::filter);
m_blockTrafficAction = addAction(m_menu, QString(), this, SLOT(switchTrayFlag(bool)),
ActionSwitchBlockTraffic, /*checkable=*/true);
addHotKey(m_blockTrafficAction, iniUser()->hotKeyValue(HotKey::blockTraffic));
addHotKey(m_blockTrafficAction, HotKey::blockTraffic);
m_blockInetTrafficAction = addAction(m_menu, QString(), this, SLOT(switchTrayFlag(bool)),
ActionSwitchBlockInetTraffic, /*checkable=*/true);
addHotKey(m_blockInetTrafficAction, iniUser()->hotKeyValue(HotKey::blockInetTraffic));
addHotKey(m_blockInetTrafficAction, HotKey::blockInetTraffic);
m_filterModeMenuAction = addAction(
m_menu, QString(), this, SLOT(switchFilterModeMenu(bool)), ActionShowFilterModeMenu);
@ -418,19 +420,12 @@ void TrayIcon::setupTrayMenu()
m_menu->addSeparator();
const QString hotKeyAppGroupModifier =
iniUser()->hotKeyValue(HotKey::appGroupModifier, HotKey::Default::appGroupModifier)
+ "+F";
for (int i = 0; i < MAX_APP_GROUP_COUNT; ++i) {
QAction *a = addAction(m_menu, QString(), this, SLOT(switchTrayFlag(bool)), ActionNone,
/*checkable=*/true);
constexpr int maxFKeyCount = 12;
if (i < maxFKeyCount) {
const QString shortcutText = hotKeyAppGroupModifier + QString::number(i + 1);
addHotKey(a, shortcutText);
if (i < MaxFKeyCount) {
addHotKey(a, HotKey::appGroupModifier);
}
m_appGroupActions.append(a);
@ -439,7 +434,7 @@ void TrayIcon::setupTrayMenu()
m_menu->addSeparator();
m_quitAction = addAction(m_menu, ":/icons/standby.png", this, SLOT(quitProgram()));
addHotKey(m_quitAction, iniUser()->hotKeyValue(HotKey::quit));
addHotKey(m_quitAction, HotKey::quit);
m_trayMenuAction =
addAction(m_menu, QString(), this, SLOT(switchTrayMenu(bool)), ActionShowTrayMenu);
@ -453,25 +448,25 @@ void TrayIcon::setupTrayMenuOptions()
m_optionsAction =
addAction(m_optionsMenu, ":/icons/cog.png", windowManager(), SLOT(showOptionsWindow()));
addHotKey(m_optionsAction, iniUser()->hotKeyValue(HotKey::options));
addHotKey(m_optionsAction, HotKey::options);
connect(m_optionsMenu, &ClickableMenu::clicked, m_optionsAction, &QAction::trigger);
m_rulesAction = addAction(
m_optionsMenu, ":/icons/script.png", windowManager(), SLOT(showRulesWindow()));
addHotKey(m_rulesAction, iniUser()->hotKeyValue(HotKey::rules));
addHotKey(m_rulesAction, HotKey::rules);
// TODO: Implement Rules
m_rulesAction->setEnabled(false);
m_zonesAction = addAction(
m_optionsMenu, ":/icons/ip_class.png", windowManager(), SLOT(showZonesWindow()));
addHotKey(m_zonesAction, iniUser()->hotKeyValue(HotKey::zones));
addHotKey(m_zonesAction, HotKey::zones);
}
void TrayIcon::setupTrayMenuFilterMode()
{
static const char *const filterModeHotKeys[] = {
static const char *const filterModeIniKeys[] = {
HotKey::filterModeAutoLearn,
HotKey::filterModeAskToConnect,
HotKey::filterModeBlock,
@ -487,13 +482,13 @@ void TrayIcon::setupTrayMenuFilterMode()
const QStringList iconPaths = FirewallConf::filterModeIconPaths();
for (const QString &name : FirewallConf::filterModeNames()) {
const QString iconPath = iconPaths.at(index);
const QString hotKey = filterModeHotKeys[index];
const auto &iniKey = filterModeIniKeys[index];
QAction *a = addAction(m_filterModeMenu, iconPath, /*receiver=*/nullptr, /*member=*/nullptr,
ActionNone, /*checkable=*/true);
a->setText(name);
addHotKey(a, iniUser()->hotKeyValue(hotKey));
addHotKey(a, iniKey);
// TODO: Implement Ask to Connect
a->setEnabled(index != 1);
@ -706,13 +701,31 @@ void TrayIcon::switchFilterMode(QAction *action)
}
}
void TrayIcon::addHotKey(QAction *action, const QString &shortcutText)
void TrayIcon::updateActionHotKeys()
{
if (shortcutText.isEmpty())
return;
int groupIndex = 0;
int index = 0;
for (auto action : hotKeyManager()->actions()) {
const auto &iniKey = m_actionIniKeys[index];
const QKeySequence shortcut = QKeySequence::fromString(shortcutText);
hotKeyManager()->addAction(action, shortcut);
QString shortcutText = iniUser()->hotKeyValue(iniKey);
if (iniKey == HotKey::appGroupModifier) {
shortcutText += "+F" + QString::number(++groupIndex);
}
const QKeySequence shortcut = QKeySequence::fromString(shortcutText);
action->setShortcut(shortcut);
++index;
}
}
void TrayIcon::addHotKey(QAction *action, const char *iniKey)
{
hotKeyManager()->addAction(action);
m_actionIniKeys.append(iniKey);
}
void TrayIcon::updateHotKeys()
@ -720,11 +733,6 @@ void TrayIcon::updateHotKeys()
hotKeyManager()->initialize(iniUser()->hotKeyEnabled(), iniUser()->hotKeyGlobal());
}
void TrayIcon::removeHotKeys()
{
hotKeyManager()->removeActions();
}
TrayIcon::ActionType TrayIcon::clickEventActionType(IniUser *iniUser, ClickType clickType)
{
const QString eventName = clickNameByType(clickType);

View File

@ -115,9 +115,10 @@ private:
void updateTrayIconShape();
void addHotKey(QAction *action, const QString &shortcutText);
void updateActionHotKeys();
void addHotKey(QAction *action, const char *iniKey);
void updateHotKeys();
void removeHotKeys();
void updateClickActions();
@ -145,9 +146,9 @@ private:
ClickableMenu *m_optionsMenu = nullptr;
QAction *m_optionsAction = nullptr;
QAction *m_rulesAction = nullptr;
QAction *m_zonesAction = nullptr;
QAction *m_statisticsAction = nullptr;
QAction *m_graphAction = nullptr;
QAction *m_zonesAction = nullptr;
QAction *m_filterEnabledAction = nullptr;
QAction *m_blockTrafficAction = nullptr;
QAction *m_blockInetTrafficAction = nullptr;
@ -157,6 +158,7 @@ private:
QAction *m_quitAction = nullptr;
QAction *m_trayMenuAction = nullptr;
QList<QAction *> m_appGroupActions;
QVector<const char *> m_actionIniKeys;
QAction *m_clickActions[ClickTypeCount] = { nullptr };

View File

@ -9,11 +9,22 @@
#include "nativeeventfilter.h"
namespace {
QKeyCombination getActionKey(QAction *action)
{
const QKeySequence keySequence = action->shortcut();
return keySequence.isEmpty() ? QKeyCombination() : keySequence[0];
}
}
HotKeyManager::HotKeyManager(QObject *parent) : QObject(parent) { }
void HotKeyManager::initialize(bool enabled, bool global)
{
if (m_enabled == enabled && m_global == global)
if (m_enabled == enabled && m_global == global && !checkShortcutsChanged())
return;
m_enabled = enabled;
@ -33,19 +44,16 @@ void HotKeyManager::setUp()
void HotKeyManager::tearDown()
{
disconnect(IoC<NativeEventFilter>());
removeActions();
}
bool HotKeyManager::addAction(QAction *action, const QKeySequence &shortcut)
bool HotKeyManager::addAction(QAction *action)
{
action->setText(action->text());
action->setShortcut(shortcut);
action->setShortcutVisibleInContextMenu(false);
const int hotKeyId = m_actions.size();
action->setData(hotKeyId);
m_actions.append(action);
m_keys.append(getActionKey(action));
return true;
}
@ -55,6 +63,7 @@ void HotKeyManager::removeActions()
IoC<NativeEventFilter>()->unregisterHotKeys();
m_actions.clear();
m_keys.clear();
}
void HotKeyManager::updateActions()
@ -63,36 +72,45 @@ void HotKeyManager::updateActions()
eventFilter->unregisterHotKeys();
int hotKeyId = 0;
for (QAction *action : std::as_const(m_actions)) {
action->setShortcutVisibleInContextMenu(enabled());
const auto key = getActionKey(action);
m_keys[hotKeyId] = key;
if (enabled() && global()) {
registerHotKey(eventFilter, action);
eventFilter->registerHotKey(hotKeyId, key);
}
++hotKeyId;
}
}
bool HotKeyManager::checkShortcutsChanged() const
{
int hotKeyId = 0;
for (QAction *action : std::as_const(m_actions)) {
const auto oldKey = getActionKey(action);
const auto key = m_keys[hotKeyId];
if (key != oldKey)
return true;
++hotKeyId;
}
return false;
}
void HotKeyManager::onHotKeyPressed(int hotKeyId)
{
if (WindowManager::activateModalWidget())
return;
if (hotKeyId >= m_actions.size())
return;
QAction *action = m_actions.at(hotKeyId);
if (action->isEnabled()) {
QAction *action = m_actions.value(hotKeyId);
if (action && action->isEnabled()) {
action->trigger();
OsUtil::beep();
}
}
void HotKeyManager::registerHotKey(NativeEventFilter *eventFilter, QAction *action) const
{
const QKeySequence shortcut = action->shortcut();
const int hotKeyId = action->data().toInt();
const auto keyCombination = shortcut[0];
const int key = keyCombination.toCombined();
eventFilter->registerHotKey(hotKeyId, key);
}

View File

@ -18,12 +18,14 @@ public:
bool enabled() const { return m_enabled; }
bool global() const { return m_global; }
const QList<QAction *> &actions() const { return m_actions; }
void initialize(bool enabled, bool global);
void setUp() override;
void tearDown() override;
bool addAction(QAction *action, const QKeySequence &shortcut);
bool addAction(QAction *action);
void removeActions();
@ -33,13 +35,14 @@ private slots:
private:
void updateActions();
void registerHotKey(NativeEventFilter *eventFilter, QAction *action) const;
bool checkShortcutsChanged() const;
private:
bool m_enabled = false;
bool m_global = false;
QList<QAction *> m_actions;
QVector<QKeyCombination> m_keys;
};
#endif // HOTKEYMANAGER_H

View File

@ -126,7 +126,7 @@ bool NativeEventFilter::registerHotKey(
return true;
}
bool NativeEventFilter::registerHotKey(int hotKeyId, int key)
bool NativeEventFilter::registerHotKey(int hotKeyId, QKeyCombination key)
{
return registerHotKey(hotKeyId, Qt::Key(key & ~Qt::KeyboardModifierMask),
Qt::KeyboardModifiers(key & Qt::KeyboardModifierMask));

View File

@ -20,7 +20,7 @@ public:
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
bool registerHotKey(int hotKeyId, Qt::Key keyCode, Qt::KeyboardModifiers modifiers);
bool registerHotKey(int hotKeyId, int key);
bool registerHotKey(int hotKeyId, QKeyCombination key);
void unregisterHotKeys();

View File

@ -39,6 +39,18 @@ const char *const defaultValue(const char *key)
IniUser::IniUser(Settings *settings) : MapSettings(settings) { }
QString IniUser::hotKeyValue(const QString &key) const
{
const auto &defaultValue = HotKey::defaultValue(key.toLatin1());
return valueText("hotKey/" + key, defaultValue);
}
void IniUser::setHotKeyValue(const QString &key, const QString &v)
{
setValue("hotKey/" + key, v);
}
void IniUser::saveDefaultIni()
{
setLanguage(defaultLanguage());

View File

@ -58,11 +58,8 @@ public:
bool hotKeyGlobal() const { return valueBool("hotKey/global", true); }
void setHotKeyGlobal(bool v) { setValue("hotKey/global", v, true); }
QString hotKeyValue(const QString &key, const QString &defaultValue = {}) const
{
return valueText("hotKey/" + key, defaultValue);
}
void setHotKeyValue(const QString &key, const QString &v) { setValue("hotKey/" + key, v); }
QString hotKeyValue(const QString &key) const;
void setHotKeyValue(const QString &key, const QString &v);
bool splashWindowVisible() const { return valueBool("splashWindow/visible", true); }
void setSplashWindowVisible(bool on) { setValue("splashWindow/visible", on, true); }