1 /*
2   This file is part of the KDE Kontact Plugin Interface Library.
3 
4   SPDX-FileCopyrightText: 2003, 2008 David Faure <faure@kde.org>
5 
6   SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #pragma once
10 
11 #include "kontactinterface_export.h"
12 #include "plugin.h"
13 #include <memory>
14 class QCommandLineParser;
15 
16 namespace KontactInterface
17 {
18 /**
19  * D-Bus Object that has the name of the standalone application (e.g. "kmail")
20  * and implements newInstance() so that running the separate application does
21  * the right thing when kontact is running.
22  * By default this means simply bringing the main window to the front,
23  * but newInstance can be reimplemented.
24  */
25 class KONTACTINTERFACE_EXPORT UniqueAppHandler : public QObject
26 {
27     Q_OBJECT
28     // We implement the PIMUniqueApplication interface
29     Q_CLASSINFO("D-Bus Interface", "org.kde.PIMUniqueApplication")
30 
31 public:
32     explicit UniqueAppHandler(Plugin *plugin);
33     ~UniqueAppHandler() override;
34 
35     /// This must be reimplemented so that app-specific command line options can be parsed
36     virtual void loadCommandLineOptions(QCommandLineParser *parser) = 0;
37 
38     Q_REQUIRED_RESULT Plugin *plugin() const;
39 
40     /**
41       Sets the main QWidget @p widget associated with this application.
42       @param widget the QWidget to set as main
43     */
44     static void setMainWidget(QWidget *widget);
45 
46     /**
47       Returns the main widget, which will zero if setMainWidget() has not be called yet.
48       @since 4.6
49     */
50     Q_REQUIRED_RESULT QWidget *mainWidget();
51 
52 public Q_SLOTS: // DBUS methods
53     int newInstance(const QByteArray &asn_id, const QStringList &args, const QString &workingDirectory);
54     bool load();
55 
56 protected:
57     virtual int activate(const QStringList &args, const QString &workingDirectory);
58 
59 private:
60     class UniqueAppHandlerPrivate;
61     std::unique_ptr<UniqueAppHandlerPrivate> const d;
62 };
63 
64 /// Base class for UniqueAppHandler
65 class UniqueAppHandlerFactoryBase
66 {
67 public:
~UniqueAppHandlerFactoryBase()68     virtual ~UniqueAppHandlerFactoryBase()
69     {
70     }
71     virtual UniqueAppHandler *createHandler(Plugin *) = 0;
72 };
73 
74 /**
75  * Used by UniqueAppWatcher below, to create the above UniqueAppHandler object
76  * when necessary.
77  * The template argument is the UniqueAppHandler-derived class.
78  * This allows to remove the need to subclass UniqueAppWatcher.
79  */
80 template<class T> class UniqueAppHandlerFactory : public UniqueAppHandlerFactoryBase
81 {
82 public:
createHandler(Plugin * plugin)83     UniqueAppHandler *createHandler(Plugin *plugin) override
84     {
85         plugin->registerClient();
86         return new T(plugin);
87     }
88 };
89 
90 /**
91  * If the standalone application is running by itself, we need to watch
92  * for when the user closes it, and activate the uniqueapphandler then.
93  * This prevents, on purpose, that the standalone app can be restarted.
94  * Kontact takes over from there.
95  *
96  */
97 class KONTACTINTERFACE_EXPORT UniqueAppWatcher : public QObject
98 {
99     Q_OBJECT
100 
101 public:
102     /**
103      * Create an instance of UniqueAppWatcher, which does everything necessary
104      * for the "unique application" behavior: create the UniqueAppHandler as soon
105      * as possible, i.e. either right now or when the standalone app is closed.
106      *
107      * @param factory templatized factory to create the handler. Example:
108      * ...   Note that the watcher takes ownership of the factory.
109      * @param plugin is the plugin application
110      */
111     UniqueAppWatcher(UniqueAppHandlerFactoryBase *factory, Plugin *plugin);
112 
113     ~UniqueAppWatcher() override;
114 
115     bool isRunningStandalone() const;
116 
117 private Q_SLOTS:
118     void slotApplicationRemoved(const QString &name, const QString &oldOwner, const QString &newOwner);
119 
120 private:
121     class UniqueAppWatcherPrivate;
122     std::unique_ptr<UniqueAppWatcherPrivate> const d;
123 };
124 
125 } // namespace
126 
127