1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
|
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in a
** written agreement between you and Nokia.
**
** GNU Free Documentation License
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of this
** file.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page usingadaptors.html
\title Using QtDBus Adaptors
\brief How to create and use DBus adaptors in Qt.
\ingroup best-practices
Adaptors are special classes that are attached to any QObject-derived class
and provide the interface to the external world using D-Bus. Adaptors are
intended to be lightweight classes whose main purpose is to relay calls to
and from the real object, possibly validating or converting the input from
the external world and, thus, protecting the real object.
Unlike multiple inheritance, adaptors can be added at any time to any object
(but not removed), which allows for greater flexibility when exporting
existing classes. Another advantage of adaptors is to provide similar but not
identical functionality in methods of the same name in different interfaces,
a case which can be quite common when adding a new version of a standard
interface to an object.
In order to use an adaptor, one must create a class which inherits
QDBusAbstractAdaptor. Since that is a standard QObject-derived class, the
Q_OBJECT macro must appear in the declaration and the source file must be
processed with the \l {moc} tool. The class must also contain one
Q_CLASSINFO entry with the \c {"D-Bus Interface"} name, declaring which
interface it is exporting. Only one entry per class is supported.
Any public slot in the class will be accessible through the bus over messages
of the MethodCall type. (See \l {Declaring Slots in D-Bus Adaptors} for more
information). Signals in the class will be automatically relayed over D-Bus.
However, not all types are allowed signals or slots' parameter lists: see
\l {The QtDBus Type System} for more information.
Also, any property declared with Q_PROPERTY will be automatically exposed
over the Properties interface on D-Bus. Since the QObject property system
does not allow for non-readable properties, it is not possible to declare
write-only properties using adaptors.
More information:
\list
\o \l{Declaring Slots in D-Bus Adaptors}
\o \l{Declaring Signals in D-Bus Adaptors}
\o \l{The QtDBus Type System}
\o \l{D-Bus Adaptor Example}
\endlist
\sa QDBusAbstractAdaptor
*/
/*!
\page qdbusadaptorexample.html
\title D-Bus Adaptor Example
\previouspage The QtDBus Type System
\contentspage Using QtDBus Adaptors
The following example code shows how a D-Bus interface can be implemented
using an adaptor.
A sample usage of QDBusAbstractAdaptor is as follows:
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 0
The code above would create an interface that could be represented more or less in the following
canonical representation:
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 1
This adaptor could be used in the application's main function as follows
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 2
Break-down analysis:
\tableofcontents
\section1 The header
The header of the example is:
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 3
The code does the following:
\list
\o it declares the adaptor MainApplicationAdaptor, which descends from QDBusAbstractAdaptor
\o it declares the Qt meta-object data using the Q_OBJECT macro
\o it declares the name of the D-Bus interface it implements.
\endlist
\section1 The properties
The properties are declared as follows:
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 4
And are implemented as follows:
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 5
The code declares three properties: one of them is a read-write property called "caption" of
string type. The other two are read-only, also of the string type.
The properties organizationName and organizationDomain are simple relays of the app object's
organizationName and organizationDomain properties. However, the caption property requires
verifying if the application has a main window associated with it: if there isn't any, the
caption property is empty. Note how it is possible to access data defined in other objects
through the getter/setter functions.
\section1 The constructor
The constructor:
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 6
The constructor does the following:
\list
\o it initialises its base class (QDBusAbstractAdaptor) with the parent object it is related to.
\o it stores the app pointer in a member variable. Note that it would be possible to access the
same object using the QDBusAbstractAdaptor::object() function, but it would be necessary to
use \a static_cast<> to properly access the methods in QApplication that are not part of
QObject.
\o it connects the application's signal \a aboutToQuit to its own signal \a aboutToQuit.
\o it connects the application's signal \a focusChanged to a private slot to do some further
processing before emitting a D-Bus signal.
\endlist
Note that there is no destructor in the example. An eventual destructor could be used to emit
one last signal before the object is destroyed, for instance.
\section1 Slots/methods
The public slots in the example (which will be exported as D-Bus methods) are the following:
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 7
This snippet of code defines 4 methods with different properties each:
\list 1
\o \c quit: this method takes no parameters and is defined to be asynchronous. That is, callers
are expected to use "fire-and-forget" mechanism when calling this method, since it provides no
useful reply. This is represented in D-Bus by the use of the
org.freedesktop.DBus.Method.NoReply annotation. See \l Q_NOREPLY for more information on
asynchronous methods
\o \c reparseConfiguration: this simple method, with no input or output arguments simply relays
the call to the application's reparseConfiguration member function.
\o \c mainWindowObject: this method takes no input parameter, but returns one string output
argument, containing the path to the main window object (if the application has a main
window), or an empty string if it has no main window. Note that this method could have also
been written: void mainWindowObject(QString &path).
\o \c setSessionManagement: this method takes one input argument (a boolean) and, depending on
its value, it calls one function or another in the application.
\endlist
See also: \l Q_NOREPLY.
\section1 Signals
The signals in this example are defined as follows:
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 8
However, signal definition isn't enough: signals have to be emitted. One simple way of emitting
signals is to connect another signal to them, so that Qt's signal handling system chains them
automatically. This is what is done for the \a aboutToQuit signal.
When this is the case, one can use the QDBusAbstractAdaptor::setAutoRelaySignals to
automatically connect every signal from the real object to the adaptor.
When simple signal-to-signal connection isn't enough, one can use a private slot do do some
work. This is what was done for the mainWindowHasFocus signal:
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 9
This private slot (which will not be exported as a method via D-Bus) was connected to the
\c focusChanged signal in the adaptor's constructor. It is therefore able to shape the
application's signal into what the interface expects it to be.
*/
/*!
\page qdbusdeclaringslots.html
\title Declaring Slots in D-Bus Adaptors
\contentspage Using QtDBus Adaptors
\nextpage Declaring Signals in D-Bus Adaptors
Slots in D-Bus adaptors are declared just like normal, public slots, but their
parameters must follow certain rules (see \l{The QtDBus Type System} for more
information). Slots whose parameters do not follow those rules or that are not
public will not be accessible via D-Bus.
Slots can have one parameter of type \c{const QDBusMessage &}, which must
appear at the end of the input parameter list, before any output parameters.
This parameter, if present, will be initialized with a copy of the
current message being processed, which allows the callee to obtain
information about the caller, such as its connection name.
Slots can be of three kinds:
\list 1
\o Asynchronous
\o Input-only
\o Input-and-output
\endlist
\section1 Asynchronous Slots
Asynchronous slots are those that do not normally return any reply to the
caller. For that reason, they cannot take any output parameters. In most
cases, by the time the first line of the slot is run, the caller function
has already resumed working.
However, slots must not rely on that behavior. Scheduling and message-dispatching
issues could change the order in which the slot is run. Code intending to
synchronize with the caller should provide its own method of synchronization.
Asynchronous slots are marked by the keyword \l Q_NOREPLY in the method
signature, before the \c void return type and the slot name. (See the
\c quit() slot in the \l{D-Bus Adaptor Example}).
\section1 Input-Only Slots
Input-only slots are normal slots that take parameters passed by value or
by constant reference. However, unlike asynchronous slots, the caller is
usually waiting for completion of the callee before resuming operation.
Therefore, non-asynchronous slots should not block or should state it its
documentation that they may do so.
Input-only slots have no special marking in their signature, except that
they take only parameters passed by value or by constant reference.
Optionally, slots can take a QDBusMessage parameter as a last parameter,
which can be used to perform additional analysis of the method call message.
\section1 Input and Output Slots
Like input-only slots, input-and-output slots are those that the caller is
waiting for a reply. Unlike input-only ones, though, this reply will contain
data. Slots that output data may contain non-constant references and may
return a value as well. However, the output parameters must all appear at
the end of the argument list and may not have input arguments interleaved.
Optionally, a QDBusMessage argument may appear between the input and the
output arguments.
\section1 Automatic Replies
Method replies are generated automatically with the contents of the output
parameters (if there were any) by the QtDBus implementation. Slots need not
worry about constructing proper QDBusMessage objects and sending them over
the connection.
However, the possibility of doing so remains there. Should the slot find out
it needs to send a special reply or even an error, it can do so by using
QDBusMessage::createReply() or QDBusMessage::createErrorReply() on the
QDBusMessage parameter and send it with QDBusConnection::send(). The
QtDBus implementation will not generate any reply if the slot did so.
\warning When a caller places a method call and waits for a reply, it will
only wait for a limited amount of time. Slots intending to take a long time
to complete should make that fact clear in documentation so that callers
properly set higher timeouts.
\section1 Delayed Replies
In some circumstances, the called slot may not be able to process
the request immediately. This is frequently the case when the
request involves an I/O or networking operation which may block.
If this is the case, the slot should return control to the
application's main loop to avoid freezing the user interface, and
resume the process later. To accomplish this, it should make use
of the extra \c QDBusMessage parameter at the end of the input
parameter list and request a delayed reply.
We do this by writing a slot that stores the request data in a
persistent structure, indicating to the caller using
\l{QDBusMessage::setDelayedReply()}{QDBusMessage::setDelayedReply(true)}
that the response will be sent later.
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 10
The use of
\l{QDBusConnection::send()}{QDBusConnection::sessionBus().send(data->reply)}
is needed to explicitly inform the caller that the response will be delayed.
In this case, the return value is unimportant; we return an arbitrary value
to satisfy the compiler.
When the request is processed and a reply is available, it should be sent
using the \c QDBusMessage object that was obtained. In our example, the
reply code could be something as follows:
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 11
As can be seen in the example, when a delayed reply is in place,
the return value(s) from the slot will be ignored by QtDBus. They
are used only to determine the slot's signature when communicating
the adaptor's description to remote applications, or in case the
code in the slot decides not to use a delayed reply.
The delayed reply itself is requested from QtDBus by calling
QDBusMessage::reply() on the original message. It then becomes the
resposibility of the called code to eventually send a reply to the
caller.
\warning When a caller places a method call and waits for a reply, it will
only wait for a limited amount of time. Slots intending to take a long time
to complete should make that fact clear in documentation so that callers
properly set higher timeouts.
\sa {Using QtDBus Adaptors}, {Declaring Signals in D-Bus Adaptors},
{The QtDBus Type System}, QDBusConnection, QDBusMessage
*/
/*!
\page qdbusdeclaringsignals.html
\title Declaring Signals in D-Bus Adaptors
\previouspage Declaring Slots in D-Bus Adaptors
\contentspage Using QtDBus Adaptors
\nextpage The QtDBus Type System
Any signal in a class derived from QDBusAbstractAdaptor will be automatically
relayed into D-Bus, provided that the signal's parameters conform to certain
rules (see \l{The QtDBus Type System} for more information). No special code
is necessary to make this relay.
However, signals must still be emitted. The easiest way to emit an adaptor
signal is to connect another signal to it, so that Qt's signals and slots
mechanism automatically emits the adaptor signal, too. This can be done in
the adaptor's constructor, as has been done in the
\l{D-Bus Adaptor Example}{D-Bus Adaptor example}.
The QDBusAbstractAdaptor::setAutoRelaySignals() convenience function can also
be used to make and break connections between signals in the real object and
the corresponding signals in the adaptor. It will inspect the list of signals
in both classes and connect those whose parameters match exactly.
\sa {Using QtDBus Adaptors},
{Declaring Slots in D-Bus Adaptors},
{The QtDBus Type System}, QDBusAbstractAdaptor
*/
/*!
\page qdbustypesystem.html
\title The QtDBus Type System
\previouspage Declaring Signals in D-Bus Adaptors
\contentspage Using QtDBus Adaptors
\nextpage D-Bus Adaptor Example
D-Bus has an extensible type system based on a few primitives and
composition of the primitives in arrays and structures. QtDBus
implements the interface to that type system through the
QDBusArgument class, allowing user programs to send and receive
practically every C++ type over the bus.
\section1 Primitive Types
The primitive types are supported natively by QDBusArgument and
need no special customization to be sent or received. They are
listed below, along with the C++ class they relate to:
\table
\header
\o Qt type
\o D-Bus equivalent type
\row
\o uchar
\o BYTE
\row
\o bool
\o BOOLEAN
\row
\o short
\o INT16
\row
\o ushort
\o UINT16
\row
\o int
\o INT32
\row
\o uint
\o UINT32
\row
\o qlonglong
\o INT64
\row
\o qulonglong
\o UINT64
\row
\o double
\o DOUBLE
\row
\o QString
\o STRING
\row
\o QDBusVariant
\o VARIANT
\row
\o QDBusObjectPath
\o OBJECT_PATH
\row
\o QDBusSignature
\o SIGNATURE
\endtable
Aside from the primitive types, QDBusArgument also supports two
non-primitive types natively, due to their widespread use in Qt
applications: QStringList and QByteArray.
\section1 Compound Types
D-Bus specifies three types of aggregations of primitive types
that allow one to create compound types. They are \c ARRAY, \c
STRUCT and maps/dictionaries.
Arrays are sets of zero or more elements of the same type, while
structures are a set of a fixed number of elements, each of any
type. Maps or dictionaries are implemented as arrays of a pair of
elements, so there can be zero or more elements in one map.
\section1 Extending the Type System
In order to use one's own type with QtDBus, the type has to be
declared as a Qt meta-type with the Q_DECLARE_METATYPE() macro and
registered with the qDBusRegisterMetaType() function. The
streaming operators \c{operator>>} and \c{operator<<} will be
automatically found by the registration system.
QtDBus provides template specializations for arrays and maps for
use with Qt's \l{Container classes}{container classes}, such as
QMap and QList, so it is not necessary to write the streaming
operator functions for those. For other types, and specially for
types implementing structures, the operators have to be explicitly
implemented.
See the documentation for QDBusArgument for examples for
structures, arrays and maps.
\section1 The Type System in Use
All of the QtDBus types (primitives and user-defined alike) can be
used to send and receive messages of all types over the bus.
\warning You may not use any type that is not on the list above,
including \a typedefs to the types listed. This also includes
QList<QVariant> and QMap<QString,QVariant>.
*/
/*!
\macro Q_NOREPLY
\relates QDBusAbstractAdaptor
\since 4.2
The Q_NOREPLY macro can be used to mark a method to be called and not wait for it to finish
processing before returning from QDBusInterface::call(). The called method cannot return any
output arguments and, if it does, any such arguments will be discarded.
You can use this macro in your own adaptors by placing it before your method's return value
(which must be "void") in the class declaration, as shown in the example:
\snippet doc/src/snippets/code/doc_src_qdbusadaptors.qdoc 12
Its presence in the method implementation (outside the class declaration) is optional.
\sa {Using QtDBus Adaptors}
*/
|