Skip to content

Commit 2ff0fd3

Browse files
committed
trayicon: Show default icon, if no battery one shown
1 parent 067d226 commit 2ff0fd3

9 files changed

+252
-125
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ set(SOURCES
1414
main.cpp
1515
powermanagementd.cpp
1616
trayicon.cpp
17+
trayiconbattery.cpp
1718
iconproducer.cpp
1819
powerbutton.cpp
1920
../config/powermanagementsettings.cpp

src/batterywatcher.cpp

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,6 @@ BatteryWatcher::BatteryWatcher(QObject *parent) : Watcher(parent)
6969

7070
settingsChanged();
7171
batteryChanged();
72-
73-
// pause timer
74-
mPauseTimer.setSingleShot(true);
75-
mPauseTimer.setTimerType(Qt::VeryCoarseTimer);
76-
connect(&mPauseTimer, &QTimer::timeout, this, &BatteryWatcher::onPauseTimeout);
7772
}
7873

7974
BatteryWatcher::~BatteryWatcher()
@@ -177,31 +172,9 @@ void BatteryWatcher::settingsChanged()
177172
{
178173
for (Solid::Battery *battery : std::as_const(mBatteries))
179174
{
180-
mTrayIcons.append(new TrayIcon(battery, this));
175+
mTrayIcons.append(new TrayIconBattery(battery, this));
181176
connect(mTrayIcons.last(), &TrayIcon::toggleShowInfo, mBatteryInfoDialog, &BatteryInfoDialog::toggleShow);
182-
connect(mTrayIcons.last(), &TrayIcon::pauseChanged, this, &BatteryWatcher::setPause);
183177
mTrayIcons.last()->show();
184178
}
185179
}
186180
}
187-
188-
void BatteryWatcher::onPauseTimeout()
189-
{
190-
for (const auto &trayIcon : std::as_const(mTrayIcons))
191-
trayIcon->setPause(TrayIcon::PAUSE::None);
192-
}
193-
194-
void BatteryWatcher::setPause(TrayIcon::PAUSE duration)
195-
{
196-
if (duration == TrayIcon::PAUSE::None)
197-
{
198-
onPauseTimeout();
199-
mPauseTimer.stop();
200-
}
201-
else
202-
{
203-
for (const auto &trayIcon : std::as_const(mTrayIcons))
204-
trayIcon->setPause(duration);
205-
mPauseTimer.start(TrayIcon::getPauseInterval(duration));
206-
}
207-
}

src/batterywatcher.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
#define BATTERYWATCHER_H
2929

3030
#include "watcher.h"
31-
#include "trayicon.h"
31+
#include "trayiconbattery.h"
3232
#include "batteryinfodialog.h"
3333
#include "../config/powermanagementsettings.h"
3434

@@ -47,13 +47,10 @@ class BatteryWatcher : public Watcher
4747
private slots:
4848
void batteryChanged();
4949
void settingsChanged();
50-
void onPauseTimeout();
51-
void setPause(TrayIcon::PAUSE duration);
5250

5351
private:
5452
QList<Solid::Battery*> mBatteries;
55-
QList<TrayIcon*> mTrayIcons;
56-
QTimer mPauseTimer;
53+
QList<TrayIconBattery*> mTrayIcons;
5754

5855
PowerManagementSettings mSettings;
5956
BatteryInfoDialog *mBatteryInfoDialog;

src/powermanagementd.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ PowerManagementd::PowerManagementd() :
4343
mBatterywatcherd(nullptr),
4444
mLidwatcherd(nullptr),
4545
mIdlenesswatcherd(nullptr),
46+
mPowerButton(nullptr),
47+
mTrayIcon(nullptr),
4648
mSettings()
4749
{
4850
connect(&mSettings, &PowerManagementSettings::settingsChanged, this, &PowerManagementd::settingsChanged);
@@ -70,6 +72,16 @@ void PowerManagementd::settingsChanged()
7072
mBatterywatcherd->deleteLater();
7173
mBatterywatcherd = nullptr;
7274
}
75+
if (!mTrayIcon && (!mBatterywatcherd || !mSettings.isShowIcon()))
76+
{
77+
mTrayIcon = new TrayIcon(this);
78+
mTrayIcon->show();
79+
} else if (mBatterywatcherd && mSettings.isShowIcon() && mTrayIcon)
80+
{
81+
mTrayIcon->hide();
82+
mTrayIcon->deleteLater();
83+
mTrayIcon = nullptr;
84+
}
7385

