File indexing completed on 2024-04-28 16:55:13

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