diff --git a/src/pimuniqueapplication.h b/src/pimuniqueapplication.h --- a/src/pimuniqueapplication.h +++ b/src/pimuniqueapplication.h @@ -33,7 +33,7 @@ /** * KDEPIM applications which can be integrated into kontact should use - * PimUniqueApplication instead of Qapplication + Dbus unique. + * PimUniqueApplication instead of QApplication + Dbus unique. * This makes command-line handling work, i.e. you can launch "korganizer" * and if kontact is already running, it will load the korganizer part and * switch to it. @@ -49,8 +49,19 @@ ~PimUniqueApplication(); void setAboutData(KAboutData &aboutData); - static bool start(const QStringList &arguments, - bool unique = true); + + /** + * Register this process as a unique application, if not already running. + * Typically called in main(). + * @param arguments should start with the appname, as QCoreApplication::arguments() does. + */ + static bool start(const QStringList &arguments); + + /** + * Ensure that another PIM application is running. + */ + static bool activateApplication(const QString &application, + const QStringList &additionalArguments = {}); Q_REQUIRED_RESULT QCommandLineParser *cmdArgs() const; diff --git a/src/pimuniqueapplication.cpp b/src/pimuniqueapplication.cpp --- a/src/pimuniqueapplication.cpp +++ b/src/pimuniqueapplication.cpp @@ -101,12 +101,38 @@ QDBusConnection::ExportAdaptors); } -bool PimUniqueApplication::start(const QStringList &arguments, bool unique) +static bool callNewInstance(const QString &appName, const QString &serviceName, const QByteArray &asn_id, const QStringList &arguments) +{ + const QString objectName = QLatin1Char('/') + appName + QLatin1String("_PimApplication"); + QDBusInterface iface(serviceName, + objectName, + QStringLiteral("org.kde.PIMUniqueApplication"), + QDBusConnection::sessionBus()); + if (iface.isValid()) { + QDBusReply reply = iface.call(QStringLiteral("newInstance"), + asn_id, + arguments, + QDir::currentPath()); + if (reply.isValid()) { + return true; + } + } + return false; +} + +int PimUniqueApplication::newInstance() +{ + return newInstance(KStartupInfo::startupId(), QStringList() << QApplication::applicationName(), QDir::currentPath()); +} + + +bool PimUniqueApplication::start(const QStringList &arguments) { const QString appName = QApplication::applicationName(); + // Try talking to /appName_PimApplication in org.kde.appName, // (which could be kontact or the standalone application), - // otherwise fall back to starting a new app + // otherwise the current app being started will register to DBus. const QString serviceName = QLatin1String("org.kde.") + appName; if (QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName)) { @@ -125,39 +151,31 @@ KWindowSystem::allowExternalProcessWindowActivation(); - const QString objectName = QLatin1Char('/') + appName + QLatin1String("_PimApplication"); - qCDebug(KONTACTINTERFACE_LOG) << objectName; - QDBusInterface iface(serviceName, - objectName, - QStringLiteral("org.kde.PIMUniqueApplication"), - QDBusConnection::sessionBus()); - if (iface.isValid()) { - QDBusReply reply = iface.call(QStringLiteral("newInstance"), - new_asn_id, - arguments, - QDir::currentPath()); - if (reply.isValid()) { - return false; // success means that main() can exist now. - } + if (callNewInstance(appName, serviceName, new_asn_id, arguments)) { + return false; // success means that main() can exit now. } } qCDebug(KONTACTINTERFACE_LOG) << "kontact not running -- start standalone application"; - if (unique) { - QDBusConnection::sessionBus().registerService(serviceName); - } + QDBusConnection::sessionBus().registerService(serviceName); // Make sure we have DrKonqi Private::disableChromiumCrashHandler(); static_cast(qApp)->activate(arguments, QDir::currentPath()); return true; } -int PimUniqueApplication::newInstance() +bool PimUniqueApplication::activateApplication(const QString &appName, const QStringList &additionalArguments) { - return newInstance(KStartupInfo::startupId(), QStringList() << QApplication::applicationName(), QDir::currentPath()); + const QString serviceName = QLatin1String("org.kde.") + appName; + QStringList arguments{ appName }; + arguments += additionalArguments; + // Start it standalone if not already running (if kontact is running, then this will do nothing) + QDBusConnection::sessionBus().interface()->startService(serviceName); + return callNewInstance(appName, serviceName, KStartupInfo::createNewStartupId(), arguments); + } // This is called via DBus either by another instance that has just been diff --git a/src/uniqueapphandler.h b/src/uniqueapphandler.h --- a/src/uniqueapphandler.h +++ b/src/uniqueapphandler.h @@ -40,7 +40,7 @@ class KONTACTINTERFACE_EXPORT UniqueAppHandler : public QObject { Q_OBJECT - // We implement the KUniqueApplication interface + // We implement the PIMUniqueApplication interface Q_CLASSINFO("D-Bus Interface", "org.kde.PIMUniqueApplication") public: