Skip to content

Commit 8d4bc1b

Browse files
committed
Refactoring tray / icon / theme
1 parent c9e9a31 commit 8d4bc1b

18 files changed

Lines changed: 314 additions & 332 deletions

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ set(PROJECT_SOURCES
175175
include/ui/mainwindow.ui
176176
include/ui/widget/StartStopButton.hpp
177177
src/ui/widget/StartStopButton.cpp
178+
include/ui/widget/TrayPopupFrame.hpp
179+
src/ui/widget/TrayPopupFrame.cpp
178180
include/ui/widget/TrayProfileSelector.hpp
179181
src/ui/widget/TrayProfileSelector.cpp
180182
include/ui/widget/TrayOtpCodes.hpp

include/ui/mainwindow.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#ifndef MW_INTERFACE
1818

19+
#include <optional>
1920
#include <QKeyEvent>
2021
#include <QSystemTrayIcon>
2122
#include <QPointer>
@@ -38,6 +39,7 @@
3839

3940
#include "group/GroupSort.hpp"
4041
#include "include/global/GuiUtils.hpp"
42+
#include "include/ui/setting/Icon.hpp"
4143
#include "include/ui/utils/DataViewHtmlGenerator.h"
4244
#include "include/ui/utils/ProfilesFilterProxyModel.h"
4345
#include "include/ui/utils/ProfilesTableModel.h"
@@ -240,7 +242,7 @@ private slots:
240242
QTextDocument *qvLogDocument = new QTextDocument(this);
241243
//
242244
QString title_error;
243-
int icon_status = -1;
245+
std::optional<Icon::TrayIconStatus> icon_status;
244246
std::shared_ptr<Configs::Profile> running;
245247
int last_running_profile_id = -1;
246248
bool m_profileConnecting = false;
@@ -473,7 +475,7 @@ private slots:
473475
};
474476

475477
inline MainWindow *GetMainWindow() {
476-
return (MainWindow *) mainwindow;
478+
return qobject_cast<MainWindow *>(mainwindow);
477479
}
478480

479481
void UI_InitMainWindow();

include/ui/setting/Icon.hpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
#pragma once
22

3-
#include <QPixmap>
3+
#include <QIcon>
44

