// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \page usingadaptors.html \title Using Qt D-Bus 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 Qt D-Bus 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 \li \l{Declaring Slots in D-Bus Adaptors} \li \l{Declaring Signals in D-Bus Adaptors} \li \l{The Qt D-Bus Type System} \li In the \l{D-Bus Complex Ping Pong Example}, \c complexpong.h and \c complexpong.cpp show an implementation of QDBusAbstractAdaptor. \endlist \sa QDBusAbstractAdaptor */ /*! \page qdbusdeclaringslots.html \title Declaring Slots in D-Bus 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 Qt D-Bus 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 \li Asynchronous \li Input-only \li 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. The \c quit() slot in the \l {D-Bus Complex Ping Pong Example} is an example of this. \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 Qt D-Bus 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 Qt D-Bus 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 code/doc_src_qdbusadaptors.cpp 10 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 code/doc_src_qdbusadaptors.cpp 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 Qt D-Bus. 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 Qt D-Bus by calling QDBusMessage::reply() on the original message. It then becomes the responsibility 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 Qt D-Bus Adaptors}, {Declaring Signals in D-Bus Adaptors}, {The Qt D-Bus Type System}, QDBusConnection, QDBusMessage */ /*! \page qdbusdeclaringsignals.html \title Declaring Signals in D-Bus Adaptors \previouspage Declaring Slots in D-Bus Adaptors \nextpage The Qt D-Bus 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 Qt D-Bus 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 you can see in the \l {D-Bus Complex Ping Pong 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 Qt D-Bus Adaptors}, {Declaring Slots in D-Bus Adaptors}, {The Qt D-Bus Type System}, QDBusAbstractAdaptor */ /*! \page qdbustypesystem.html \title The Qt D-Bus Type System \previouspage Declaring Signals in D-Bus Adaptors D-Bus has an extensible type system based on a few primitives and composition of the primitives in arrays and structures. Qt D-Bus 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 \li Qt type \li D-Bus equivalent type \row \li uchar \li BYTE \row \li bool \li BOOLEAN \row \li short \li INT16 \row \li ushort \li UINT16 \row \li int \li INT32 \row \li uint \li UINT32 \row \li qlonglong \li INT64 \row \li qulonglong \li UINT64 \row \li double \li DOUBLE \row \li QString \li STRING \row \li QDBusVariant \li VARIANT \row \li QDBusObjectPath \li OBJECT_PATH \row \li QDBusSignature \li 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 Qt D-Bus, 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. Qt D-Bus 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 Qt D-Bus 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 and QMap. */ /*! \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 code/doc_src_qdbusadaptors.cpp 12 Its presence in the method implementation (outside the class declaration) is optional. \sa {Using Qt D-Bus Adaptors} */