5
5
* https://lxqt.org
6
6
*
7
7
* Copyright: 2011 Razor team
8
+ * 2025~ LXQt team
8
9
* Authors:
9
10
* Christian Surlykke <[email protected] >
11
+
10
12
*
11
13
* This program or library is free software; you can redistribute it
12
14
* and/or modify it under the terms of the GNU Lesser General Public
25
27
*
26
28
* END_COMMON_COPYRIGHT_HEADER */
27
29
28
- #include < QDebug>
29
- #include < QApplication>
30
30
#include < QProcess>
31
31
#include < QActionGroup>
32
32
#include < QMessageBox>
33
- #include < QToolTip>
34
- #include < QHelpEvent>
35
33
#include < QPixmapCache>
36
34
#include < QPainter>
37
35
#include < QtSvg/QSvgRenderer>
38
- #include < Solid/Battery>
39
- #include < Solid/Device>
40
- #include < QIcon>
41
36
#include < QStringBuilder>
42
- #include < QGlobalStatic>
43
37
44
38
#include " trayicon.h"
45
- #include " batteryhelper.h"
46
39
#include " ../config/powermanagementsettings.h"
47
40
48
41
#include < LXQt/Globals>
49
42
#include < LXQt/Notification>
50
43
#include " PowerProfiles.h"
44
+ #include < QTimer>
51
45
52
- TrayIcon::TrayIcon (Solid::Battery *battery, QObject *parent)
46
+ QList<TrayIcon *> TrayIcon::msInstances;
47
+ std::unique_ptr<QMenu> TrayIcon::msContextMenu{nullptr };
48
+ std::unique_ptr<QTimer> TrayIcon::msPauseTimer{nullptr };
49
+ std::unique_ptr<QActionGroup> TrayIcon::msPauseActions{nullptr };
50
+
51
+ TrayIcon::TrayIcon (QObject *parent)
53
52
: QSystemTrayIcon(parent),
54
- mBattery(battery),
55
- mIconProducer(battery),
56
- mContextMenu(),
53
+ mBaseIcon(QIcon::fromTheme(QL1S(" preferences-system-power-management" ))),
57
54
mHasPauseEmblem(false )
58
55
{
59
- connect (mBattery , &Solid::Battery::chargePercentChanged, this , &TrayIcon::updateTooltip);
60
- connect (mBattery , &Solid::Battery::chargeStateChanged, this , &TrayIcon::updateTooltip);
61
- connect (mBattery , &Solid::Battery::timeToEmptyChanged, this , &TrayIcon::updateTooltip);
62
- connect (mBattery , &Solid::Battery::timeToFullChanged, this , &TrayIcon::updateTooltip);
63
- updateTooltip ();
64
56
65
- connect (&mIconProducer , &IconProducer::iconChanged, this , &TrayIcon::iconChanged);
66
57
iconChanged ();
67
58
68
59
connect (this , &TrayIcon::activated, this , &TrayIcon::onActivated);
69
60
70
- mContextMenu .addAction (QIcon::fromTheme (QStringLiteral (" configure" )), tr (" Configure" ),
71
- this , &TrayIcon::onConfigureTriggered);
61
+ if (!msPauseTimer)
62
+ {
63
+ msPauseTimer.reset (new QTimer);
64
+ msPauseTimer->setSingleShot (true );
65
+ msPauseTimer->setTimerType (Qt::VeryCoarseTimer);
66
+ connect (msPauseTimer.get (), &QTimer::timeout, [] { onPauseTimeout (); });
67
+ }
68
+ if (!msContextMenu) {
69
+ msContextMenu.reset (new QMenu);
70
+ connect (msContextMenu->addAction (QIcon::fromTheme (QStringLiteral (" configure" )), tr (" Configure" )), &QAction::triggered, [] { onConfigureTriggered (); });
72
71
73
- // pause actions
74
- mPauseActions = new QActionGroup ( this );
75
- mPauseActions ->setExclusionPolicy (QActionGroup::ExclusionPolicy::ExclusiveOptional);
76
- connect (mPauseActions , &QActionGroup::triggered, this , &TrayIcon:: onPauseTriggered);
72
+ // pause actions
73
+ msPauseActions. reset ( new QActionGroup{ nullptr } );
74
+ msPauseActions ->setExclusionPolicy (QActionGroup::ExclusionPolicy::ExclusiveOptional);
75
+ connect (msPauseActions. get () , &QActionGroup::triggered, [] (QAction * action) { onPauseTriggered (action); } );
77
76
78
- QAction *a = new QAction (tr (" 30 minutes" ), mPauseActions );
79
- a->setCheckable (true );
80
- a->setData (PAUSE::Half);
77
+ QAction *a = new QAction (tr (" 30 minutes" ), msPauseActions. get () );
78
+ a->setCheckable (true );
79
+ a->setData (PAUSE::Half);
81
80
82
- a = new QAction (tr (" 1 hour" ), mPauseActions );
83
- a->setCheckable (true );
84
- a->setData (PAUSE::One);
81
+ a = new QAction (tr (" 1 hour" ), msPauseActions. get () );
82
+ a->setCheckable (true );
83
+ a->setData (PAUSE::One);
85
84
86
- a = new QAction (tr (" 2 hours" ), mPauseActions );
87
- a->setCheckable (true );
88
- a->setData (PAUSE::Two);
85
+ a = new QAction (tr (" 2 hours" ), msPauseActions. get () );
86
+ a->setCheckable (true );
87
+ a->setData (PAUSE::Two);
89
88
90
- a = new QAction (tr (" 3 hours" ), mPauseActions );
91
- a->setCheckable (true );
92
- a->setData (PAUSE::Three);
89
+ a = new QAction (tr (" 3 hours" ), msPauseActions. get () );
90
+ a->setCheckable (true );
91
+ a->setData (PAUSE::Three);
93
92
94
- a = new QAction (tr (" 4 hours" ), mPauseActions );
95
- a->setCheckable (true );
96
- a->setData (PAUSE::Four);
93
+ a = new QAction (tr (" 4 hours" ), msPauseActions. get () );
94
+ a->setCheckable (true );
95
+ a->setData (PAUSE::Four);
97
96
98
- QMenu *pauseMenu = mContextMenu . addMenu (QIcon::fromTheme (QStringLiteral (" media-playback-pause" )),
99
- tr (" Pause idleness checks" ));
100
- pauseMenu->addActions (mPauseActions ->actions ());
97
+ QMenu *pauseMenu = msContextMenu-> addMenu (QIcon::fromTheme (QStringLiteral (" media-playback-pause" )),
98
+ tr (" Pause idleness checks" ));
99
+ pauseMenu->addActions (msPauseActions ->actions ());
101
100
102
- // power-profiles actions
103
- mContextMenu . addAction (LXQt::PowerProfiles::instance ().menuAction ());
101
+ // power-profiles actions
102
+ msContextMenu-> addAction (LXQt::PowerProfiles::instance ().menuAction ());
104
103
105
- mContextMenu . addSeparator ();
104
+ msContextMenu-> addSeparator ();
106
105
107
- mContextMenu . addAction (QIcon::fromTheme (QStringLiteral (" help-about" )), tr (" About" ),
108
- this , & TrayIcon::onAboutTriggered );
109
- mContextMenu . addAction ( QIcon::fromTheme ( QStringLiteral ( " edit-delete " )), tr ( " Disable icon " ),
110
- this , &TrayIcon::onDisableIconTriggered );
111
- setContextMenu (& mContextMenu );
106
+ connect (msContextMenu-> addAction (QIcon::fromTheme (QStringLiteral (" help-about" )), tr (" About" )), &QAction::triggered, [] { TrayIcon::onAboutTriggered (); });
107
+ connect (msContextMenu-> addAction ( QIcon::fromTheme ( QStringLiteral ( " edit-delete " )), tr ( " Disable icon " )), &QAction::triggered, [] { TrayIcon::onDisableIconTriggered (); } );
108
+ }
109
+ setContextMenu (msContextMenu. get () );
110
+ msInstances. push_back ( this );
112
111
}
113
112
114
113
TrayIcon::~TrayIcon ()
115
114
{
115
+ msInstances.removeOne (this );
116
+ if (msInstances.empty ())
117
+ {
118
+ msPauseTimer.reset (nullptr );
119
+ msPauseActions.reset (nullptr );
120
+ msContextMenu.reset (nullptr );
121
+ }
122
+ }
123
+
124
+ /* virtual*/ const QIcon & TrayIcon::getIcon () const
125
+ {
126
+ return mBaseIcon ;
116
127
}
117
128
118
129
void TrayIcon::iconChanged ()
119
130
{
120
131
mHasPauseEmblem = PowerManagementSettings ().isIdlenessWatcherPaused ();
121
- setIcon (mHasPauseEmblem ? emblemizedIcon () : mIconProducer . mIcon );
132
+ setIcon (mHasPauseEmblem ? emblemizedIcon () : getIcon () );
122
133
}
123
134
124
135
QIcon TrayIcon::emblemizedIcon ()
@@ -131,7 +142,7 @@ QIcon TrayIcon::emblemizedIcon()
131
142
);
132
143
133
144
const QSize icnSize (200 , 200 ); // NOTE: QSystemTrayIcon::geometry() gives an empty rectangle
134
- QPixmap icnPix = mIconProducer . mIcon .pixmap (icnSize);
145
+ QPixmap icnPix = getIcon () .pixmap (icnSize);
135
146
const qreal pixelRatio = icnPix.devicePixelRatio ();
136
147
const QSize icnPixSize ((QSizeF (icnSize) * pixelRatio).toSize ());
137
148
@@ -162,24 +173,10 @@ QIcon TrayIcon::emblemizedIcon()
162
173
return QIcon (pix);
163
174
}
164
175
165
- void TrayIcon::updateTooltip ()
176
+ void TrayIcon::onPauseTimeout ()
166
177
{
167
- QString stateStr = mBattery ->chargePercent () <= 0 && mBattery ->chargeState () == Solid::Battery::NoCharge ?
168
- tr (" Empty" ) : BatteryHelper::stateToString (mBattery ->chargeState ());
169
- QString tooltip = stateStr % QString::fromLatin1 (" (%1%)" ).arg (mBattery ->chargePercent ());
170
- switch (mBattery ->chargeState ())
171
- {
172
- case Solid::Battery::Charging:
173
- tooltip += QL1S (" , " ) % BatteryHelper::timeToFullString (mBattery ->timeToFull ());
174
- break ;
175
- case Solid::Battery::Discharging:
176
- tooltip += QL1S (" , " ) % BatteryHelper::timeToEmptyString (mBattery ->timeToEmpty ());
177
- break ;
178
- default :
179
- break ;
180
- }
181
-
182
- setToolTip (tooltip);
178
+ for (const auto &trayIcon : std::as_const (msInstances))
179
+ trayIcon->setPause (TrayIcon::PAUSE::None);
183
180
}
184
181
185
182
void TrayIcon::onConfigureTriggered ()
@@ -189,8 +186,18 @@ void TrayIcon::onConfigureTriggered()
189
186
190
187
void TrayIcon::onPauseTriggered (QAction *action)
191
188
{
192
- emit pauseChanged (!action->isChecked () ? PAUSE::None
193
- : static_cast <PAUSE>(action->data ().toInt ()));
189
+ const PAUSE duration = !action->isChecked () ? None : static_cast <PAUSE>(action->data ().toInt ());
190
+ if (duration == None)
191
+ {
192
+ onPauseTimeout ();
193
+ msPauseTimer->stop ();
194
+ }
195
+ else
196
+ {
197
+ for (const auto &trayIcon : std::as_const (msInstances))
198
+ trayIcon->setPause (duration);
199
+ msPauseTimer->start (getPauseInterval (duration));
200
+ }
194
201
}
195
202
196
203
void TrayIcon::onAboutTriggered ()
@@ -236,7 +243,7 @@ void TrayIcon::onActivated(QSystemTrayIcon::ActivationReason reason)
236
243
void TrayIcon::setPause (PAUSE duration)
237
244
{
238
245
// add/remove the pause emblem and correct the checked action if needed
239
- QAction *checked = mPauseActions ->checkedAction ();
246
+ QAction *checked = msPauseActions ->checkedAction ();
240
247
if (duration == PAUSE::None)
241
248
{
242
249
PowerManagementSettings ().setIdlenessWatcherPaused (false );
@@ -252,7 +259,7 @@ void TrayIcon::setPause(PAUSE duration)
252
259
iconChanged (); // adds the pause emblem
253
260
if (checked == nullptr || checked->data ().toInt () != duration)
254
261
{
255
- const auto actions = mPauseActions ->actions ();
262
+ const auto actions = msPauseActions ->actions ();
256
263
for (const auto &a : actions)
257
264
{
258
265
if (a->data ().toInt () == duration)
0 commit comments