55
namespace Icon {
66

7-
enum TrayIconStatus {
8-
NONE,
9-
RUNNING,
10-
SYSTEM_PROXY,
11-
VPN,
12-
DNS,
13-
SYSTEM_PROXY_DNS,
7+
enum class TrayIconStatus {
8+
None,
9+
Running,
10+
SystemProxy,
11+
Vpn,
12+
Dns,
13+
SystemProxyDns,
1414
};
1515

16-
QPixmap GetTrayIcon(TrayIconStatus status);
16+
QIcon GetTrayIcon(TrayIconStatus status);
17+
18+
// Drop cached icons so the next GetTrayIcon reloads from disk/resources.
19+
// Call when custom-icon files are replaced or the custom-icon setting flips.
20+
void InvalidateTrayIconCache();
1721
} // namespace Icon

include/ui/setting/ThemeManager.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ class ThemeManager : public QObject {
1515
void themeChanged(QString themeName);
1616
};
1717

18-
extern ThemeManager *themeManager;
18+
ThemeManager *themeManager();

include/ui/widget/TrayOtpCodes.hpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,27 @@
11
#pragma once
22

3-
#include <QFrame>
43
#include <QList>
54
#include <QString>
65
#include <memory>
76

87
#include "include/database/entities/OtpProfile.h"
8+
#include "include/ui/widget/TrayPopupFrame.hpp"
99

10-
class QLineEdit;
11-
class QListWidget;
1210
class QListWidgetItem;
1311
class QTimer;
1412

1513
// A real window, not a tray submenu, for the reason given on TrayProfileSelector.
16-
class TrayOtpCodes : public QFrame {
14+
class TrayOtpCodes : public TrayPopupFrame {
1715
Q_OBJECT
1816

1917
public:
2018
explicit TrayOtpCodes(QWidget *parent = nullptr);
2119

22-
void popupAt(const QPoint &globalPos);
23-
2420
protected:
25-
void keyPressEvent(QKeyEvent *event) override;
26-
2721
bool eventFilter(QObject *watched, QEvent *event) override;
2822

23+
void preparePopup() override;
24+
2925
private:
3026
void reload();
3127

@@ -36,10 +32,6 @@ class TrayOtpCodes : public QFrame {
3632

3733
void copyCurrent(const QListWidgetItem *item);
3834

39-
QLineEdit *search = nullptr;
40-
41-
QListWidget *list = nullptr;
42-
4335
QTimer *ticker = nullptr;
4436

4537
QList<std::shared_ptr<Configs::OtpProfile>> profiles;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#pragma once
2+
3+
#include <QFrame>
4+
5+
class QKeyEvent;
6+
class QLineEdit;
7+
class QListWidget;
8+
class QVBoxLayout;
9+
10+
// Shared chrome for the system-tray popups (profile picker, OTP codes): a
11+
// frameless always-on-top tool window, a rounded card, a search row with a
12+
// close button, and screen-clamped positioning.
13+
//
14+
// Subclasses own the list (and any extra header/footer) and the data that
15+
// fills it. Search/list keyboard handling that is common (Esc, Down from the
16+
// search box) lives here; item activation stays in the subclass.
17+
class TrayPopupFrame : public QFrame {
18+
Q_OBJECT
19+
20+
public:
21+
explicit TrayPopupFrame(QWidget *parent = nullptr);
22+
23+
// Rebuild contents, size to fit, place near globalPos (kept fully on the
24+
// containing screen), then show and focus the search box.
25+
void popupAt(const QPoint &globalPos);
26+
27+
protected:
28+
void keyPressEvent(QKeyEvent *event) override;
29+
bool eventFilter(QObject *watched, QEvent *event) override;
30+
31+
virtual void preparePopup() = 0;
32+
virtual void afterShow() {}
33+
34+
void clearSearch();
35+
void setListWidget(QListWidget *list);
36+
37+
QFrame *m_card = nullptr;
38+
QVBoxLayout *m_cardLayout = nullptr;
39+
QLineEdit *m_search = nullptr;
40+
QListWidget *m_list = nullptr;
41+
};

include/ui/widget/TrayProfileSelector.hpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
#pragma once
22

3-
#include <QFrame>
43
#include <QString>
54
#include <QStringList>
65
#include <QList>
76
#include <functional>
87
#include <utility>
98

9+
#include "include/ui/widget/TrayPopupFrame.hpp"
10+
1011
class QLabel;
11-
class QLineEdit;
12-
class QListWidget;
1312
class QListWidgetItem;
1413
class QPushButton;
1514
class QTimer;
@@ -26,7 +25,7 @@ class QTimer;
2625
// Behaviour: a rounded card with a debounced search box on top over a compact, paginated
2726
// list. A single click (or Enter) selects; it closes when it loses focus (like a menu) and
2827
// also has an explicit Close button.
29-
class TrayProfileSelector : public QFrame {
28+
class TrayProfileSelector : public TrayPopupFrame {
3029
Q_OBJECT
3130
public:
3231
enum Mode { Server, Routing };
@@ -45,14 +44,11 @@ class TrayProfileSelector : public QFrame {
4544

4645
TrayProfileSelector(Mode mode, Callbacks cb, QWidget *parent = nullptr);
4746

48-
// Show the panel anchored near globalPos (kept fully on the containing screen) and
49-
// focus the search box. Resets navigation/search to the top level first.
50-
void popupAt(const QPoint &globalPos);
51-
5247
protected:
5348
bool event(QEvent *e) override; // close when the panel loses activation
54-
void keyPressEvent(QKeyEvent *e) override; // Esc closes
5549
bool eventFilter(QObject *obj, QEvent *e) override; // list/search key handling
50+
void preparePopup() override;
51+
void afterShow() override;
5652

5753
private:
5854
void rebuild(); // repopulate for the current view/query/page
@@ -80,12 +76,10 @@ class TrayProfileSelector : public QFrame {
8076
QList<std::pair<int, QString>> m_routeCache;
8177
QStringList m_routeCacheLower;
8278

83-
QLineEdit *m_search = nullptr;
8479
QTimer *m_debounce = nullptr;
8580
QPushButton *m_backBtn = nullptr;
8681
QLabel *m_title = nullptr;
8782
QPushButton *m_stopBtn = nullptr;
88-
QListWidget *m_list = nullptr;
8983
QPushButton *m_prevBtn = nullptr;
9084
QLabel *m_pageLabel = nullptr;
9185
QPushButton *m_nextBtn = nullptr;

res/translations/ru_RU.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5443,7 +5443,7 @@ Your local edits are overwritten on each update.</source>
54435443
</message>
54445444
</context>
54455445
<context>
5446-
<name>TrayProfileSelector</name>
5446+
<name>TrayPopupFrame</name>
54475447
<message>
54485448
<source>Search…</source>
54495449
<translation>Поиск…</translation>
@@ -5452,6 +5452,9 @@ Your local edits are overwritten on each update.</source>
54525452
<source>Close</source>
54535453
<translation>Закрыть</translation>
54545454
</message>
5455+
</context>
5456+
<context>
5457+
<name>TrayProfileSelector</name>
54555458
<message>
54565459
<source>Back to groups</source>
54575460
<translation>Назад к группам</translation>

res/translations/zh_CN.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5489,7 +5489,7 @@ Your local edits are overwritten on each update.</source>
54895489
</message>
54905490
</context>
54915491
<context>
5492-
<name>TrayProfileSelector</name>
5492+
<name>TrayPopupFrame</name>
54935493
<message>
54945494
<source>Search…</source>
54955495
<translation>搜索...</translation>
@@ -5498,6 +5498,9 @@ Your local edits are overwritten on each update.</source>
54985498
<source>Close</source>
54995499
<translation>关闭</translation>
55005500
</message>
5501+
</context>
5502+
<context>
5503+
<name>TrayProfileSelector</name>
55015504
<message>
55025505
<source>Back to groups</source>
55035506
<translation>返回分组</translation>

src/ui/mainWindow/mainwindow_deeplink.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "include/global/PeriodicRunner.hpp"
1818
#include "include/sys/AutoRun.hpp"
1919
#include "include/ui/mainWindow/MainWindowInternal.h"
20+
#include "include/ui/setting/Icon.hpp"
2021
#include "include/ui/utils/ProfilesTableModel.h"
2122

2223
namespace {
@@ -267,7 +268,8 @@ void MainWindow::dialog_message_impl(MwMessage cmd, const QStringList &args) {
267268
updateLogFilterFields();
268269
ui->actionTraffic_Stats->setVisible(!settings->disable_traffic_aggregation);
269270
if (changed(MwArg::TrayIcon)) {
270-
icon_status = -1;
271+
Icon::InvalidateTrayIconCache();
272+
icon_status.reset();
271273
}
272274
if (changed(MwArg::MaxLogLines)) {
273275
qvLogDocument->setMaximumBlockCount(settings->max_log_line);

0 commit comments

Comments
 (0)