diff --git a/containmentactions/contextmenu/menu.cpp b/containmentactions/contextmenu/menu.cpp index de7c8fd01..b2bd484e6 100644 --- a/containmentactions/contextmenu/menu.cpp +++ b/containmentactions/contextmenu/menu.cpp @@ -1,315 +1,315 @@ /* * Copyright 2009 by Chani Armitage * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "menu.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kworkspace.h" #include "krunner_interface.h" #include "screensaver_interface.h" #ifdef Q_OS_WIN #define _WIN32_WINNT 0x0500 // require NT 5.0 (win 2k pro) #include #endif // Q_OS_WIN ContextMenu::ContextMenu(QObject *parent, const QVariantList &args) : Plasma::ContainmentActions(parent, args), m_runCommandAction(nullptr), m_lockScreenAction(nullptr), m_logoutAction(nullptr), m_separator1(nullptr), m_separator2(nullptr), m_separator3(nullptr), m_buttons(nullptr) { } ContextMenu::~ContextMenu() { } void ContextMenu::restore(const KConfigGroup &config) { Plasma::Containment *c = containment(); Q_ASSERT(c); m_actions.clear(); m_actionOrder.clear(); QHash actions; QSet disabled; if (c->containmentType() == Plasma::Types::PanelContainment || c->containmentType() == Plasma::Types::CustomPanelContainment) { m_actionOrder << QStringLiteral("add widgets") << QStringLiteral("_add panel") << QStringLiteral("lock widgets") << QStringLiteral("_context") << QStringLiteral("configure") << QStringLiteral("remove"); } else { actions.insert(QStringLiteral("configure shortcuts"), false); m_actionOrder << QStringLiteral("_context") << QStringLiteral("_run_command") << QStringLiteral("add widgets") << QStringLiteral("_add panel") << QStringLiteral("manage activities") << QStringLiteral("remove") << QStringLiteral("lock widgets") << QStringLiteral("_sep1") < it(actions); while (it.hasNext()) { it.next(); m_actions.insert(it.key(), config.readEntry(it.key(), it.value())); } // everything below should only happen once, so check for it if (!m_runCommandAction) { m_runCommandAction = new QAction(i18nc("plasma_containmentactions_contextmenu", "Run Command..."), this); m_runCommandAction->setIcon(QIcon::fromTheme(QStringLiteral("system-run"))); m_runCommandAction->setShortcut(KGlobalAccel::self()->globalShortcut(QStringLiteral("krunner"), QStringLiteral("run command")).value(0)); connect(m_runCommandAction, &QAction::triggered, this, &ContextMenu::runCommand); m_lockScreenAction = new QAction(i18nc("plasma_containmentactions_contextmenu", "Lock Screen"), this); m_lockScreenAction->setIcon(QIcon::fromTheme(QStringLiteral("system-lock-screen"))); m_lockScreenAction->setShortcut(KGlobalAccel::self()->globalShortcut(QStringLiteral("ksmserver"), QStringLiteral("Lock Session")).value(0)); connect(m_lockScreenAction, &QAction::triggered, this, &ContextMenu::lockScreen); m_logoutAction = new QAction(i18nc("plasma_containmentactions_contextmenu", "Leave..."), this); m_logoutAction->setIcon(QIcon::fromTheme(QStringLiteral("system-log-out"))); m_logoutAction->setShortcut(KGlobalAccel::self()->globalShortcut(QStringLiteral("ksmserver"), QStringLiteral("Log Out")).value(0)); connect(m_logoutAction, &QAction::triggered, this, &ContextMenu::startLogout); m_separator1 = new QAction(this); m_separator1->setSeparator(true); m_separator2 = new QAction(this); m_separator2->setSeparator(true); m_separator3 = new QAction(this); m_separator3->setSeparator(true); } } QList ContextMenu::contextualActions() { Plasma::Containment *c = containment(); Q_ASSERT(c); QList actions; foreach (const QString &name, m_actionOrder) { if (!m_actions.value(name)) { continue; } if (name == QLatin1String("_context")) { actions << c->contextualActions(); } if (name == QLatin1String("_wallpaper")) { if (!c->wallpaper().isEmpty()) { QObject *wallpaperGraphicsObject = c->property("wallpaperGraphicsObject").value(); if (wallpaperGraphicsObject) { actions << wallpaperGraphicsObject->property("contextualActions").value >(); } } } else if (QAction *a = action(name)) { // Bug 364292: show "Remove this Panel" option only when panelcontroller is opened if (name != QLatin1String("remove") || c->isUserConfiguring() || (c->containmentType() != Plasma::Types::PanelContainment && c->containmentType() != Plasma::Types::CustomPanelContainment)) { actions << a; } } } return actions; } QAction *ContextMenu::action(const QString &name) { Plasma::Containment *c = containment(); Q_ASSERT(c); if (name == QLatin1String("_sep1")) { return m_separator1; } else if (name == QLatin1String("_sep2")) { return m_separator2; } else if (name == QLatin1String("_sep3")) { return m_separator3; } else if (name == QLatin1String("_add panel")) { if (c->corona() && c->corona()->immutability() == Plasma::Types::Mutable) { return c->corona()->actions()->action(QStringLiteral("add panel")); } } else if (name == QLatin1String("_run_command")) { - if (KAuthorized::authorizeAction(QStringLiteral("run_command"))) { + if (KAuthorized::authorizeAction(QStringLiteral("run_command")) && KAuthorized::authorize(QStringLiteral("run_command"))) { return m_runCommandAction; } } else if (name == QLatin1String("_lock_screen")) { if (KAuthorized::authorizeAction(QStringLiteral("lock_screen"))) { return m_lockScreenAction; } } else if (name == QLatin1String("_logout")) { - if (KAuthorized::authorizeAction(QStringLiteral("logout"))) { + if (KAuthorized::authorize(QStringLiteral("logout"))) { return m_logoutAction; } } else if (name == QLatin1String("lock widgets")) { if (c->corona()) { return c->corona()->actions()->action(QStringLiteral("lock widgets")); } } else if (name == QLatin1String("manage activities")) { if (c->corona()) { return c->corona()->actions()->action(QStringLiteral("manage activities")); } } else { //FIXME: remove action: make removal of current activity possible return c->actions()->action(name); } return nullptr; } void ContextMenu::runCommand() { if (!KAuthorized::authorizeAction(QStringLiteral("run_command"))) { return; } QString interface(QStringLiteral("org.kde.krunner")); org::kde::krunner::App krunner(interface, QStringLiteral("/App"), QDBusConnection::sessionBus()); krunner.display(); } void ContextMenu::lockScreen() { if (!KAuthorized::authorizeAction(QStringLiteral("lock_screen"))) { return; } #ifndef Q_OS_WIN QString interface(QStringLiteral("org.freedesktop.ScreenSaver")); org::freedesktop::ScreenSaver screensaver(interface, QStringLiteral("/ScreenSaver"), QDBusConnection::sessionBus()); if (screensaver.isValid()) { screensaver.Lock(); } #else LockWorkStation(); #endif // !Q_OS_WIN } void ContextMenu::startLogout() { // this short delay is due to two issues: // a) KWorkSpace's DBus alls are all syncronous // b) the destrution of the menu that this action is in is delayed // // (a) leads to the menu hanging out where everyone can see it because // the even loop doesn't get returned to allowing it to close. // // (b) leads to a 0ms timer not working since a 0ms timer just appends to // the event queue, and then the menu closing event gets appended to that. // // ergo a timer with small timeout QTimer::singleShot(10, this, &ContextMenu::logout); } void ContextMenu::logout() { if (!KAuthorized::authorizeAction(QStringLiteral("logout"))) { return; } KWorkSpace::requestShutDown(); } QWidget* ContextMenu::createConfigurationInterface(QWidget* parent) { QWidget *widget = new QWidget(parent); QVBoxLayout *lay = new QVBoxLayout(); widget->setLayout(lay); widget->setWindowTitle(i18nc("plasma_containmentactions_contextmenu", "Configure Contextual Menu Plugin")); m_buttons = new QButtonGroup(widget); m_buttons->setExclusive(false); foreach (const QString &name, m_actionOrder) { QCheckBox *item = nullptr; if (name == QLatin1String("_context")) { item = new QCheckBox(widget); //FIXME better text item->setText(i18nc("plasma_containmentactions_contextmenu", "[Other Actions]")); } else if (name == QLatin1String("_wallpaper")) { item = new QCheckBox(widget); item->setText(i18nc("plasma_containmentactions_contextmenu", "Wallpaper Actions")); item->setIcon(QIcon::fromTheme(QStringLiteral("user-desktop"))); } else if (name == QLatin1String("_sep1") || name ==QLatin1String("_sep2") || name == QLatin1String("_sep3")) { item = new QCheckBox(widget); item->setText(i18nc("plasma_containmentactions_contextmenu", "[Separator]")); } else { QAction *a = action(name); if (a) { item = new QCheckBox(widget); item->setText(a->text()); item->setIcon(a->icon()); } } if (item) { item->setChecked(m_actions.value(name)); item->setProperty("actionName", name); lay->addWidget(item); m_buttons->addButton(item); } } return widget; } void ContextMenu::configurationAccepted() { QList buttons = m_buttons->buttons(); QListIterator it(buttons); while (it.hasNext()) { QAbstractButton *b = it.next(); if (b) { m_actions.insert(b->property("actionName").toString(), b->isChecked()); } } } void ContextMenu::save(KConfigGroup &config) { QHashIterator it(m_actions); while (it.hasNext()) { it.next(); config.writeEntry(it.key(), it.value()); } } K_EXPORT_PLASMA_CONTAINMENTACTIONS_WITH_JSON(contextmenu, ContextMenu, "plasma-containmentactions-contextmenu.json") #include "menu.moc" diff --git a/dataengines/powermanagement/powermanagementengine.cpp b/dataengines/powermanagement/powermanagementengine.cpp index 30f8cd2ce..e6db1dfad 100644 --- a/dataengines/powermanagement/powermanagementengine.cpp +++ b/dataengines/powermanagement/powermanagementengine.cpp @@ -1,678 +1,678 @@ /* * Copyright 2007 Aaron Seigo * Copyright 2007-2008 Sebastian Kuegler * CopyRight 2007 Maor Vanmak * Copyright 2008 Dario Freddi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License version 2 as * published by the Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "powermanagementengine.h" //solid specific includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "powermanagementservice.h" static const char SOLID_POWERMANAGEMENT_SERVICE[] = "org.kde.Solid.PowerManagement"; Q_DECLARE_METATYPE(QList) Q_DECLARE_METATYPE(InhibitionInfo) PowermanagementEngine::PowermanagementEngine(QObject* parent, const QVariantList& args) : Plasma::DataEngine(parent, args) , m_sources(basicSourceNames()) { Q_UNUSED(args) qDBusRegisterMetaType>(); qDBusRegisterMetaType(); init(); } PowermanagementEngine::~PowermanagementEngine() {} void PowermanagementEngine::init() { connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceAdded, this, &PowermanagementEngine::deviceAdded); connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceRemoved, this, &PowermanagementEngine::deviceRemoved); if (QDBusConnection::sessionBus().interface()->isServiceRegistered(SOLID_POWERMANAGEMENT_SERVICE)) { if (!QDBusConnection::sessionBus().connect(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/Actions/BrightnessControl"), QStringLiteral("org.kde.Solid.PowerManagement.Actions.BrightnessControl"), QStringLiteral("brightnessChanged"), this, SLOT(screenBrightnessChanged(int)))) { qDebug() << "error connecting to Brightness changes via dbus"; } if (!QDBusConnection::sessionBus().connect(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/Actions/BrightnessControl"), QStringLiteral("org.kde.Solid.PowerManagement.Actions.BrightnessControl"), QStringLiteral("brightnessMaxChanged"), this, SLOT(maximumScreenBrightnessChanged(int)))) { qDebug() << "error connecting to max brightness changes via dbus"; } if (!QDBusConnection::sessionBus().connect(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/Actions/KeyboardBrightnessControl"), QStringLiteral("org.kde.Solid.PowerManagement.Actions.KeyboardBrightnessControl"), QStringLiteral("keyboardBrightnessChanged"), this, SLOT(keyboardBrightnessChanged(int)))) { qDebug() << "error connecting to Keyboard Brightness changes via dbus"; } if (!QDBusConnection::sessionBus().connect(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/Actions/KeyboardBrightnessControl"), QStringLiteral("org.kde.Solid.PowerManagement.Actions.KeyboardBrightnessControl"), QStringLiteral("keyboardBrightnessMaxChanged"), this, SLOT(maximumKeyboardBrightnessChanged(int)))) { qDebug() << "error connecting to max keyboard Brightness changes via dbus"; } if (!QDBusConnection::sessionBus().connect(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/Actions/HandleButtonEvents"), QStringLiteral("org.kde.Solid.PowerManagement.Actions.HandleButtonEvents"), QStringLiteral("triggersLidActionChanged"), this, SLOT(triggersLidActionChanged(bool)))) { qDebug() << "error connecting to lid action trigger changes via dbus"; } if (!QDBusConnection::sessionBus().connect(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/PolicyAgent"), QStringLiteral("org.kde.Solid.PowerManagement.PolicyAgent"), QStringLiteral("InhibitionsChanged"), this, SLOT(inhibitionsChanged(QList,QStringList)))) { qDebug() << "error connecting to inhibition changes via dbus"; } if (!QDBusConnection::sessionBus().connect(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement"), SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("batteryRemainingTimeChanged"), this, SLOT(batteryRemainingTimeChanged(qulonglong)))) { qDebug() << "error connecting to remaining time changes"; } } } QStringList PowermanagementEngine::basicSourceNames() const { QStringList sources; sources << QStringLiteral("Battery") << QStringLiteral("AC Adapter") << QStringLiteral("Sleep States") << QStringLiteral("PowerDevil") << QStringLiteral("Inhibitions"); return sources; } QStringList PowermanagementEngine::sources() const { return m_sources; } bool PowermanagementEngine::sourceRequestEvent(const QString &name) { if (name == QLatin1String("Battery")) { const QList listBattery = Solid::Device::listFromType(Solid::DeviceInterface::Battery); m_batterySources.clear(); if (listBattery.isEmpty()) { setData(QStringLiteral("Battery"), QStringLiteral("Has Battery"), false); setData(QStringLiteral("Battery"), QStringLiteral("Has Cumulative"), false); return true; } uint index = 0; QStringList batterySources; foreach (const Solid::Device &deviceBattery, listBattery) { const Solid::Battery* battery = deviceBattery.as(); const QString source = QStringLiteral("Battery%1").arg(index++); batterySources << source; m_batterySources[deviceBattery.udi()] = source; connect(battery, &Solid::Battery::chargeStateChanged, this, &PowermanagementEngine::updateBatteryChargeState); connect(battery, &Solid::Battery::chargePercentChanged, this, &PowermanagementEngine::updateBatteryChargePercent); connect(battery, &Solid::Battery::energyChanged, this, &PowermanagementEngine::updateBatteryEnergy); connect(battery, &Solid::Battery::presentStateChanged, this, &PowermanagementEngine::updateBatteryPresentState); // Set initial values updateBatteryChargeState(battery->chargeState(), deviceBattery.udi()); updateBatteryChargePercent(battery->chargePercent(), deviceBattery.udi()); updateBatteryEnergy(battery->energy(), deviceBattery.udi()); updateBatteryPresentState(battery->isPresent(), deviceBattery.udi()); updateBatteryPowerSupplyState(battery->isPowerSupply(), deviceBattery.udi()); setData(source, QStringLiteral("Vendor"), deviceBattery.vendor()); setData(source, QStringLiteral("Product"), deviceBattery.product()); setData(source, QStringLiteral("Capacity"), battery->capacity()); setData(source, QStringLiteral("Type"), batteryType(battery)); } updateBatteryNames(); updateOverallBattery(); setData(QStringLiteral("Battery"), QStringLiteral("Has Battery"), !batterySources.isEmpty()); if (!batterySources.isEmpty()) { setData(QStringLiteral("Battery"), QStringLiteral("Sources"), batterySources); QDBusMessage msg = QDBusMessage::createMethodCall(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement"), SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("batteryRemainingTime")); QDBusPendingReply reply = QDBusConnection::sessionBus().asyncCall(msg); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if (!reply.isError()) { batteryRemainingTimeChanged(reply.value()); } watcher->deleteLater(); }); } m_sources = basicSourceNames() + batterySources; } else if (name == QLatin1String("AC Adapter")) { connect(Solid::PowerManagement::notifier(), &Solid::PowerManagement::Notifier::appShouldConserveResourcesChanged, this, &PowermanagementEngine::updateAcPlugState); updateAcPlugState(Solid::PowerManagement::appShouldConserveResources()); } else if (name == QLatin1String("Sleep States")) { const QSet sleepstates = Solid::PowerManagement::supportedSleepStates(); setData(QStringLiteral("Sleep States"), QStringLiteral("Standby"), sleepstates.contains(Solid::PowerManagement::StandbyState)); setData(QStringLiteral("Sleep States"), QStringLiteral("Suspend"), sleepstates.contains(Solid::PowerManagement::SuspendState)); setData(QStringLiteral("Sleep States"), QStringLiteral("Hibernate"), sleepstates.contains(Solid::PowerManagement::HibernateState)); setData(QStringLiteral("Sleep States"), QStringLiteral("HybridSuspend"), sleepstates.contains(Solid::PowerManagement::HybridSuspendState)); - setData(QStringLiteral("Sleep States"), QStringLiteral("LockScreen"), KAuthorized::authorize(QStringLiteral("lock_screen"))); + setData(QStringLiteral("Sleep States"), QStringLiteral("LockScreen"), KAuthorized::authorizeAction(QStringLiteral("lock_screen"))); setData(QStringLiteral("Sleep States"), QStringLiteral("Logout"), KAuthorized::authorize(QStringLiteral("logout"))); } else if (name == QLatin1String("PowerDevil")) { QDBusMessage screenMsg = QDBusMessage::createMethodCall(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/Actions/BrightnessControl"), QStringLiteral("org.kde.Solid.PowerManagement.Actions.BrightnessControl"), QStringLiteral("brightness")); QDBusPendingReply screenReply = QDBusConnection::sessionBus().asyncCall(screenMsg); QDBusPendingCallWatcher *screenWatcher = new QDBusPendingCallWatcher(screenReply, this); QObject::connect(screenWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if (!reply.isError()) { screenBrightnessChanged(reply.value()); } watcher->deleteLater(); }); QDBusMessage maxScreenMsg = QDBusMessage::createMethodCall(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/Actions/BrightnessControl"), QStringLiteral("org.kde.Solid.PowerManagement.Actions.BrightnessControl"), QStringLiteral("brightnessMax")); QDBusPendingReply maxScreenReply = QDBusConnection::sessionBus().asyncCall(maxScreenMsg); QDBusPendingCallWatcher *maxScreenWatcher = new QDBusPendingCallWatcher(maxScreenReply, this); QObject::connect(maxScreenWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if (!reply.isError()) { maximumScreenBrightnessChanged(reply.value()); } watcher->deleteLater(); }); QDBusMessage keyboardMsg = QDBusMessage::createMethodCall(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/Actions/KeyboardBrightnessControl"), QStringLiteral("org.kde.Solid.PowerManagement.Actions.KeyboardBrightnessControl"), QStringLiteral("keyboardBrightness")); QDBusPendingReply keyboardReply = QDBusConnection::sessionBus().asyncCall(keyboardMsg); QDBusPendingCallWatcher *keyboardWatcher = new QDBusPendingCallWatcher(keyboardReply, this); QObject::connect(keyboardWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if (!reply.isError()) { keyboardBrightnessChanged(reply.value()); } watcher->deleteLater(); }); QDBusMessage maxKeyboardMsg = QDBusMessage::createMethodCall(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/Actions/KeyboardBrightnessControl"), QStringLiteral("org.kde.Solid.PowerManagement.Actions.KeyboardBrightnessControl"), QStringLiteral("keyboardBrightnessMax")); QDBusPendingReply maxKeyboardReply = QDBusConnection::sessionBus().asyncCall(maxKeyboardMsg); QDBusPendingCallWatcher *maxKeyboardWatcher = new QDBusPendingCallWatcher(maxKeyboardReply, this); QObject::connect(maxKeyboardWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if (!reply.isError()) { maximumKeyboardBrightnessChanged(reply.value()); } watcher->deleteLater(); }); QDBusMessage lidIsPresentMsg = QDBusMessage::createMethodCall(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement"), SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("isLidPresent")); QDBusPendingReply lidIsPresentReply = QDBusConnection::sessionBus().asyncCall(lidIsPresentMsg); QDBusPendingCallWatcher *lidIsPresentWatcher = new QDBusPendingCallWatcher(lidIsPresentReply, this); QObject::connect(lidIsPresentWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if (!reply.isError()) { setData(QStringLiteral("PowerDevil"), QStringLiteral("Is Lid Present"), reply.value()); } watcher->deleteLater(); }); QDBusMessage triggersLidActionMsg = QDBusMessage::createMethodCall(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/Actions/HandleButtonEvents"), QStringLiteral("org.kde.Solid.PowerManagement.Actions.HandleButtonEvents"), QStringLiteral("triggersLidAction")); QDBusPendingReply triggersLidActionReply = QDBusConnection::sessionBus().asyncCall(triggersLidActionMsg); QDBusPendingCallWatcher *triggersLidActionWatcher = new QDBusPendingCallWatcher(triggersLidActionReply, this); QObject::connect(triggersLidActionWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if (!reply.isError()) { triggersLidActionChanged(reply.value()); } watcher->deleteLater(); }); } else if (name == QLatin1Literal("Inhibitions")) { QDBusMessage inhibitionsMsg = QDBusMessage::createMethodCall(SOLID_POWERMANAGEMENT_SERVICE, QStringLiteral("/org/kde/Solid/PowerManagement/PolicyAgent"), QStringLiteral("org.kde.Solid.PowerManagement.PolicyAgent"), QStringLiteral("ListInhibitions")); QDBusPendingReply> inhibitionsReply = QDBusConnection::sessionBus().asyncCall(inhibitionsMsg); QDBusPendingCallWatcher *inhibitionsWatcher = new QDBusPendingCallWatcher(inhibitionsReply, this); QObject::connect(inhibitionsWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { QDBusPendingReply> reply = *watcher; watcher->deleteLater(); if (!reply.isError()) { removeAllData(QStringLiteral("Inhibitions")); inhibitionsChanged(reply.value(), QStringList()); } }); //any info concerning lock screen/screensaver goes here } else if (name == QLatin1String("UserActivity")) { setData(QStringLiteral("UserActivity"), QStringLiteral("IdleTime"), KIdleTime::instance()->idleTime()); } else { qDebug() << "Data for '" << name << "' not found"; return false; } return true; } QString PowermanagementEngine::batteryType(const Solid::Battery* battery) const { switch(battery->type()) { case Solid::Battery::PrimaryBattery: return QStringLiteral("Battery"); break; case Solid::Battery::UpsBattery: return QStringLiteral("Ups"); break; case Solid::Battery::MonitorBattery: return QStringLiteral("Monitor"); break; case Solid::Battery::MouseBattery: return QStringLiteral("Mouse"); break; case Solid::Battery::KeyboardBattery: return QStringLiteral("Keyboard"); break; case Solid::Battery::PdaBattery: return QStringLiteral("Pda"); break; case Solid::Battery::PhoneBattery: return QStringLiteral("Phone"); break; case Solid::Battery::GamingInputBattery: return QStringLiteral("GamingInput"); break; default: return QStringLiteral("Unknown"); } return QStringLiteral("Unknown"); } bool PowermanagementEngine::updateSourceEvent(const QString &source) { if (source == QLatin1String("UserActivity")) { setData(QStringLiteral("UserActivity"), QStringLiteral("IdleTime"), KIdleTime::instance()->idleTime()); return true; } return Plasma::DataEngine::updateSourceEvent(source); } Plasma::Service* PowermanagementEngine::serviceForSource(const QString &source) { if (source == QLatin1String("PowerDevil")) { return new PowerManagementService(this); } return nullptr; } QString PowermanagementEngine::batteryStateToString(int newState) const { QString state(QStringLiteral("Unknown")); if (newState == Solid::Battery::NoCharge) { state = QLatin1String("NoCharge"); } else if (newState == Solid::Battery::Charging) { state = QLatin1String("Charging"); } else if (newState == Solid::Battery::Discharging) { state = QLatin1String("Discharging"); } else if (newState == Solid::Battery::FullyCharged) { state = QLatin1String("FullyCharged"); } return state; } void PowermanagementEngine::updateBatteryChargeState(int newState, const QString& udi) { const QString source = m_batterySources[udi]; setData(source, QStringLiteral("State"), batteryStateToString(newState)); updateOverallBattery(); } void PowermanagementEngine::updateBatteryPresentState(bool newState, const QString& udi) { const QString source = m_batterySources[udi]; setData(source, QStringLiteral("Plugged in"), newState); // FIXME This needs to be renamed and Battery Monitor adjusted } void PowermanagementEngine::updateBatteryChargePercent(int newValue, const QString& udi) { const QString source = m_batterySources[udi]; setData(source, QStringLiteral("Percent"), newValue); updateOverallBattery(); } void PowermanagementEngine::updateBatteryEnergy(double newValue, const QString &udi) { const QString source = m_batterySources[udi]; setData(source, QStringLiteral("Energy"), newValue); } void PowermanagementEngine::updateBatteryPowerSupplyState(bool newState, const QString& udi) { const QString source = m_batterySources[udi]; setData(source, QStringLiteral("Is Power Supply"), newState); } void PowermanagementEngine::updateBatteryNames() { uint unnamedBatteries = 0; foreach (QString source, m_batterySources) { DataContainer *batteryDataContainer = containerForSource(source); if (batteryDataContainer) { const QString batteryVendor = batteryDataContainer->data()[QStringLiteral("Vendor")].toString(); const QString batteryProduct = batteryDataContainer->data()[QStringLiteral("Product")].toString(); // Don't show battery name for primary power supply batteries. They usually have cryptic serial number names. const bool showBatteryName = batteryDataContainer->data()[QStringLiteral("Type")].toString() != QLatin1String("Battery") || !batteryDataContainer->data()[QStringLiteral("Is Power Supply")].toBool(); if (!batteryProduct.isEmpty() && batteryProduct != QLatin1String("Unknown Battery") && showBatteryName) { if (!batteryVendor.isEmpty()) { setData(source, QStringLiteral("Pretty Name"), QString(batteryVendor + ' ' + batteryProduct)); } else { setData(source, QStringLiteral("Pretty Name"), batteryProduct); } } else { ++unnamedBatteries; if (unnamedBatteries > 1) { setData(source, QStringLiteral("Pretty Name"), i18nc("Placeholder is the battery number", "Battery %1", unnamedBatteries)); } else { setData(source, QStringLiteral("Pretty Name"), i18n("Battery")); } } } } } void PowermanagementEngine::updateOverallBattery() { const QList listBattery = Solid::Device::listFromType(Solid::DeviceInterface::Battery); bool hasCumulative = false; double energy = 0; double totalEnergy = 0; bool allFullyCharged = true; bool charging = false; bool noCharge = false; double totalPercentage = 0; int count = 0; foreach (const Solid::Device &deviceBattery, listBattery) { const Solid::Battery* battery = deviceBattery.as(); if (battery && battery->isPowerSupply()) { hasCumulative = true; energy += battery->energy(); totalEnergy += battery->energyFull(); totalPercentage += battery->chargePercent(); allFullyCharged = allFullyCharged && (battery->chargeState() == Solid::Battery::FullyCharged); charging = charging || (battery->chargeState() == Solid::Battery::Charging); noCharge = noCharge || (battery->chargeState() == Solid::Battery::NoCharge); ++count; } } if (count == 1) { // Energy is sometimes way off causing us to show rubbish; this is a UPower issue // but anyway having just one battery and the tooltip showing strange readings // compared to the popup doesn't look polished. setData(QStringLiteral("Battery"), QStringLiteral("Percent"), totalPercentage); } else if (totalEnergy > 0) { setData(QStringLiteral("Battery"), QStringLiteral("Percent"), qRound(energy / totalEnergy * 100)); } else if (count > 0) { // UPS don't have energy, see Bug 348588 setData(QStringLiteral("Battery"), QStringLiteral("Percent"), qRound(totalPercentage / static_cast(count))); } else { setData(QStringLiteral("Battery"), QStringLiteral("Percent"), 0); } if (hasCumulative) { if (allFullyCharged) { setData(QStringLiteral("Battery"), QStringLiteral("State"), "FullyCharged"); } else if (charging) { setData(QStringLiteral("Battery"), QStringLiteral("State"), "Charging"); } else if (noCharge) { setData(QStringLiteral("Battery"), QStringLiteral("State"), "NoCharge"); } else { setData(QStringLiteral("Battery"), QStringLiteral("State"), "Discharging"); } } else { setData(QStringLiteral("Battery"), QStringLiteral("State"), "Unknown"); } setData(QStringLiteral("Battery"), QStringLiteral("Has Cumulative"), hasCumulative); } void PowermanagementEngine::updateAcPlugState(bool onBattery) { setData(QStringLiteral("AC Adapter"), QStringLiteral("Plugged in"), !onBattery); } void PowermanagementEngine::deviceRemoved(const QString& udi) { if (m_batterySources.contains(udi)) { Solid::Device device(udi); Solid::Battery* battery = device.as(); if (battery) battery->disconnect(); const QString source = m_batterySources[udi]; m_batterySources.remove(udi); removeSource(source); QStringList sourceNames(m_batterySources.values()); sourceNames.removeAll(source); setData(QStringLiteral("Battery"), QStringLiteral("Sources"), sourceNames); setData(QStringLiteral("Battery"), QStringLiteral("Has Battery"), !sourceNames.isEmpty()); updateOverallBattery(); } } void PowermanagementEngine::deviceAdded(const QString& udi) { Solid::Device device(udi); if (device.isValid()) { const Solid::Battery* battery = device.as(); if (battery) { int index = 0; QStringList sourceNames(m_batterySources.values()); while (sourceNames.contains(QStringLiteral("Battery%1").arg(index))) { index++; } const QString source = QStringLiteral("Battery%1").arg(index); sourceNames << source; m_batterySources[device.udi()] = source; connect(battery, &Solid::Battery::chargeStateChanged, this, &PowermanagementEngine::updateBatteryChargeState); connect(battery, &Solid::Battery::chargePercentChanged, this, &PowermanagementEngine::updateBatteryChargePercent); connect(battery, &Solid::Battery::energyChanged, this, &PowermanagementEngine::updateBatteryEnergy); connect(battery, &Solid::Battery::presentStateChanged, this, &PowermanagementEngine::updateBatteryPresentState); connect(battery, &Solid::Battery::powerSupplyStateChanged, this, &PowermanagementEngine::updateBatteryPowerSupplyState); // Set initial values updateBatteryChargeState(battery->chargeState(), device.udi()); updateBatteryChargePercent(battery->chargePercent(), device.udi()); updateBatteryEnergy(battery->energy(), device.udi()); updateBatteryPresentState(battery->isPresent(), device.udi()); updateBatteryPowerSupplyState(battery->isPowerSupply(), device.udi()); setData(source, QStringLiteral("Vendor"), device.vendor()); setData(source, QStringLiteral("Product"), device.product()); setData(source, QStringLiteral("Capacity"), battery->capacity()); setData(source, QStringLiteral("Type"), batteryType(battery)); setData(QStringLiteral("Battery"), QStringLiteral("Sources"), sourceNames); setData(QStringLiteral("Battery"), QStringLiteral("Has Battery"), !sourceNames.isEmpty()); updateBatteryNames(); updateOverallBattery(); } } } void PowermanagementEngine::batteryRemainingTimeChanged(qulonglong time) { //qDebug() << "Remaining time 2:" << time; setData(QStringLiteral("Battery"), QStringLiteral("Remaining msec"), time); } void PowermanagementEngine::screenBrightnessChanged(int brightness) { setData(QStringLiteral("PowerDevil"), QStringLiteral("Screen Brightness"), brightness); } void PowermanagementEngine::maximumScreenBrightnessChanged(int maximumBrightness) { setData(QStringLiteral("PowerDevil"), QStringLiteral("Maximum Screen Brightness"), maximumBrightness); setData(QStringLiteral("PowerDevil"), QStringLiteral("Screen Brightness Available"), maximumBrightness > 0); } void PowermanagementEngine::keyboardBrightnessChanged(int brightness) { setData(QStringLiteral("PowerDevil"), QStringLiteral("Keyboard Brightness"), brightness); } void PowermanagementEngine::maximumKeyboardBrightnessChanged(int maximumBrightness) { setData(QStringLiteral("PowerDevil"), QStringLiteral("Maximum Keyboard Brightness"), maximumBrightness); setData(QStringLiteral("PowerDevil"), QStringLiteral("Keyboard Brightness Available"), maximumBrightness > 0); } void PowermanagementEngine::triggersLidActionChanged(bool triggers) { setData(QStringLiteral("PowerDevil"), QStringLiteral("Triggers Lid Action"), triggers); } void PowermanagementEngine::inhibitionsChanged(const QList &added, const QStringList &removed) { for (auto it = removed.constBegin(); it != removed.constEnd(); ++it) { removeData(QStringLiteral("Inhibitions"), (*it)); } for (auto it = added.constBegin(); it != added.constEnd(); ++it) { const QString &name = (*it).first; QString prettyName; QString icon; const QString &reason = (*it).second; populateApplicationData(name, &prettyName, &icon); setData(QStringLiteral("Inhibitions"), name, QVariantMap{ {QStringLiteral("Name"), prettyName}, {QStringLiteral("Icon"), icon}, {QStringLiteral("Reason"), reason} }); } } void PowermanagementEngine::populateApplicationData(const QString &name, QString *prettyName, QString *icon) { if (m_applicationInfo.contains(name)) { const auto &info = m_applicationInfo.value(name); *prettyName = info.first; *icon = info.second; } else { KService::Ptr service = KService::serviceByStorageId(name + ".desktop"); if (service) { *prettyName = service->property(QStringLiteral("Name"), QVariant::Invalid).toString(); // cannot be null *icon = service->icon(); m_applicationInfo.insert(name, qMakePair(*prettyName, *icon)); } else { *prettyName = name; *icon = name.section(QLatin1Char('/'), -1).toLower(); } } } K_EXPORT_PLASMA_DATAENGINE_WITH_JSON(powermanagement, PowermanagementEngine, "plasma-dataengine-powermanagement.json") #include "powermanagementengine.moc"