File indexing completed on 2024-05-12 17:10:48

0001 /***************************************************************************
0002  *   Copyright (C) 2008 by Dario Freddi <drf@kde.org>                      *
0003  *                                                                         *
0004  *   This program is free software; you can redistribute it and/or modify  *
0005  *   it under the terms of the GNU General Public License as published by  *
0006  *   the Free Software Foundation; either version 2 of the License, or     *
0007  *   (at your option) any later version.                                   *
0008  *                                                                         *
0009  *   This program is distributed in the hope that it will be useful,       *
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0012  *   GNU General Public License for more details.                          *
0013  *                                                                         *
0014  *   You should have received a copy of the GNU General Public License     *
0015  *   along with this program; if not, write to the                         *
0016  *   Free Software Foundation, Inc.,                                       *
0017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
0018  ***************************************************************************/
0019 
0020 #include "GeneralPage.h"
0021 
0022 #include "ErrorOverlay.h"
0023 #include "PowerDevilSettings.h"
0024 
0025 #include "actions/bundled/suspendsession.h"
0026 
0027 #include "powerdevilpowermanagement.h"
0028 
0029 #include <Solid/Device>
0030 #include <Solid/DeviceInterface>
0031 #include <Solid/Battery>
0032 
0033 #include <QDBusMessage>
0034 #include <QDBusReply>
0035 #include <QDBusConnection>
0036 #include <QDBusConnectionInterface>
0037 #include <QDBusMetaType>
0038 #include <QDBusServiceWatcher>
0039 
0040 #include <KNotifyConfigWidget>
0041 #include <KPluginFactory>
0042 #include <KSharedConfig>
0043 #include <KAboutData>
0044 #include <KLocalizedString>
0045 
0046 #include <kauth_version.h>
0047 #include <KAuth/Action>
0048 #include <KAuth/ExecuteJob>
0049 
0050 K_PLUGIN_CLASS_WITH_JSON(GeneralPage, "kcm_powerdevilglobalconfig.json")
0051 
0052 GeneralPage::GeneralPage(QWidget *parent, const QVariantList &args)
0053         : KCModule(parent, args)
0054 {
0055     setButtons(Apply | Help);
0056 
0057 //     KAboutData *about =
0058 //         new KAboutData("powerdevilglobalconfig", "powerdevilglobalconfig", ki18n("Global Power Management Configuration"),
0059 //                        "", ki18n("A global power management configurator for KDE Power Management System"),
0060 //                        KAboutData::License_GPL, ki18n("(c), 2010 Dario Freddi"),
0061 //                        ki18n("From this module, you can configure the main Power Management daemon, assign profiles to "
0062 //                              "states, and do some advanced fine tuning on battery handling"));
0063 //
0064 //     about->addAuthor(ki18n("Dario Freddi"), ki18n("Maintainer") , "drf@kde.org",
0065 //                      "http://drfav.wordpress.com");
0066 //
0067 //     setAboutData(about);
0068 
0069     setupUi(this);
0070 
0071     fillUi();
0072 
0073     QDBusServiceWatcher *watcher = new QDBusServiceWatcher("org.kde.Solid.PowerManagement",
0074                                                            QDBusConnection::sessionBus(),
0075                                                            QDBusServiceWatcher::WatchForRegistration |
0076                                                            QDBusServiceWatcher::WatchForUnregistration,
0077                                                            this);
0078 
0079     connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, &GeneralPage::onServiceRegistered);
0080     connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, &GeneralPage::onServiceUnregistered);
0081 
0082     if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.Solid.PowerManagement")) {
0083         onServiceRegistered("org.kde.Solid.PowerManagement");
0084     } else {
0085         onServiceUnregistered("org.kde.Solid.PowerManagement");
0086     }
0087 }
0088 
0089 GeneralPage::~GeneralPage()
0090 {
0091 }
0092 
0093 void GeneralPage::fillUi()
0094 {
0095     bool hasPowerSupplyBattery = false;
0096     bool hasPeripheralBattery = false;
0097 
0098     const auto devices = Solid::Device::listFromType(Solid::DeviceInterface::Battery, QString());
0099     for (const Solid::Device &device : devices) {
0100         const Solid::Battery *b = qobject_cast<const Solid::Battery*> (device.asDeviceInterface(Solid::DeviceInterface::Battery));
0101         if (b->isPowerSupply()) {
0102             hasPowerSupplyBattery = true;
0103         } else {
0104             hasPeripheralBattery = true;
0105         }
0106     }
0107 
0108     BatteryCriticalCombo->addItem(QIcon::fromTheme("dialog-cancel"), i18n("Do nothing"), PowerDevil::BundledActions::SuspendSession::None);
0109     if (PowerDevil::PowerManagement::instance()->canSuspend()) {
0110         BatteryCriticalCombo->addItem(QIcon::fromTheme("system-suspend"), i18nc("Suspend to RAM", "Sleep"), PowerDevil::BundledActions::SuspendSession::ToRamMode);
0111     }
0112     if (PowerDevil::PowerManagement::instance()->canHibernate()) {
0113         BatteryCriticalCombo->addItem(QIcon::fromTheme("system-suspend-hibernate"), i18n("Hibernate"), PowerDevil::BundledActions::SuspendSession::ToDiskMode);
0114     }
0115     BatteryCriticalCombo->addItem(QIcon::fromTheme("system-shutdown"), i18n("Shut down"), PowerDevil::BundledActions::SuspendSession::ShutdownMode);
0116 
0117     notificationsButton->setIcon(QIcon::fromTheme("preferences-desktop-notification"));
0118 
0119     // modified fields...
0120 
0121     connect(notificationsButton, &QAbstractButton::clicked, this, &GeneralPage::configureNotifications);
0122 
0123     connect(lowSpin, SIGNAL(valueChanged(int)), SLOT(changed()));
0124     connect(criticalSpin, SIGNAL(valueChanged(int)), SLOT(changed()));
0125     connect(lowPeripheralSpin, SIGNAL(valueChanged(int)), SLOT(changed()));
0126 
0127     connect(BatteryCriticalCombo, SIGNAL(currentIndexChanged(int)), SLOT(changed()));
0128 
0129     connect(chargeStartThresholdSpin, QOverload<int>::of(&QSpinBox::valueChanged), this, &GeneralPage::markAsChanged);
0130     connect(chargeStopThresholdSpin, QOverload<int>::of(&QSpinBox::valueChanged), this, &GeneralPage::onChargeStopThresholdChanged);
0131     chargeStopThresholdMessage->hide();
0132 
0133     connect(pausePlayersCheckBox, SIGNAL(stateChanged(int)), SLOT(changed()));
0134 
0135     if (!hasPowerSupplyBattery) {
0136         BatteryCriticalLabel->hide();
0137         BatteryCriticalCombo->hide();
0138         lowLabel->hide();
0139         lowSpin->hide();
0140         criticalLabel->hide();
0141         criticalSpin->hide();
0142     }
0143 
0144     if (!hasPeripheralBattery) {
0145         lowPeripheralLabel->hide();
0146         lowPeripheralSpin->hide();
0147     }
0148 
0149     if (!hasPowerSupplyBattery && !hasPeripheralBattery) {
0150         batteryLevelsLabel->hide();
0151     }
0152 }
0153 
0154 void GeneralPage::load()
0155 {
0156     lowSpin->setValue(PowerDevilSettings::batteryLowLevel());
0157     criticalSpin->setValue(PowerDevilSettings::batteryCriticalLevel());
0158     lowPeripheralSpin->setValue(PowerDevilSettings::peripheralBatteryLowLevel());
0159 
0160     BatteryCriticalCombo->setCurrentIndex(BatteryCriticalCombo->findData(PowerDevilSettings::batteryCriticalAction()));
0161 
0162     pausePlayersCheckBox->setChecked(PowerDevilSettings::pausePlayersOnSuspend());
0163 
0164     KAuth::Action action(QStringLiteral("org.kde.powerdevil.chargethresholdhelper.getthreshold"));
0165     action.setHelperId(QStringLiteral("org.kde.powerdevil.chargethresholdhelper"));
0166     KAuth::ExecuteJob *job = action.execute();
0167     job->exec();
0168 
0169     if (!job->error()) {
0170         const auto data = job->data();
0171         m_chargeStartThreshold = data.value(QStringLiteral("chargeStartThreshold")).toInt();
0172         chargeStartThresholdSpin->setValue(m_chargeStartThreshold);
0173         m_chargeStopThreshold = data.value(QStringLiteral("chargeStopThreshold")).toInt();
0174         chargeStopThresholdSpin->setValue(m_chargeStopThreshold);
0175 
0176         setChargeThresholdSupported(true);
0177     } else {
0178         qDebug() << "org.kde.powerdevil.chargethresholdhelper.getthreshold failed" << job->errorText();
0179         setChargeThresholdSupported(false);
0180     }
0181 
0182     Q_EMIT changed(false);
0183 }
0184 
0185 void GeneralPage::configureNotifications()
0186 {
0187     KNotifyConfigWidget::configure(this, "powerdevil");
0188 }
0189 
0190 void GeneralPage::save()
0191 {
0192     PowerDevilSettings::setBatteryLowLevel(lowSpin->value());
0193     PowerDevilSettings::setBatteryCriticalLevel(criticalSpin->value());
0194     PowerDevilSettings::setPeripheralBatteryLowLevel(lowPeripheralSpin->value());
0195 
0196     PowerDevilSettings::setBatteryCriticalAction(BatteryCriticalCombo->itemData(BatteryCriticalCombo->currentIndex()).toInt());
0197 
0198     PowerDevilSettings::setPausePlayersOnSuspend(pausePlayersCheckBox->checkState() == Qt::Checked);
0199 
0200     PowerDevilSettings::self()->save();
0201 
0202     if ((m_chargeStartThreshold != -1 && chargeStartThresholdSpin->value() != m_chargeStartThreshold) || (
0203                 m_chargeStopThreshold != -1 && chargeStopThresholdSpin->value() != m_chargeStopThreshold)) {
0204         KAuth::Action action(QStringLiteral("org.kde.powerdevil.chargethresholdhelper.setthreshold"));
0205         action.setHelperId(QStringLiteral("org.kde.powerdevil.chargethresholdhelper"));
0206         action.setArguments({
0207             {QStringLiteral("chargeStartThreshold"), m_chargeStartThreshold != -1 ? chargeStartThresholdSpin->value() : -1},
0208             {QStringLiteral("chargeStopThreshold"), m_chargeStopThreshold != -1 ? chargeStopThresholdSpin->value() : -1}
0209         });
0210         KAuth::ExecuteJob *job = action.execute();
0211         job->exec();
0212         if (!job->error()) {
0213             m_chargeStartThreshold = m_chargeStartThreshold != -1 ? chargeStartThresholdSpin->value() : -1;
0214             m_chargeStopThreshold = m_chargeStopThreshold != -1 ? chargeStopThresholdSpin->value() : -1;
0215         }
0216     }
0217 
0218     // Notify Daemon
0219     QDBusMessage call = QDBusMessage::createMethodCall("org.kde.Solid.PowerManagement", "/org/kde/Solid/PowerManagement",
0220                                                        "org.kde.Solid.PowerManagement", "refreshStatus");
0221 
0222     // Perform call
0223     QDBusConnection::sessionBus().asyncCall(call);
0224 
0225     // And now we are set with no change
0226     Q_EMIT changed(false);
0227 }
0228 
0229 void GeneralPage::defaults()
0230 {
0231     KCModule::defaults();
0232 }
0233 
0234 void GeneralPage::setChargeThresholdSupported(bool supported)
0235 {
0236     batteryThresholdLabel->setVisible(supported);
0237     batteryThresholdExplanation->setVisible(supported);
0238 
0239     chargeStartThresholdLabel->setVisible(supported && m_chargeStartThreshold != -1);
0240     chargeStartThresholdSpin->setVisible(supported && m_chargeStartThreshold != -1);
0241 
0242     chargeStopThresholdLabel->setVisible(supported && m_chargeStopThreshold != -1);
0243     chargeStopThresholdSpin->setVisible(supported && m_chargeStopThreshold != -1);
0244 }
0245 
0246 void GeneralPage::onServiceRegistered(const QString& service)
0247 {
0248     Q_UNUSED(service);
0249 
0250     if (m_errorOverlay) {
0251         m_errorOverlay->deleteLater();
0252         m_errorOverlay = nullptr;
0253     }
0254 }
0255 
0256 void GeneralPage::onServiceUnregistered(const QString& service)
0257 {
0258     Q_UNUSED(service);
0259 
0260     if (m_errorOverlay) {
0261         m_errorOverlay->deleteLater();
0262     }
0263 
0264     m_errorOverlay = new ErrorOverlay(this, i18n("The Power Management Service appears not to be running."),
0265                                       this);
0266 }
0267 
0268 void GeneralPage::onChargeStopThresholdChanged(int threshold)
0269 {
0270     if (threshold > m_chargeStopThreshold) {
0271         // Only show message if there is actually a charging or fully charged battery
0272         const auto devices = Solid::Device::listFromType(Solid::DeviceInterface::Battery, QString());
0273         for (const Solid::Device &device : devices) {
0274             const Solid::Battery *b = qobject_cast<const Solid::Battery*>(device.asDeviceInterface(Solid::DeviceInterface::Battery));
0275             if (b->chargeState() == Solid::Battery::Charging || b->chargeState() == Solid::Battery::FullyCharged) {
0276                 chargeStopThresholdMessage->animatedShow();
0277                 break;
0278             }
0279         }
0280     } else if (chargeStopThresholdMessage->isVisible()) {
0281         chargeStopThresholdMessage->animatedHide();
0282     }
0283 
0284     markAsChanged();
0285 }
0286 
0287 #include "GeneralPage.moc"