File indexing completed on 2024-06-23 05:07:15
0001 /* 0002 SPDX-FileCopyrightText: 2008 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <QCommandLineParser> 0010 #include <QDBusConnection> 0011 #include <QDBusError> 0012 #include <QLoggingCategory> 0013 #include <QObject> 0014 0015 #include <memory> 0016 0017 class QCoreApplication; 0018 class QApplication; 0019 class QGuiApplication; 0020 0021 /** 0022 * D-Bus session bus monitoring and command line handling. 0023 */ 0024 class AkApplicationBase : public QObject 0025 { 0026 Q_OBJECT 0027 public: 0028 ~AkApplicationBase() override; 0029 void parseCommandLine(); 0030 void setDescription(const QString &desc); 0031 0032 void addCommandLineOptions(const QCommandLineOption &option); 0033 void addPositionalCommandLineOption(const QString &name, const QString &description = QString(), const QString &syntax = QString()); 0034 const QCommandLineParser &commandLineArguments() const 0035 { 0036 return mCmdLineParser; 0037 } 0038 0039 void printUsage() const; 0040 0041 /** Returns the AkApplication instance */ 0042 static AkApplicationBase *instance(); 0043 0044 /** Forward to Q[Core]Application for convenience. */ 0045 int exec(); 0046 0047 protected: 0048 AkApplicationBase(std::unique_ptr<QCoreApplication> app, const QLoggingCategory &loggingCategory); 0049 void init(); 0050 0051 std::unique_ptr<QCoreApplication> mApp; 0052 0053 private Q_SLOTS: 0054 void pollSessionBus() const; 0055 0056 private: 0057 QString mInstanceId; 0058 const QLoggingCategory &mLoggingCategory; 0059 static AkApplicationBase *sInstance; 0060 0061 QCommandLineParser mCmdLineParser; 0062 }; 0063 0064 template<typename T> 0065 class AkApplicationImpl : public AkApplicationBase 0066 { 0067 public: 0068 AkApplicationImpl(int &argc, char **argv, const QLoggingCategory &loggingCategory = *QLoggingCategory::defaultCategory()) 0069 : AkApplicationBase(std::make_unique<T>(argc, argv), loggingCategory) 0070 { 0071 init(); 0072 } 0073 }; 0074 0075 template<typename T> 0076 class AkUniqueApplicationImpl : public AkApplicationBase 0077 { 0078 public: 0079 AkUniqueApplicationImpl(int &argc, char **argv, const QString &serviceName, const QLoggingCategory &loggingCategory = *QLoggingCategory::defaultCategory()) 0080 : AkApplicationBase(std::make_unique<T>(argc, argv), loggingCategory) 0081 { 0082 registerUniqueServiceOrTerminate(serviceName, loggingCategory); 0083 init(); 0084 } 0085 0086 private: 0087 void registerUniqueServiceOrTerminate(const QString &serviceName, const QLoggingCategory &log) 0088 { 0089 auto bus = QDBusConnection::sessionBus(); 0090 if (!bus.isConnected()) { 0091 qCCritical(log, "Session bus not found. Is DBus running?"); 0092 exit(1); 0093 } 0094 0095 if (!bus.registerService(serviceName)) { 0096 // We couldn't register. Most likely, it's already running. 0097 const QString lastError = bus.lastError().message(); 0098 if (lastError.isEmpty()) { 0099 qCInfo(log, "Service %s already registered, terminating now.", qUtf8Printable(serviceName)); 0100 exit(0); // already running, so it's OK. Terminate now. 0101 } else { 0102 qCCritical(log, "Unable to register service as %s due to an error: %s", qUtf8Printable(serviceName), qUtf8Printable(lastError)); 0103 exit(1); // :( 0104 } 0105 } 0106 } 0107 }; 0108 0109 /** 0110 * Returns the contents of @p name environment variable if it is defined, 0111 * or @p defaultValue otherwise. 0112 */ 0113 QString akGetEnv(const char *name, const QString &defaultValue = QString()); 0114 0115 using AkCoreApplication = AkApplicationImpl<QCoreApplication>; 0116 using AkApplication = AkApplicationImpl<QApplication>; 0117 using AkGuiApplication = AkApplicationImpl<QGuiApplication>; 0118 using AkUniqueGuiApplication = AkUniqueApplicationImpl<QGuiApplication>;