File indexing completed on 2024-05-12 09:41:26

0001 /*
0002  *   SPDX-FileCopyrightText: 2010 Dario Freddi <drf@kde.org>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "powerdevilapp.h"
0008 
0009 #include "powerdevilfdoconnector.h"
0010 #include "powermanagementadaptor.h"
0011 #include "powermanagementpolicyagentadaptor.h"
0012 
0013 #include "powerdevil_debug.h"
0014 #include "powerdevil_version.h"
0015 #include "powerdevilcore.h"
0016 #include "../osd/osd.h"
0017 
0018 #include <QAction>
0019 #include <QDBusConnection>
0020 #include <QDBusConnectionInterface>
0021 #include <QDebug>
0022 #include <QFileInfo>
0023 #include <QKeySequence>
0024 #include <QSessionManager>
0025 #include <QTimer>
0026 
0027 #include <KAboutData>
0028 #include <KCrash>
0029 #include <KDBusService>
0030 #include <KLocalizedString>
0031 
0032 #include <KActionCollection>
0033 #include <KGlobalAccel>
0034 
0035 #include <qnamespace.h>
0036 
0037 PowerDevilApp::PowerDevilApp(int &argc, char **argv)
0038     : QGuiApplication(argc, argv)
0039     , m_core(nullptr)
0040 {
0041 }
0042 
0043 PowerDevilApp::~PowerDevilApp()
0044 {
0045     delete m_core;
0046 }
0047 
0048 void PowerDevilApp::init()
0049 {
0050     KLocalizedString::setApplicationDomain(QByteArrayLiteral("powerdevil"));
0051 
0052     KAboutData aboutData(QStringLiteral("org_kde_powerdevil"),
0053                          i18n("KDE Power Management System"),
0054                          QStringLiteral(POWERDEVIL_VERSION_STRING),
0055                          i18nc("@title", "PowerDevil, an advanced, modular and lightweight power management daemon"),
0056                          KAboutLicense::GPL,
0057                          i18nc("@info:credit", "(c) 2015-2019 Kai Uwe Broulik"));
0058     aboutData.addAuthor(i18nc("@info:credit", "Kai Uwe Broulik"), i18nc("@info:credit", "Maintainer"), QStringLiteral("kde@privat.broulik.de"));
0059     aboutData.addAuthor(i18nc("@info:credit", "Dario Freddi"), i18nc("@info:credit", "Previous maintainer"), QStringLiteral("drf@kde.org"));
0060     aboutData.setProductName("Powerdevil");
0061 
0062     KAboutData::setApplicationData(aboutData);
0063 
0064     if (QDBusConnection::systemBus().interface()->isServiceRegistered(QLatin1String("org.freedesktop.PowerManagement"))
0065         || QDBusConnection::systemBus().interface()->isServiceRegistered(QLatin1String("org.freedesktop.Policy.Power"))) {
0066         qCCritical(POWERDEVIL) << "KDE Power Management system not initialized, another power manager has been detected";
0067         return;
0068     }
0069 
0070     // not parenting Core to PowerDevilApp as it is the deleted too late on teardown
0071     // where the X connection is already lost leading to a crash (Bug 371127)
0072     m_core = new PowerDevil::Core(nullptr /*, KComponentData(aboutData)*/);
0073 
0074     connect(m_core, &PowerDevil::Core::coreReady, this, &PowerDevilApp::onCoreReady);
0075 
0076     // Before doing anything, let's set up our backend
0077     const QStringList paths = QCoreApplication::libraryPaths();
0078     QFileInfoList fileInfos;
0079     for (const QString &path : paths) {
0080         QDir dir(path + QStringLiteral("/kf6/powerdevil/"), QStringLiteral("*"), QDir::SortFlags(QDir::QDir::Name), QDir::NoDotAndDotDot | QDir::Files);
0081         fileInfos.append(dir.entryInfoList());
0082     }
0083 
0084     QFileInfo backendFileInfo;
0085     for (const QFileInfo &f : std::as_const(fileInfos)) {
0086         if (f.baseName().toLower() == QLatin1String("powerdevilupowerbackend")) {
0087             backendFileInfo = f;
0088             break;
0089         }
0090     }
0091 
0092     QPluginLoader *loader = new QPluginLoader(backendFileInfo.filePath(), m_core);
0093     QObject *instance = loader->instance();
0094     if (!instance) {
0095         qCCritical(POWERDEVIL) << "KDE Power Management System init failed!" << loader->errorString();
0096         return;
0097     }
0098 
0099     auto interface = qobject_cast<PowerDevil::BackendInterface *>(instance);
0100     if (!interface) {
0101         qCCritical(POWERDEVIL) << "KDE Power Management System init failed! Failed to cast plugin instance to BackendInterface, check your plugin";
0102         return;
0103     }
0104 
0105     qCDebug(POWERDEVIL) << "Backend loaded, loading core";
0106     m_core->loadCore(interface);
0107 }
0108 
0109 void PowerDevilApp::onCoreReady()
0110 {
0111     qCDebug(POWERDEVIL) << "Core is ready, registering various services on the bus...";
0112     // DBus logic for the core
0113     new PowerManagementAdaptor(m_core);
0114     new PowerDevil::FdoConnector(m_core);
0115 
0116     QDBusConnection::sessionBus().registerService(QLatin1String("org.kde.Solid.PowerManagement"));
0117     QDBusConnection::sessionBus().registerObject(QLatin1String("/org/kde/Solid/PowerManagement"), m_core);
0118 
0119     QDBusConnection::systemBus().interface()->registerService("org.freedesktop.Policy.Power");
0120 
0121     // Start the Policy Agent service
0122     qDBusRegisterMetaType<QList<InhibitionInfo>>();
0123     qDBusRegisterMetaType<InhibitionInfo>();
0124     new PowerManagementPolicyAgentAdaptor(PowerDevil::PolicyAgent::instance());
0125 
0126     QDBusConnection::sessionBus().registerService(QLatin1String("org.kde.Solid.PowerManagement.PolicyAgent"));
0127     QDBusConnection::sessionBus().registerObject(QLatin1String("/org/kde/Solid/PowerManagement/PolicyAgent"), PowerDevil::PolicyAgent::instance());
0128 
0129     KActionCollection *coll = new KActionCollection(this);
0130     QAction *action = coll->addAction(QStringLiteral("powerProfile"));
0131     action->setText(i18n("Switch Power Profile"));
0132     KGlobalAccel::self()->setGlobalShortcut(action, QList<QKeySequence>{Qt::Key_Battery, Qt::MetaModifier | Qt::Key_B});
0133     connect(action, &QAction::triggered, this, &PowerDevilApp::showOsd);
0134 }
0135 
0136 int main(int argc, char **argv)
0137 {
0138     QGuiApplication::setDesktopSettingsAware(false);
0139     QGuiApplication::setAttribute(Qt::AA_DisableSessionManager);
0140     PowerDevilApp app(argc, argv);
0141     KCrash::initialize();
0142 
0143     bool replace = false;
0144     {
0145         QCommandLineParser parser;
0146         QCommandLineOption replaceOption({QStringLiteral("replace")}, i18n("Replace an existing instance"));
0147 
0148         parser.addOption(replaceOption);
0149 
0150         KAboutData aboutData = KAboutData::applicationData();
0151         aboutData.setupCommandLine(&parser);
0152 
0153         parser.process(app);
0154         aboutData.processCommandLine(&parser);
0155 
0156         replace = parser.isSet(replaceOption);
0157     }
0158     KDBusService service(KDBusService::Unique | KDBusService::StartupOption(replace ? KDBusService::Replace : 0));
0159     KCrash::setFlags(KCrash::AutoRestart);
0160 
0161     app.setQuitOnLastWindowClosed(false);
0162     app.setQuitLockEnabled(false);
0163     app.init();
0164 
0165     return app.exec();
0166 }
0167 
0168 void PowerDevilApp::showOsd() {
0169     QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.powerdevil.powerProfileOsdService"),
0170                                                           QStringLiteral("/org/kde/powerdevil/powerProfileOsdService"),
0171                                                           QStringLiteral("org.kde.powerdevil.powerProfileOsdService"),
0172                                                           QStringLiteral("showOsd"));
0173     QDBusConnection::sessionBus().asyncCall(message);
0174 }
0175 
0176 #include "moc_powerdevilapp.cpp"