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

0001 /***************************************************************************
0002  *   Copyright (C) 2008-2010 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 "EditPage.h"
0021 
0022 #include "actioneditwidget.h"
0023 #include "ErrorOverlay.h"
0024 
0025 #include <powerdevilactionconfig.h>
0026 #include <powerdevilprofilegenerator.h>
0027 #include <powerdevilpowermanagement.h>
0028 
0029 #include <powerdevil_debug.h>
0030 #include <Kirigami/TabletModeWatcher>
0031 
0032 #include <QCheckBox>
0033 #include <QFormLayout>
0034 #include <QLabel>
0035 #include <QTabBar>
0036 
0037 #include <QDBusMessage>
0038 #include <QDBusReply>
0039 #include <QDBusConnection>
0040 #include <QDBusConnectionInterface>
0041 #include <QDBusMetaType>
0042 #include <QDBusServiceWatcher>
0043 
0044 #include <KConfigGroup>
0045 #include <QDebug>
0046 #include <KMessageBox>
0047 #include <KAboutData>
0048 #include <KPluginFactory>
0049 #include <KLocalizedString>
0050 
0051 #include <Solid/Battery>
0052 #include <Solid/Device>
0053 
0054 K_PLUGIN_CLASS_WITH_JSON(EditPage, "kcm_powerdevilprofilesconfig.json")
0055 
0056 EditPage::EditPage(QWidget *parent, const QVariantList &args)
0057         : KCModule(parent, args)
0058 {
0059     setButtons(Apply | Help | Default);
0060 
0061 //     KAboutData *about =
0062 //         new KAboutData("powerdevilprofilesconfig", "powerdevilprofilesconfig", ki18n("Power Profiles Configuration"),
0063 //                        "", ki18n("A profile configurator for KDE Power Management System"),
0064 //                        KAboutData::License_GPL, ki18n("(c), 2010 Dario Freddi"),
0065 //                        ki18n("From this module, you can manage KDE Power Management System's power profiles, by tweaking "
0066 //                              "existing ones or creating new ones."));
0067 //
0068 //     about->addAuthor(ki18n("Dario Freddi"), ki18n("Maintainer") , "drf@kde.org",
0069 //                      "http://drfav.wordpress.com");
0070 //
0071 //     setAboutData(about);
0072 
0073     setupUi(this);
0074 
0075     m_profilesConfig = KSharedConfig::openConfig("powermanagementprofilesrc", KConfig::SimpleConfig | KConfig::CascadeConfig);
0076 
0077     if (m_profilesConfig->groupList().isEmpty()) {
0078         auto interface = Kirigami::TabletModeWatcher::self();
0079 
0080         PowerDevil::ProfileGenerator::generateProfiles(
0081             interface->isTabletMode(),
0082             PowerDevil::PowerManagement::instance()->isVirtualMachine(),
0083             PowerDevil::PowerManagement::instance()->canSuspend(),
0084             PowerDevil::PowerManagement::instance()->canHibernate()
0085         );
0086         m_profilesConfig->reparseConfiguration();
0087     }
0088 
0089     qCDebug(POWERDEVIL) << "loaded profiles" << m_profilesConfig.data()->groupList() << m_profilesConfig.data()->entryMap().keys();
0090 
0091     // Create widgets for each profile
0092     ActionEditWidget *editWidget = new ActionEditWidget("AC", tabWidget);
0093     m_editWidgets.insert("AC", editWidget);
0094     acWidgetLayout->addWidget(editWidget);
0095     connect(editWidget, &ActionEditWidget::changed, this, &EditPage::onChanged);
0096 
0097     editWidget = new ActionEditWidget("Battery", tabWidget);
0098     m_editWidgets.insert("Battery", editWidget);
0099     batteryWidgetLayout->addWidget(editWidget);
0100     connect(editWidget, &ActionEditWidget::changed, this, &EditPage::onChanged);
0101 
0102     editWidget = new ActionEditWidget("LowBattery", tabWidget);
0103     m_editWidgets.insert("LowBattery", editWidget);
0104     lowBatteryWidgetLayout->addWidget(editWidget);
0105     connect(editWidget, &ActionEditWidget::changed, this, &EditPage::onChanged);
0106 
0107     QDBusServiceWatcher *watcher = new QDBusServiceWatcher("org.kde.Solid.PowerManagement",
0108                                                            QDBusConnection::sessionBus(),
0109                                                            QDBusServiceWatcher::WatchForRegistration |
0110                                                            QDBusServiceWatcher::WatchForUnregistration,
0111                                                            this);
0112 
0113     connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, &EditPage::onServiceRegistered);
0114     connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, &EditPage::onServiceUnregistered);
0115 
0116     bool hasBattery = false;
0117     const auto batteries = Solid::Device::listFromType(Solid::DeviceInterface::Battery, QString());
0118     for(const Solid::Device &device : batteries) {
0119         const Solid::Battery *b = qobject_cast<const Solid::Battery*> (device.asDeviceInterface(Solid::DeviceInterface::Battery));
0120         if (b->isPowerSupply() && (b->type() == Solid::Battery::PrimaryBattery || b->type() == Solid::Battery::UpsBattery)) {
0121             hasBattery = true;
0122             break;
0123         }
0124     }
0125 
0126     if (!hasBattery) {
0127         tabWidget->setTabEnabled(1, false);
0128         tabWidget->setTabEnabled(2, false);
0129         tabWidget->tabBar()->hide();
0130     }
0131 
0132     if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.Solid.PowerManagement")) {
0133         onServiceRegistered("org.kde.Solid.PowerManagement");
0134     } else {
0135         onServiceUnregistered("org.kde.Solid.PowerManagement");
0136     }
0137 }
0138 
0139 void EditPage::onChanged(bool value)
0140 {
0141     ActionEditWidget *editWidget = qobject_cast< ActionEditWidget* >(sender());
0142     if (!editWidget) {
0143         return;
0144     }
0145 
0146     m_profileEdited[editWidget->configName()] = value;
0147 
0148     if (value) {
0149         Q_EMIT changed(true);
0150     }
0151 
0152     checkAndEmitChanged();
0153 }
0154 
0155 void EditPage::load()
0156 {
0157     qCDebug(POWERDEVIL) << "Loading routine called";
0158     for (QHash< QString, ActionEditWidget* >::const_iterator i = m_editWidgets.constBegin();
0159          i != m_editWidgets.constEnd(); ++i) {
0160         i.value()->load();
0161 
0162         m_profileEdited[i.value()->configName()] = false;
0163     }
0164 }
0165 
0166 void EditPage::save()
0167 {
0168     for (auto it = m_editWidgets.constBegin(); it != m_editWidgets.constEnd(); ++it) {
0169         (*it)->save();
0170     }
0171 
0172     notifyDaemon();
0173 
0174     Q_EMIT changed(false);
0175 }
0176 
0177 void EditPage::notifyDaemon()
0178 {
0179     QDBusConnection::sessionBus().asyncCall(
0180         QDBusMessage::createMethodCall(
0181             QStringLiteral("org.kde.Solid.PowerManagement"),
0182             QStringLiteral("/org/kde/Solid/PowerManagement"),
0183             QStringLiteral("org.kde.Solid.PowerManagement"),
0184             QStringLiteral("refreshStatus")
0185         )
0186     );
0187 }
0188 
0189 void EditPage::restoreDefaultProfiles()
0190 {
0191     // Confirm
0192     int ret = KMessageBox::warningContinueCancel(this, i18n("The KDE Power Management System will now generate a set of defaults "
0193                                                             "based on your computer's capabilities. This will also erase "
0194                                                             "all existing modifications you made. "
0195                                                             "Are you sure you want to continue?"), i18n("Restore Default Profiles"));
0196     if (ret == KMessageBox::Continue) {
0197         qCDebug(POWERDEVIL) << "Restoring defaults.";
0198         auto interface = Kirigami::TabletModeWatcher::self();
0199 
0200         PowerDevil::ProfileGenerator::generateProfiles(
0201             interface->isTabletMode(),
0202             PowerDevil::PowerManagement::instance()->isVirtualMachine(),
0203             PowerDevil::PowerManagement::instance()->canSuspend(),
0204             PowerDevil::PowerManagement::instance()->canHibernate()
0205         );
0206 
0207         load();
0208 
0209         notifyDaemon();
0210     }
0211 }
0212 
0213 void EditPage::defaults()
0214 {
0215     restoreDefaultProfiles();
0216 }
0217 
0218 void EditPage::checkAndEmitChanged()
0219 {
0220     bool value = false;
0221     for (QHash< QString, bool >::const_iterator i = m_profileEdited.constBegin();
0222          i != m_profileEdited.constEnd(); ++i) {
0223         if (i.value()) {
0224             value = i.value();
0225         }
0226     }
0227 
0228     Q_EMIT changed(value);
0229 }
0230 
0231 void EditPage::onServiceRegistered(const QString& service)
0232 {
0233     Q_UNUSED(service);
0234 
0235     QDBusPendingCallWatcher *currentProfileWatcher = new QDBusPendingCallWatcher(QDBusConnection::sessionBus().asyncCall(
0236         QDBusMessage::createMethodCall(
0237             QStringLiteral("org.kde.Solid.PowerManagement"),
0238             QStringLiteral("/org/kde/Solid/PowerManagement"),
0239             QStringLiteral("org.kde.Solid.PowerManagement"),
0240             QStringLiteral("currentProfile")
0241         )
0242     ), this);
0243 
0244     QObject::connect(currentProfileWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
0245         QDBusPendingReply<QString> reply = *watcher;
0246 
0247         if (!reply.isError()) {
0248             const QString &currentProfile = reply.value();
0249             if (currentProfile == QLatin1String("Battery")) {
0250                 tabWidget->setCurrentIndex(1);
0251             } else if (currentProfile == QLatin1String("LowBattery")) {
0252                 tabWidget->setCurrentIndex(2);
0253             }
0254         }
0255 
0256         watcher->deleteLater();
0257     });
0258 
0259     if (m_errorOverlay) {
0260         m_errorOverlay->deleteLater();
0261         m_errorOverlay = nullptr;
0262     }
0263 }
0264 
0265 void EditPage::onServiceUnregistered(const QString& service)
0266 {
0267     Q_UNUSED(service);
0268 
0269     if (m_errorOverlay) {
0270         m_errorOverlay->deleteLater();
0271     }
0272 
0273     m_errorOverlay = new ErrorOverlay(this, i18n("The Power Management Service appears not to be running."),
0274                                       this);
0275 }
0276 
0277 #include "EditPage.moc"