UI: Options: Add ability to set tray icon click actions

This commit is contained in:
Nodir Temirkhodjaev 2022-02-11 15:55:21 +03:00
parent 05843839a5
commit e267de3260
7 changed files with 299 additions and 21 deletions

View File

@ -18,6 +18,7 @@
#include <form/controls/controlutil.h>
#include <form/dialog/passworddialog.h>
#include <form/opt/optionscontroller.h>
#include <form/tray/trayicon.h>
#include <fortmanager.h>
#include <fortsettings.h>
#include <manager/translationmanager.h>
@ -143,6 +144,7 @@ void OptionsPage::onRetranslateUi()
m_gbStartup->setTitle(tr("Startup"));
m_gbTraffic->setTitle(tr("Traffic"));
m_gbGlobal->setTitle(tr("Global"));
m_gbTray->setTitle(tr("Tray"));
m_gbLogs->setTitle(tr("Logs"));
m_gbDriver->setTitle(tr("Driver"));
m_gbNewVersion->setTitle(tr("New Version"));
@ -172,6 +174,12 @@ void OptionsPage::onRetranslateUi()
m_labelLanguage->setText(tr("Language:"));
m_labelTrayEvent->setText(tr("Event:"));
m_labelTrayAction->setText(tr("Action:"));
retranslateComboTrayEvent();
retranslateComboTrayAction();
refreshComboTrayAction();
m_cbLogDebug->setText(tr("Log debug messages"));
m_cbLogConsole->setText(tr("Show log messages in console"));
@ -187,7 +195,7 @@ void OptionsPage::retranslateComboStartMode()
const QStringList list = { tr("Disabled"), tr("For current user"), tr("For all users") };
int currentIndex = m_comboAutoRun->currentIndex();
if (m_comboAutoRun->currentIndex() < 0) {
if (currentIndex < 0) {
currentIndex = m_currentAutoRunMode;
}
@ -226,6 +234,32 @@ void OptionsPage::retranslateEditPassword()
settings()->hasPassword() ? tr("Installed") : tr("Not Installed"));
}
void OptionsPage::retranslateComboTrayEvent()
{
const QStringList list = { tr("Single Click"), tr("Double Click"), tr("Middle Click") };
int currentIndex = m_comboTrayEvent->currentIndex();
if (currentIndex < 0) {
currentIndex = 0;
}
m_comboTrayEvent->clear();
m_comboTrayEvent->addItems(list);
m_comboTrayEvent->setCurrentIndex(currentIndex);
}
void OptionsPage::retranslateComboTrayAction()
{
const QStringList list = { tr("Show Programs"), tr("Show Options"), tr("Show Statistics"),
tr("Show/Hide Traffic Graph"), tr("Switch Filter Enabled"), tr("Switch Stop Traffic"),
tr("Switch Stop Internet Traffic"), tr("Switch Auto-Allow New Programs") };
m_comboTrayAction->clear();
m_comboTrayAction->addItems(list);
m_comboTrayAction->setCurrentIndex(-1);
}
void OptionsPage::retranslateDriverMessage()
{
const auto text = driverManager()->isDeviceError()
@ -281,6 +315,10 @@ QLayout *OptionsPage::setupColumn1()
setupGlobalBox();
layout->addWidget(m_gbGlobal);
// Tray Group Box
setupTrayBox();
layout->addWidget(m_gbTray);
// Logs Group Box
setupLogsBox();
layout->addWidget(m_gbLogs);
@ -475,6 +513,52 @@ void OptionsPage::setupComboLanguage()
connect(translationManager(), &TranslationManager::languageChanged, this, refreshComboLanguage);
}
void OptionsPage::setupTrayBox()
{
// Tray Event & Action Rows
auto eventLayout = setupTrayEventLayout();
auto actionLayout = setupTrayActionLayout();
auto layout = new QVBoxLayout();
layout->addLayout(eventLayout);
layout->addLayout(actionLayout);
m_gbTray = new QGroupBox(this);
m_gbTray->setLayout(layout);
}
void OptionsPage::refreshComboTrayAction()
{
const TrayIcon::ActionType actionType = windowManager()->trayIcon()->clickEventActionType(
static_cast<TrayIcon::ClickType>(m_comboTrayEvent->currentIndex()));
m_comboTrayAction->setCurrentIndex(actionType);
}
QLayout *OptionsPage::setupTrayEventLayout()
{
m_labelTrayEvent = ControlUtil::createLabel();
m_comboTrayEvent = ControlUtil::createComboBox(
QStringList(), [&](int /*index*/) { refreshComboTrayAction(); });
m_comboTrayEvent->setFixedWidth(200);
return ControlUtil::createRowLayout(m_labelTrayEvent, m_comboTrayEvent);
}
QLayout *OptionsPage::setupTrayActionLayout()
{
m_labelTrayAction = ControlUtil::createLabel();
m_comboTrayAction = ControlUtil::createComboBox(QStringList(), [&](int index) {
windowManager()->trayIcon()->setClickEventActionType(
static_cast<TrayIcon::ClickType>(m_comboTrayEvent->currentIndex()),
static_cast<TrayIcon::ActionType>(index));
});
m_comboTrayAction->setFixedWidth(200);
return ControlUtil::createRowLayout(m_labelTrayAction, m_comboTrayAction);
}
void OptionsPage::setupLogsBox()
{
m_cbLogDebug = ControlUtil::createCheckBox(ini()->logDebug(), [&](bool checked) {

View File

@ -25,6 +25,8 @@ private:
void retranslateComboStartMode();
void retranslateEditPassword();
void retranslateComboTrayEvent();
void retranslateComboTrayAction();
void retranslateDriverMessage();
void setupStartup();
@ -40,6 +42,10 @@ private:
void setupPasswordLock();
QLayout *setupLangLayout();
void setupComboLanguage();
void setupTrayBox();
void refreshComboTrayAction();
QLayout *setupTrayEventLayout();
QLayout *setupTrayActionLayout();
void setupLogsBox();
QLayout *setupColumn2();
void setupDriverBox();
@ -55,6 +61,7 @@ private:
QGroupBox *m_gbStartup = nullptr;
QGroupBox *m_gbTraffic = nullptr;
QGroupBox *m_gbGlobal = nullptr;
QGroupBox *m_gbTray = nullptr;
QGroupBox *m_gbLogs = nullptr;
QGroupBox *m_gbDriver = nullptr;
QGroupBox *m_gbNewVersion = nullptr;
@ -74,6 +81,10 @@ private:
QPushButton *m_btPasswordLock = nullptr;
QLabel *m_labelLanguage = nullptr;
QComboBox *m_comboLanguage = nullptr;
QLabel *m_labelTrayEvent = nullptr;
QComboBox *m_comboTrayEvent = nullptr;
QLabel *m_labelTrayAction = nullptr;
QComboBox *m_comboTrayAction = nullptr;
QCheckBox *m_cbLogDebug = nullptr;
QCheckBox *m_cbLogConsole = nullptr;
QLabel *m_iconDriver = nullptr;

View File

@ -20,6 +20,103 @@
namespace {
const char *const eventSingleClick = "singleClick";
const char *const eventDoubleClick = "doubleClick";
const char *const eventMiddleClick = "middleClick";
const char *const actionShowPrograms = "Programs";
const char *const actionShowOptions = "Options";
const char *const actionShowStatistics = "Statistics";
const char *const actionShowTrafficGraph = "TrafficGraph";
const char *const actionSwitchFilterEnabled = "FilterEnabled";
const char *const actionSwitchStopTraffic = "StopTraffic";
const char *const actionSwitchStopInetTraffic = "StopInetTraffic";
const char *const actionSwitchAutoAllowPrograms = "AutoAllowPrograms";
QString clickNameByType(TrayIcon::ClickType clickType)
{
switch (clickType) {
case TrayIcon::SingleClick:
return eventSingleClick;
case TrayIcon::DoubleClick:
return eventDoubleClick;
case TrayIcon::MiddleClick:
return eventMiddleClick;
default:
return QString();
}
}
QString actionNameByType(TrayIcon::ActionType actionType)
{
switch (actionType) {
case TrayIcon::ActionShowPrograms:
return actionShowPrograms;
case TrayIcon::ActionShowOptions:
return actionShowOptions;
case TrayIcon::ActionShowStatistics:
return actionShowStatistics;
case TrayIcon::ActionShowTrafficGraph:
return actionShowTrafficGraph;
case TrayIcon::ActionSwitchFilterEnabled:
return actionSwitchFilterEnabled;
case TrayIcon::ActionSwitchStopTraffic:
return actionSwitchStopTraffic;
case TrayIcon::ActionSwitchStopInetTraffic:
return actionSwitchStopInetTraffic;
case TrayIcon::ActionSwitchAutoAllowPrograms:
return actionSwitchAutoAllowPrograms;
default:
return QString();
}
}
TrayIcon::ActionType actionTypeByName(const QString &name)
{
if (name.isEmpty())
return TrayIcon::ActionNone;
if (name == actionShowPrograms)
return TrayIcon::ActionShowPrograms;
if (name == actionShowOptions)
return TrayIcon::ActionShowOptions;
if (name == actionShowStatistics)
return TrayIcon::ActionShowStatistics;
if (name == actionShowTrafficGraph)
return TrayIcon::ActionShowTrafficGraph;
if (name == actionSwitchFilterEnabled)
return TrayIcon::ActionSwitchFilterEnabled;
if (name == actionSwitchStopTraffic)
return TrayIcon::ActionSwitchStopTraffic;
if (name == actionSwitchStopInetTraffic)
return TrayIcon::ActionSwitchStopInetTraffic;
if (name == actionSwitchAutoAllowPrograms)
return TrayIcon::ActionSwitchAutoAllowPrograms;
return TrayIcon::ActionNone;
}
TrayIcon::ActionType defaultActionTypeByClick(TrayIcon::ClickType clickType)
{
switch (clickType) {
case TrayIcon::SingleClick:
return TrayIcon::ActionShowPrograms;
case TrayIcon::DoubleClick:
return TrayIcon::ActionShowOptions;
case TrayIcon::MiddleClick:
return TrayIcon::ActionShowStatistics;
default:
return TrayIcon::ActionNone;
}
}
void setActionCheckable(QAction *action, bool checked = false, const QObject *receiver = nullptr,
const char *member = nullptr)
{
@ -100,6 +197,14 @@ WindowManager *TrayIcon::windowManager() const
return ctrl()->windowManager();
}
void TrayIcon::onMouseClicked(TrayIcon::ClickType clickType)
{
QAction *action = m_clickActions[clickType];
if (action) {
action->trigger();
}
}
void TrayIcon::onTrayActivated(QSystemTrayIcon::ActivationReason reason)
{
switch (reason) {
@ -108,23 +213,23 @@ void TrayIcon::onTrayActivated(QSystemTrayIcon::ActivationReason reason)
QTimer::singleShot(QApplication::doubleClickInterval(), this, [&] {
if (m_trayTriggered) {
m_trayTriggered = false;
emit mouseClicked();
onMouseClicked(SingleClick);
}
});
break;
case QSystemTrayIcon::DoubleClick:
if (m_trayTriggered) {
m_trayTriggered = false;
emit mouseDoubleClicked();
onMouseClicked(DoubleClick);
}
break;
case QSystemTrayIcon::MiddleClick:
m_trayTriggered = false;
emit mouseMiddleClicked();
onMouseClicked(MiddleClick);
break;
case QSystemTrayIcon::Context:
m_trayTriggered = false;
emit mouseRightClicked(QCursor::pos());
showTrayMenu(QCursor::pos());
break;
default:
break;
@ -180,7 +285,7 @@ void TrayIcon::retranslateUi()
m_filterEnabledAction->setText(tr("Filter Enabled"));
m_stopTrafficAction->setText(tr("Stop Traffic"));
m_stopInetTrafficAction->setText(tr("Stop Internet Traffic"));
m_allowAllNewAction->setText(tr("Auto-Allow New Programs"));
m_autoAllowProgsAction->setText(tr("Auto-Allow New Programs"));
m_quitAction->setText(tr("Quit"));
}
@ -193,6 +298,8 @@ void TrayIcon::setupUi()
updateTrayMenu();
updateTrayIcon();
updateClickActions();
}
void TrayIcon::setupTrayMenu()
@ -232,8 +339,9 @@ void TrayIcon::setupTrayMenu()
addAction(m_menu, QIcon(), QString(), this, SLOT(saveTrayFlags()), true);
addHotKey(m_stopInetTrafficAction, iniUser()->hotKeyStopInetTraffic());
m_allowAllNewAction = addAction(m_menu, QIcon(), QString(), this, SLOT(saveTrayFlags()), true);
addHotKey(m_allowAllNewAction, iniUser()->hotKeyAllowAllNew());
m_autoAllowProgsAction =
addAction(m_menu, QIcon(), QString(), this, SLOT(saveTrayFlags()), true);
addHotKey(m_autoAllowProgsAction, iniUser()->hotKeyAllowAllNew());
m_menu->addSeparator();
@ -263,12 +371,12 @@ void TrayIcon::updateTrayMenuFlags()
m_filterEnabledAction->setEnabled(editEnabled);
m_stopTrafficAction->setEnabled(editEnabled);
m_stopInetTrafficAction->setEnabled(editEnabled);
m_allowAllNewAction->setEnabled(editEnabled);
m_autoAllowProgsAction->setEnabled(editEnabled);
m_filterEnabledAction->setChecked(conf()->filterEnabled());
m_stopTrafficAction->setChecked(conf()->stopTraffic());
m_stopInetTrafficAction->setChecked(conf()->stopInetTraffic());
m_allowAllNewAction->setChecked(conf()->allowAllNew());
m_autoAllowProgsAction->setChecked(conf()->allowAllNew());
int appGroupIndex = 0;
for (QAction *action : qAsConst(m_appGroupActions)) {
@ -308,7 +416,7 @@ void TrayIcon::saveTrayFlags()
conf()->setFilterEnabled(m_filterEnabledAction->isChecked());
conf()->setStopTraffic(m_stopTrafficAction->isChecked());
conf()->setStopInetTraffic(m_stopInetTrafficAction->isChecked());
conf()->setAllowAllNew(m_allowAllNewAction->isChecked());
conf()->setAllowAllNew(m_autoAllowProgsAction->isChecked());
int i = 0;
for (AppGroup *appGroup : conf()->appGroups()) {
@ -337,3 +445,60 @@ void TrayIcon::removeHotKeys()
{
hotKeyManager()->removeActions();
}
TrayIcon::ActionType TrayIcon::clickEventActionType(ClickType clickType) const
{
const QString eventName = clickNameByType(clickType);
const QString actionName = iniUser()->trayAction(eventName);
const ActionType actionType = actionTypeByName(actionName);
return (actionType != ActionNone) ? actionType : defaultActionTypeByClick(clickType);
}
void TrayIcon::setClickEventActionType(ClickType clickType, ActionType actionType)
{
const QString eventName = clickNameByType(clickType);
const QString actionName = actionNameByType(actionType);
iniUser()->setTrayAction(eventName, actionName);
updateClickActions();
}
void TrayIcon::updateClickActions()
{
m_clickActions[SingleClick] = clickActionFromIni(SingleClick);
m_clickActions[DoubleClick] = clickActionFromIni(DoubleClick);
m_clickActions[MiddleClick] = clickActionFromIni(MiddleClick);
}
QAction *TrayIcon::clickActionFromIni(ClickType clickType) const
{
const ActionType actionType = clickEventActionType(clickType);
return clickActionByType(actionType);
}
QAction *TrayIcon::clickActionByType(ActionType actionType) const
{
switch (actionType) {
case TrayIcon::ActionShowPrograms:
return m_programsAction;
case TrayIcon::ActionShowOptions:
return m_optionsAction;
case TrayIcon::ActionShowStatistics:
return m_statisticsAction;
case TrayIcon::ActionShowTrafficGraph:
return m_graphAction;
case TrayIcon::ActionSwitchFilterEnabled:
return m_filterEnabledAction;
case TrayIcon::ActionSwitchStopTraffic:
return m_stopTrafficAction;
case TrayIcon::ActionSwitchStopInetTraffic:
return m_stopInetTrafficAction;
case TrayIcon::ActionSwitchAutoAllowPrograms:
return m_autoAllowProgsAction;
}
return nullptr;
}

View File

@ -19,6 +19,19 @@ class TrayIcon : public QSystemTrayIcon
Q_OBJECT
public:
enum ClickType : qint8 { SingleClick = 0, DoubleClick, MiddleClick, ClickTypeCount };
enum ActionType : qint8 {
ActionNone = -1,
ActionShowPrograms = 0,
ActionShowOptions,
ActionShowStatistics,
ActionShowTrafficGraph,
ActionSwitchFilterEnabled,
ActionSwitchStopTraffic,
ActionSwitchStopInetTraffic,
ActionSwitchAutoAllowPrograms
};
explicit TrayIcon(QObject *parent = nullptr);
~TrayIcon() override;
@ -31,11 +44,8 @@ public:
HotKeyManager *hotKeyManager() const;
WindowManager *windowManager() const;
signals:
void mouseClicked();
void mouseDoubleClicked();
void mouseMiddleClicked();
void mouseRightClicked(const QPoint &pos);
ActionType clickEventActionType(ClickType clickType) const;
void setClickEventActionType(ClickType clickType, ActionType actionType);
public slots:
void updateTrayIcon(bool alerted = false);
@ -44,6 +54,7 @@ public slots:
void updateTrayMenu(bool onlyFlags = false);
protected slots:
void onMouseClicked(TrayIcon::ClickType clickType);
void onTrayActivated(QSystemTrayIcon::ActivationReason reason);
void saveTrayFlags();
@ -63,6 +74,11 @@ private:
void updateHotKeys();
void removeHotKeys();
void updateClickActions();
QAction *clickActionFromIni(ClickType clickType) const;
QAction *clickActionByType(ActionType actionType) const;
private:
bool m_trayTriggered : 1;
@ -77,9 +93,11 @@ private:
QAction *m_filterEnabledAction = nullptr;
QAction *m_stopTrafficAction = nullptr;
QAction *m_stopInetTrafficAction = nullptr;
QAction *m_allowAllNewAction = nullptr;
QAction *m_autoAllowProgsAction = nullptr;
QAction *m_quitAction = nullptr;
QList<QAction *> m_appGroupActions;
QAction *m_clickActions[ClickTypeCount] = { nullptr };
};
#endif // TRAYICON_H

View File

@ -107,10 +107,6 @@ void WindowManager::setupTrayIcon()
{
m_trayIcon = new TrayIcon(this);
connect(m_trayIcon, &TrayIcon::mouseClicked, this, &WindowManager::showProgramsWindow);
connect(m_trayIcon, &TrayIcon::mouseDoubleClicked, this, &WindowManager::showOptionsWindow);
connect(m_trayIcon, &TrayIcon::mouseMiddleClicked, this, &WindowManager::showStatisticsWindow);
connect(m_trayIcon, &TrayIcon::mouseRightClicked, m_trayIcon, &TrayIcon::showTrayMenu);
connect(m_trayIcon, &QSystemTrayIcon::messageClicked, this,
&WindowManager::onTrayMessageClicked);

View File

@ -31,6 +31,7 @@ public:
ServicesWindow *serviceWindow() const { return m_serviceWindow; }
ZonesWindow *zoneWindow() const { return m_zoneWindow; }
GraphWindow *graphWindow() const { return m_graphWindow; }
TrayIcon *trayIcon() const { return m_trayIcon; }
void setUp() override;
void tearDown() override;

View File

@ -32,6 +32,9 @@ public:
}
QString hotKeyQuit() const { return valueText("hotKey/quit"); }
QString trayAction(const QString &event) const { return valueText("tray/" + event); }
void setTrayAction(const QString &event, const QString &v) { setValue("tray/" + event, v); }
QRect progWindowGeometry() const { return value("progWindow/geometry").toRect(); }
void setProgWindowGeometry(const QRect &v) { setValue("progWindow/geometry", v); }