KDBusAddons

kdbusservice.h
1/*
2 This file is part of libkdbusaddons
3
4 SPDX-FileCopyrightText: 2011 David Faure <faure@kde.org>
5 SPDX-FileCopyrightText: 2011 Kevin Ottens <ervin@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
8*/
9
10#ifndef KDBUSSERVICE_H
11#define KDBUSSERVICE_H
12
13#include <QObject>
14#include <QUrl>
15#include <memory>
16
17#include <kdbusaddons_export.h>
18
19class KDBusServicePrivate;
20
21/**
22 * @class KDBusService kdbusservice.h <KDBusService>
23 *
24 * KDBusService takes care of registering the current process with D-Bus.
25 *
26 * This registers the application at a predictable location on D-Bus, registers
27 * the QCoreApplication (or subclass) object at /MainApplication, and
28 * assists in implementing the application side of D-Bus activation from
29 * the <a
30 * href="http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html">Desktop
31 * Entry Specification</a>.
32 *
33 * An application can either work in Multiple mode or Unique mode.
34 *
35 * In Multiple mode, the application can be launched many times. The service
36 * name in the D-Bus registration will contain the PID to distinguish the
37 * various instances; for example: <tt>org.kde.konqueror-12345</tt>.
38 *
39 * In Unique mode, only one instance of this application can ever run.
40 * The first instance of the application registers with D-Bus without the PID,
41 * and any attempt to run the application again will cause the
42 * activateRequested() signal to be emitted in the already-running instance; the
43 * duplicate instance will then quit. The exit value can be set by the already
44 * running instance with setExitValue(), the default value is @c 0.
45 *
46 * Unique-mode applications should usually delay parsing command-line arguments
47 * until after creating a KDBusService object; that way they know they are the
48 * original instance of the application.
49 *
50 * Applications that set the D-Bus activation entry (DBusActivatable=true) in
51 * their desktop files will use Unique mode and connect to the signals emitted
52 * by this class.
53 * Note that the D-Bus interface is exported for Multiple-mode applications as
54 * well, so it also makes sense for such applications to connect to the signals
55 * emitted by this class.
56 *
57 * @note In order to avoid a race, the application should export its objects to
58 * D-Bus before allowing the event loop to run (for example, by calling
59 * QCoreApplication::exec()). Otherwise, the application will appear on the bus
60 * before its objects are accessible via D-Bus, which could be a problem for
61 * other applications or scripts which start the application in order to talk
62 * D-Bus to it immediately.
63 *
64 * Example usage:
65 *
66 * @code
67 QApplication app(argc, argv);
68 app.setApplicationName("kuiserver");
69 app.setOrganizationDomain("kde.org");
70 // Create your D-Bus objects here
71 // ...
72 KDBusService service(KDBusService::Unique);
73 // If this point is reached, this is the only running instance
74 // i.e. org.kde.kuiserver has been registered
75 return app.exec();
76 * @endcode
77 *
78 * @since 5.0
79 */
80class KDBUSADDONS_EXPORT KDBusService : public QObject
81{
82 Q_OBJECT
83
84public:
85 /**
86 * Options to control the behaviour of KDBusService
87 * @see StartupOptions
88 */
90 /**
91 * Indicates that only one instance of this application should ever exist.
92 *
93 * Cannot be combined with @c Multiple.
94 */
95 Unique = 1,
96 /**
97 * Indicates that multiple instances of the application may exist.
98 *
99 * Cannot be combined with @c Unique. This is the default.
100 */
101 Multiple = 2,
102 /** Indicates that the application should not exit if it failed to
103 * register with D-Bus.
104 *
105 * If not set, KDBusService will quit the application if it failed to
106 * register the service with D-Bus or a @c Unique instance can not be
107 * activated. A @c Multiple instance will exit with error code @c 1.
108 * The exit value of a @c Unique instance can be set from the running
109 * instance with setExitValue(), the default value is @c 0.
110 */
111 NoExitOnFailure = 4,
112 /**
113 * Indicates that if there's already a unique service running, to be quit and replaced
114 * with our own.
115 *
116 * If exported, it will try first quitting the service calling @c org.qtproject.Qt.QCoreApplication.quit,
117 * which is exported by KDBusService by default.
118 *
119 * @since 5.65
120 */
121 Replace = 8
122 };
123 Q_ENUM(StartupOption)
124
125 /**
126 * Stores a combination of #StartupOption values.
127 */
129 Q_FLAG(StartupOptions)
130
131 /**
132 * Tries to register the current process to D-Bus at an address based on the
133 * application name and organization domain.
134 *
135 * The D-Bus service name is the reversed organization domain, followed by
136 * the application name. If @p options includes the @c Multiple flag, the
137 * application PID will be appended. For example,
138 * @code
139 * app.setApplicationName("kuiserver");
140 * app.setOrganizationDomain("kde.org");
141 * @endcode
142 * will make KDBusService register as @c org.kde.kuiserver in @c Unique
143 * mode, and @c org.kde.kuiserver-1234 (if the process has PID @c 1234) in
144 * @c Multiple mode.
145 */
146 explicit KDBusService(StartupOptions options = Multiple, QObject *parent = nullptr);
147
148 /**
149 * Destroys this object (but does not unregister the application).
150 *
151 * Deleting this object before unregister() could confuse
152 * clients, who will see the service on the bus but will be unable to use
153 * the activation methods.
154 */
155 ~KDBusService() override;
156
157 /**
158 * Returns true if the D-Bus registration succeeded.
159 *
160 * Note that this is only useful when specifying the option NoExitOnFailure.
161 * Otherwise, the simple fact that this process is still running indicates
162 * that the registration succeeded.
163 */
164 bool isRegistered() const;
165
166 /**
167 * Returns the name of the D-Bus service registered by this class.
168 * Mostly useful when using the option Multiple.
169 * @since 5.33
170 */
171 QString serviceName() const;
172
173 /**
174 * Returns the error message from the D-Bus registration if it failed.
175 *
176 * Note that this is only useful when specifying the option NoExitOnFailure.
177 * Otherwise the process has quit by the time you can get a chance to call this.
178 */
179 QString errorMessage() const;
180
181 /**
182 * Sets the exit value to be used for a duplicate instance.
183 *
184 * If this is a @c Unique application, a slot connected to
185 * activateRequested() can use this to specify a non-zero exit value for the
186 * duplicate instance. This would typically be done if invalid command-line
187 * arguments are passed.
188 *
189 * Note that this will only work if the signal-slot connection type is
190 * Qt::DirectConnection.
191 *
192 * @param value The exit value for the duplicate instance.
193 */
194 void setExitValue(int value);
195
196Q_SIGNALS:
197 /**
198 * Signals that the application is to be activated.
199 *
200 * If this is a @c Unique application, when KDBusService is constructed in
201 * subsequent instances of the application (ie: when the executable is run
202 * when an instance is already running), it will cause this signal to be
203 * emitted in the already-running instance (with the arguments passed to the
204 * duplicate instance), and the duplicate instance will then exit.
205 *
206 * If this application's desktop file indicates that it supports D-Bus
207 * activation (DBusActivatable=true), a command launcher may also call the Activate()
208 * D-Bus method to trigger this signal. In this case, @p args will be empty.
209 *
210 * In single-window applications, the connected signal should typically
211 * raise the window.
212 *
213 * @param arguments The arguments the executable was called with, starting with the executable file name.
214 * See QCoreApplication::arguments().
215 * This can also be empty.
216 *
217 * A typical implementation of the signal handler would be:
218 * @code
219 * if (!arguments.isEmpty()) {
220 * commandLineParser->parse(arguments); // same QCommandLineParser instance as the one used in main()
221 * handleCmdLine(workingDirectory); // shared method with main(), which uses commandLineParser to handle options and positional arguments
222 * }
223 * @endcode
224 *
225 * For GUI applications, the handler also needs to deal with any platform-specific startup ids
226 * and make sure the mainwindow is shown as well as request its activation from the window manager.
227 * For X11, KDBusService makes the id for the Startup Notification protocol available
228 * from QX11Info::nextStartupId(), if there is one.
229 * For Wayland, KDBusService provides the token for the XDG Activation protocol in the
230 * "XDG_ACTIVATION_TOKEN" environment variable and unsets it again after the signal, if there is one.
231 * The util method @c KWindowSystem::updateStartupId(QWindow *window) (since KF 5.91) takes care of that.
232 * A typical implementation in the signal handler would be:
233 * @code
234 * mainWindow->show();
235 * KWindowSystem::updateStartupId(mainWindow->windowHandle());
236 * mainWindow->raise();
237 * KWindowSystem::activateWindow(mainWindow->windowHandle());
238 * @endcode
239 *
240 * If you're using the builtin handling of @c --help and @c --version in QCommandLineParser,
241 * you should call parser.process(arguments) before creating the KDBusService instance,
242 * since parse() doesn't handle those (and exiting the already-running instance would be wrong anyway).
243 *
244 * @see setExitValue()
245 */
246 void activateRequested(const QStringList &arguments, const QString &workingDirectory);
247
248 /**
249 * Signals that one or more files should be opened in the application.
250 *
251 * This signal is emitted to request handling of the respective method of the D-Bus activation.
252 * For GUI applications, the signal handler also needs to deal with any platform-specific startup ids
253 * and make sure the mainwindow is shown as well as request its activation from the window manager.
254 * See documentation of activateRequested(const QStringList &arguments, const QString &)
255 * for details.
256 *
257 * @param uris The URLs of the files to open.
258 */
259 void openRequested(const QList<QUrl> &uris);
260
261 /**
262 * Signals that an application action should be triggered.
263 *
264 * This signal is emitted to request handling of the respective method of the D-Bus activation.
265 * For GUI applications, the signal handler also needs to deal with any platform-specific startup ids
266 * and make sure the mainwindow is shown as well as request its activation from the window manager.
267 * See documentation of activateRequested(const QStringList &arguments, const QString &)
268 * for details.
269 *
270 * See the desktop entry specification for more information about action activation.
271 */
272 void activateActionRequested(const QString &actionName, const QVariant &parameter);
273
274public Q_SLOTS:
275 /**
276 * Manually unregister the given serviceName from D-Bus.
277 */
278 void unregister();
279
280private:
281 // fdo.Application spec
282 KDBUSADDONS_NO_EXPORT void Activate(const QVariantMap &platform_data);
283 KDBUSADDONS_NO_EXPORT void Open(const QStringList &uris, const QVariantMap &platform_data);
284 KDBUSADDONS_NO_EXPORT void ActivateAction(const QString &action_name, const QVariantList &maybeParameter, const QVariantMap &platform_data);
285 friend class KDBusServiceAdaptor;
286
287 // org.kde.KDBusService
288 KDBUSADDONS_NO_EXPORT int CommandLine(const QStringList &arguments, const QString &workingDirectory, const QVariantMap &platform_data);
289 friend class KDBusServiceExtensionsAdaptor;
290
291private:
292 std::unique_ptr<KDBusServicePrivate> const d;
293};
294
295Q_DECLARE_OPERATORS_FOR_FLAGS(KDBusService::StartupOptions)
296
297#endif /* KDBUSSERVICE_H */
KDBusService takes care of registering the current process with D-Bus.
StartupOption
Options to control the behaviour of KDBusService.
Q_ENUM(...)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 13 2024 11:52:36 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.