7486
if (mSettings.isLidWatcherEnabled() && !mLidwatcherd)
7587
{

src/powermanagementd.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class BatteryWatcher;
1717
class LidWatcher;
1818
class IdlenessWatcher;
1919
class PowerButton;
20+
class TrayIcon;
2021

2122
class PowerManagementd : public QObject
2223
{
@@ -36,7 +37,8 @@ private slots:
3637
BatteryWatcher* mBatterywatcherd;
3738
LidWatcher* mLidwatcherd;
3839
IdlenessWatcher* mIdlenesswatcherd;
39-
PowerButton *mPowerButton;
40+
PowerButton* mPowerButton;
41+
TrayIcon* mTrayIcon;
4042

4143
PowerManagementSettings mSettings;
4244
LXQt::Notification mNotification;

src/trayicon.cpp

Lines changed: 81 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
* https://lxqt.org
66
*
77
* Copyright: 2011 Razor team
8+
* 2025~ LXQt team
89
* Authors:
910
* Christian Surlykke <[email protected]>
11+
* Palo Kisa <[email protected]>
1012
*
1113
* This program or library is free software; you can redistribute it
1214
* and/or modify it under the terms of the GNU Lesser General Public
@@ -25,100 +27,109 @@
2527
*
2628
* END_COMMON_COPYRIGHT_HEADER */
2729

28-
#include <QDebug>
29-
#include <QApplication>
3030
#include <QProcess>
3131
#include <QActionGroup>
3232
#include <QMessageBox>
33-
#include <QToolTip>
34-
#include <QHelpEvent>
3533
#include <QPixmapCache>
3634
#include <QPainter>
3735
#include <QtSvg/QSvgRenderer>
38-
#include <Solid/Battery>
39-
#include <Solid/Device>
40-
#include <QIcon>
4136
#include <QStringBuilder>
42-
#include <QGlobalStatic>
4337

4438
#include "trayicon.h"
45-
#include "batteryhelper.h"
4639
#include "../config/powermanagementsettings.h"
4740

4841
#include <LXQt/Globals>
4942
#include <LXQt/Notification>
5043
#include "PowerProfiles.h"
44+
#include <QTimer>
5145

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)
5352
: QSystemTrayIcon(parent),
54-
mBattery(battery),
55-
mIconProducer(battery),
56-
mContextMenu(),
53+
mBaseIcon(QIcon::fromTheme(QL1S("preferences-system-power-management"))),
5754
mHasPauseEmblem(false)
5855
{
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();
6456

65-
connect(&mIconProducer, &IconProducer::iconChanged, this, &TrayIcon::iconChanged);
6657
iconChanged();
6758

6859
connect(this, &TrayIcon::activated, this, &TrayIcon::onActivated);
6960

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(); });
7271

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); });
7776

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);
8180

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);
8584

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);
8988

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);
9392

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);
9796

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());
101100

102-
// power-profiles actions
103-
mContextMenu.addAction(LXQt::PowerProfiles::instance().menuAction());
101+
// power-profiles actions
102+
msContextMenu->addAction(LXQt::PowerProfiles::instance().menuAction());
104103

105-
mContextMenu.addSeparator();
104+
msContextMenu->addSeparator();
106105

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);
112111
}
113112

114113
TrayIcon::~TrayIcon()
115114
{
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;
116127
}
117128

118129
void TrayIcon::iconChanged()
119130
{
120131
mHasPauseEmblem = PowerManagementSettings().isIdlenessWatcherPaused();
121-
setIcon(mHasPauseEmblem ? emblemizedIcon() : mIconProducer.mIcon);
132+
setIcon(mHasPauseEmblem ? emblemizedIcon() : getIcon());
122133
}
123134

124135
QIcon TrayIcon::emblemizedIcon()
@@ -131,7 +142,7 @@ QIcon TrayIcon::emblemizedIcon()
131142
);
132143

133144
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);
135146
const qreal pixelRatio = icnPix.devicePixelRatio();
136147
const QSize icnPixSize((QSizeF(icnSize) * pixelRatio).toSize());
137148

@@ -162,24 +173,10 @@ QIcon TrayIcon::emblemizedIcon()
162173
return QIcon(pix);
163174
}
164175

165-
void TrayIcon::updateTooltip()
176+
void TrayIcon::onPauseTimeout()
166177
{
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);
183180
}
184181

185182
void TrayIcon::onConfigureTriggered()
@@ -189,8 +186,18 @@ void TrayIcon::onConfigureTriggered()
189186

190187
void TrayIcon::onPauseTriggered(QAction *action)
191188
{
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+
}
194201
}
195202

196203
void TrayIcon::onAboutTriggered()
@@ -236,7 +243,7 @@ void TrayIcon::onActivated(QSystemTrayIcon::ActivationReason reason)
236243
void TrayIcon::setPause(PAUSE duration)
237244
{
238245
// add/remove the pause emblem and correct the checked action if needed
239-
QAction *checked = mPauseActions->checkedAction();
246+
QAction *checked = msPauseActions->checkedAction();
240247
if (duration == PAUSE::None)
241248
{
242249
PowerManagementSettings().setIdlenessWatcherPaused(false);
@@ -252,7 +259,7 @@ void TrayIcon::setPause(PAUSE duration)
252259
iconChanged(); // adds the pause emblem
253260
if (checked == nullptr || checked->data().toInt() != duration)
254261
{
255-
const auto actions = mPauseActions->actions();
262+
const auto actions = msPauseActions->actions();
256263
for (const auto &a : actions)
257264
{
258265
if (a->data().toInt() == duration)

0 commit comments

Comments
 (0)