From 9ac8167ea2303e073e80d309c6e89ad7dceeffe9 Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Thu, 21 Apr 2022 06:28:36 +0300 Subject: [PATCH] kpowercontrol: semi-working battery status Signed-off-by: Ivailo Monev --- kpowercontrol/CMakeLists.txt | 1 + kpowercontrol/kpowercontrol.cpp | 186 ++++++++++++++++++++++++++------ kpowercontrol/kpowercontrol.h | 7 ++ kpowercontrol/main.cpp | 7 -- 4 files changed, 164 insertions(+), 37 deletions(-) diff --git a/kpowercontrol/CMakeLists.txt b/kpowercontrol/CMakeLists.txt index b9f6965f..5841adaa 100644 --- a/kpowercontrol/CMakeLists.txt +++ b/kpowercontrol/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(kpowercontrol ${kpowercontrol_SRCS}) target_link_libraries(kpowercontrol ${KDE4_KDEUI_LIBS} ${KDE4_KPOWERMANAGER_LIBS} + ${KDE4_SOLID_LIBS} ) install(TARGETS kpowercontrol ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/kpowercontrol/kpowercontrol.cpp b/kpowercontrol/kpowercontrol.cpp index b06771f1..fc44aae7 100644 --- a/kpowercontrol/kpowercontrol.cpp +++ b/kpowercontrol/kpowercontrol.cpp @@ -18,8 +18,8 @@ #include "kpowercontrol.h" -#include -#include +#include +#include #include #include #include @@ -28,47 +28,117 @@ #include #include +static inline QString normalizeUDI(const QString &solidudi) +{ + const QByteArray udihex = solidudi.toLatin1().toHex(); + return QString::fromLatin1(udihex.constData(), udihex.size()); +} + +static inline QString deviceProduct(const Solid::Device &soliddevice) +{ + QString deviceproduct = soliddevice.product(); + if (deviceproduct.isEmpty()) { + deviceproduct = soliddevice.udi(); + const int lastslashindex = deviceproduct.lastIndexOf(QLatin1Char('/')); + deviceproduct = deviceproduct.mid(lastslashindex + 1); + } + return deviceproduct; +} + +static inline QString batteryState(const Solid::Battery::ChargeState solidstate) +{ + switch (solidstate) { + case Solid::Battery::NoCharge: { + return i18n("Unknown"); + } + case Solid::Battery::Charging: { + return i18n("Charging"); + } + case Solid::Battery::Discharging: { + return i18n("Discharging"); + } + } + Q_ASSERT(false); + return i18n("Unknown"); +} + KPowerControl::KPowerControl(QObject* parent) : KStatusNotifierItem(parent), m_menu(nullptr), m_helpmenu(nullptr) { setTitle(i18n("Power management")); - setCategory(KStatusNotifierItem::SystemServices); + setCategory(KStatusNotifierItem::Hardware); setIconByName("preferences-system-power-management"); setStatus(KStatusNotifierItem::Passive); m_menu = new KMenu(associatedWidget()); setContextMenu(m_menu); - QDBusConnectionInterface* sessionbusiface = QDBusConnection::sessionBus().interface(); - if (sessionbusiface->isServiceRegistered("org.freedesktop.PowerManagement")) { - if (!KPowerManager::isSupported()) { - setOverlayIconByName("dialog-error"); - showMessage(i18n("Power management"), i18n("Power manager is not supported on this system"), "dialog-error"); - } else if (!KPowerManager::isEnabled()) { - setOverlayIconByName("dialog-error"); - showMessage(i18n("Power management"), i18n("Power manager is disabled"), "dialog-information"); - } else { - connect( - &m_powermanager, SIGNAL(profileChanged(QString)), - this, SLOT(slotProfileChanged(QString)) - ); - - foreach (const QString &profile, m_powermanager.profiles()) { - KAction* profileaction = actionCollection()->addAction(QString::fromLatin1("profile_%1").arg(profile)); - profileaction->setText(profile); - profileaction->setCheckable(true); - profileaction->setChecked(profile == m_powermanager.profile()); - connect(profileaction, SIGNAL(triggered()), this, SLOT(slotChangeProfile())); - m_menu->addAction(profileaction); - } - - m_menu->addSeparator(); - } - } else { + if (!KPowerManager::isSupported()) { setOverlayIconByName("dialog-error"); - showMessage(i18n("Power management"), i18n("Power manager is not active"), "dialog-error"); + showMessage(i18n("Power management"), i18n("Power management is not supported on this system"), "dialog-error"); + } else if (!KPowerManager::isEnabled()) { + setOverlayIconByName("dialog-error"); + showMessage(i18n("Power management"), i18n("Power manager is disabled"), "dialog-information"); + } else { + connect( + &m_powermanager, SIGNAL(profileChanged(QString)), + this, SLOT(slotProfileChanged(QString)) + ); + + foreach (const QString &profile, m_powermanager.profiles()) { + KAction* profileaction = actionCollection()->addAction(QString::fromLatin1("profile_%1").arg(profile)); + profileaction->setText(profile); + profileaction->setCheckable(true); + profileaction->setChecked(profile == m_powermanager.profile()); + connect(profileaction, SIGNAL(triggered()), this, SLOT(slotChangeProfile())); + m_menu->addAction(profileaction); + } + + m_menu->addSeparator(); + } + + const QList solidbatteries = Solid::Device::listFromType(Solid::DeviceInterface::Battery); + // qDebug() << Q_FUNC_INFO << solidbatteries.size(); + if (!solidbatteries.isEmpty()) { + bool isfirst = true; + QString batteryudi; + foreach (const Solid::Device &soliddevice, solidbatteries) { + const Solid::Battery* solidbattery = soliddevice.as(); + // qDebug() << Q_FUNC_INFO << soliddevice.udi() << solidbattery->chargePercent(); + connect( + solidbattery, SIGNAL(chargeStateChanged(int,QString)), + this, SLOT(slotChargeStateChanged(int,QString)) + ); + connect( + solidbattery, SIGNAL(powerSupplyStateChanged(bool,QString)), + this, SLOT(slotPowerSupplyStateChanged(bool,QString)) + ); + connect( + solidbattery, SIGNAL(plugStateChanged(bool,QString)), + this, SLOT(slotPlugStateChanged(bool,QString)) + ); + + + KAction* batteryaction = actionCollection()->addAction( + QString::fromLatin1("battery_%1").arg(normalizeUDI(soliddevice.udi())) + ); + batteryaction->setText(deviceProduct(soliddevice)); + batteryaction->setCheckable(true); + batteryaction->setChecked(isfirst); + batteryaction->setData(soliddevice.udi()); + connect(batteryaction, SIGNAL(triggered()), this, SLOT(slotChangeBattery())); + m_menu->addAction(batteryaction); + + if (batteryudi.isEmpty() || solidbattery->isPowerSupply()) { + batteryudi = soliddevice.udi(); + } + isfirst = false; + } + setBattery(batteryudi); + + m_menu->addSeparator(); } m_helpmenu = new KHelpMenu(associatedWidget(), KGlobal::mainComponent().aboutData()); @@ -92,6 +162,12 @@ void KPowerControl::slotChangeProfile() } } +void KPowerControl::slotChangeBattery() +{ + KAction* batteryaction = qobject_cast(sender()); + setBattery(batteryaction->data().toString()); +} + void KPowerControl::slotProfileChanged(const QString &profile) { const QString profileobjectname = QString::fromLatin1("profile_%1").arg(profile); @@ -102,3 +178,53 @@ void KPowerControl::slotProfileChanged(const QString &profile) } } } + +void KPowerControl::setBattery(const QString &solidudi) +{ + // qDebug() << Q_FUNC_INFO << solidudi; + foreach (QAction* qaction, actionCollection()->actions()) { + const QString qactionobjectname = qaction->objectName(); + const QString qactiondata = qaction->data().toString(); + if (qactionobjectname.startsWith(QLatin1String("battery_"))) { + qaction->setChecked(qactiondata == solidudi); + } + } + + Solid::Device soliddevice(solidudi); + const Solid::Battery* solidbattery = soliddevice.as(); + if (solidbattery->isPowerSupply()) { + setIconByName(soliddevice.icon()); + setStatus(KStatusNotifierItem::Active); + } else { + setIconByName("preferences-system-power-management"); + setStatus(KStatusNotifierItem::Passive); + } + // qDebug() << Q_FUNC_INFO << soliddevice.icon(); + + QString batterytooltip = i18n( + "Product: %1
Is power supply: %2
Charge state: %3
Charge percent:%4", + deviceProduct(soliddevice), + solidbattery->isPowerSupply() ? i18n("Yes") : i18n("No"), + batteryState(solidbattery->chargeState()), + solidbattery->chargePercent() + ); + setToolTip(KIcon(soliddevice.icon()), i18n("Battery details"), batterytooltip); +} + +void KPowerControl::slotChargeStateChanged(const int newstate, const QString &solidudi) +{ + qDebug() << Q_FUNC_INFO << newstate << solidudi; + // TODO: +} + +void KPowerControl::slotPowerSupplyStateChanged(const bool newstate, const QString &solidudi) +{ + qDebug() << Q_FUNC_INFO << newstate << solidudi; + // TODO: +} + +void KPowerControl::slotPlugStateChanged(const bool newstate, const QString &solidudi) +{ + qDebug() << Q_FUNC_INFO << newstate << solidudi; + // TODO: +} \ No newline at end of file diff --git a/kpowercontrol/kpowercontrol.h b/kpowercontrol/kpowercontrol.h index 3779baf6..2087efea 100644 --- a/kpowercontrol/kpowercontrol.h +++ b/kpowercontrol/kpowercontrol.h @@ -33,9 +33,16 @@ public: private Q_SLOTS: void slotChangeProfile(); + void slotChangeBattery(); void slotProfileChanged(const QString &profile); + void slotChargeStateChanged(const int newstate, const QString &solidudi); + void slotPowerSupplyStateChanged(const bool newstate, const QString &solidudi); + void slotPlugStateChanged(const bool newstate, const QString &solidudi); + private: + void setBattery(const QString &solidudi); + KMenu* m_menu; KHelpMenu* m_helpmenu; KPowerManager m_powermanager; diff --git a/kpowercontrol/main.cpp b/kpowercontrol/main.cpp index 38fa9b28..80b2e078 100644 --- a/kpowercontrol/main.cpp +++ b/kpowercontrol/main.cpp @@ -16,7 +16,6 @@ Boston, MA 02110-1301, USA. */ -#include #include #include #include @@ -53,12 +52,6 @@ int main(int argc, char** argv) return 0; } - QDBusConnectionInterface* sessionbusiface = QDBusConnection::sessionBus().interface(); - if (!sessionbusiface->isServiceRegistered("org.freedesktop.PowerManagement")) { - kDebug() << "Activating org.freedesktop.PowerManagement"; - sessionbusiface->startService("org.freedesktop.PowerManagement"); - } - KPowerControl kpowercontrol(&kpowercontrolapp); return kpowercontrolapp.exec();