Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qdbusabstractadaptor.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
7
8#include <QtCore/qcoreapplication.h>
9#include <QtCore/qmetaobject.h>
10#include <QtCore/qset.h>
11#include <QtCore/qtimer.h>
12#include <QtCore/qthread.h>
13
14#include "qdbusconnection.h"
15
16#include "qdbusconnection_p.h" // for qDBusParametersForMethod
17#include "qdbusmetatype_p.h"
18
19#include <algorithm>
20
21#ifndef QT_NO_DBUS
22
24
25int QDBusAdaptorConnector::relaySlotMethodIndex()
26{
27 static const int cachedRelaySlotMethodIndex = staticMetaObject.indexOfMethod("relaySlot()");
28 Q_ASSERT(cachedRelaySlotMethodIndex != 0); // 0 should be deleteLater() or destroyed()
29 return cachedRelaySlotMethodIndex;
30}
31
33{
34 if (!obj)
35 return nullptr;
36
37 for (QObject *child : std::as_const(obj->children())) {
38 QDBusAdaptorConnector *connector = qobject_cast<QDBusAdaptorConnector *>(child);
39 if (connector) {
40 connector->polish();
41 return connector;
42 }
43 }
44 return nullptr;
45}
46
51
53{
55 if (connector)
56 return connector;
57 return new QDBusAdaptorConnector(obj);
58}
59
64
66 const QString &xml)
67{
68 adaptor->d_func()->xml = xml;
69}
70
106{
107
108 Q_ASSERT_X(obj, Q_FUNC_INFO, "Expected non-null parent");
109
111
112 connector->waitingForPolish = true;
114}
115
125
135{
136 const QMetaObject *us = metaObject();
137 const QMetaObject *them = parent()->metaObject();
138 bool connected = false;
139 for (int idx = staticMetaObject.methodCount(); idx < us->methodCount(); ++idx) {
140 QMetaMethod mm = us->method(idx);
141
143 continue;
144
145 // try to connect/disconnect to a signal on the parent that has the same method signature
147 if (them->indexOfSignal(sig) == -1)
148 continue;
149 sig.prepend(QSIGNAL_CODE + '0');
150 parent()->disconnect(sig, this, sig);
151 if (enable)
152 connected = connect(parent(), sig, sig) || connected;
153 }
154 d_func()->autoRelaySignals = connected;
155}
156
164{
165 return d_func()->autoRelaySignals;
166}
167
172
176
178{
179 // find the interface name
180 const QMetaObject *mo = adaptor->metaObject();
181 int ciid = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE);
182 if (ciid != -1) {
183 QMetaClassInfo mci = mo->classInfo(ciid);
184 if (*mci.value()) {
185 // find out if this interface exists first
186 const char *interface = mci.value();
187 AdaptorMap::Iterator it = std::lower_bound(adaptors.begin(), adaptors.end(),
189 if (it != adaptors.end() && qstrcmp(interface, it->interface) == 0) {
190 // exists. Replace it (though it's probably the same)
191 if (it->adaptor != adaptor) {
192 // reconnect the signals
193 disconnectAllSignals(it->adaptor);
194 connectAllSignals(adaptor);
195 }
196 it->adaptor = adaptor;
197 } else {
198 // create a new one
201 entry.adaptor = adaptor;
202 adaptors << entry;
203
204 // connect the adaptor's signals to our relaySlot slot
205 connectAllSignals(adaptor);
206 }
207 }
208 }
209}
210
212{
213 QMetaObject::disconnect(obj, -1, this, relaySlotMethodIndex());
214}
215
220
222{
223 if (!waitingForPolish)
224 return; // avoid working multiple times if multiple adaptors were added
225
226 waitingForPolish = false;
227 for (QObject *child : std::as_const(parent()->children())) {
228 QDBusAbstractAdaptor *adaptor = qobject_cast<QDBusAbstractAdaptor *>(child);
229 if (adaptor)
230 addAdaptor(adaptor);
231 }
232
233 // sort the adaptor list
234 std::sort(adaptors.begin(), adaptors.end());
235}
236
238{
239 QObject *sndr = sender();
240 if (Q_LIKELY(sndr)) {
241 relay(sndr, senderSignalIndex(), argv.arguments);
242 } else {
243 qWarning("QtDBus: cannot relay signals from parent %s(%p \"%s\") unless they are emitted in the object's thread %s(%p \"%s\"). "
244 "Current thread is %s(%p \"%s\").",
248 }
249}
250
251void QDBusAdaptorConnector::relay(QObject *senderObj, int lastSignalIdx, void **argv)
252{
253 if (lastSignalIdx < QObject::staticMetaObject.methodCount())
254 // QObject signal (destroyed(QObject *)) -- ignore
255 return;
256
257 QMetaMethod mm = senderObj->metaObject()->method(lastSignalIdx);
258 const QMetaObject *senderMetaObject = mm.enclosingMetaObject();
259
260 QObject *realObject = senderObj;
261 if (qobject_cast<QDBusAbstractAdaptor *>(senderObj))
262 // it's an adaptor, so the real object is in fact its parent
263 realObject = realObject->parent();
264
265 // break down the parameter list
266 QList<QMetaType> types;
267 QString errorMsg;
268 int inputCount = qDBusParametersForMethod(mm, types, errorMsg);
269 if (inputCount == -1) {
270 // invalid signal signature
271 qWarning("QDBusAbstractAdaptor: Cannot relay signal %s::%s: %s",
272 senderMetaObject->className(), mm.methodSignature().constData(),
273 qPrintable(errorMsg));
274 return;
275 }
276 if (inputCount + 1 != types.size() ||
277 types.at(inputCount) == QDBusMetaTypeId::message()) {
278 // invalid signal signature
279 qWarning("QDBusAbstractAdaptor: Cannot relay signal %s::%s",
280 senderMetaObject->className(), mm.methodSignature().constData());
281 return;
282 }
283
285 const int numTypes = types.size();
286 args.reserve(numTypes - 1);
287 for (int i = 1; i < numTypes; ++i)
288 args << QVariant(QMetaType(types.at(i)), argv[i]);
289
290 // now emit the signal with all the information
291 emit relaySignal(realObject, senderMetaObject, lastSignalIdx, args);
292}
293
295
296#include "moc_qdbusabstractadaptor_p.cpp"
297#include "moc_qdbusabstractadaptor.cpp"
298
299#endif // QT_NO_DBUS
bool connected
\inmodule QtCore
Definition qbytearray.h:57
QByteArray & prepend(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qbytearray.h:280
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
static void saveIntrospectionXml(QDBusAbstractAdaptor *adaptor, const QString &xml)
static QString retrieveIntrospectionXml(QDBusAbstractAdaptor *adaptor)
QDBusAbstractAdaptor(QObject *parent)
Constructs a QDBusAbstractAdaptor with obj as the parent object.
bool autoRelaySignals() const
Returns true if automatic signal relaying from the real object (see object()) is enabled,...
void setAutoRelaySignals(bool enable)
Toggles automatic signal relaying from the real object (see object()).
~QDBusAbstractAdaptor()
Destroys the adaptor.
void relay(QObject *sender, int id, void **)
void addAdaptor(QDBusAbstractAdaptor *adaptor)
void relaySlot(QMethodRawArguments a)
void relaySignal(QObject *obj, const QMetaObject *metaObject, int sid, const QVariantList &args)
void disconnectAllSignals(QObject *object)
QDBusAdaptorConnector(QObject *parent)
void connectAllSignals(QObject *object)
qsizetype size() const noexcept
Definition qlist.h:397
iterator Iterator
Definition qlist.h:249
iterator end()
Definition qlist.h:626
iterator begin()
Definition qlist.h:625
void reserve(qsizetype size)
Definition qlist.h:753
\inmodule QtCore
\inmodule QtCore
Definition qmetaobject.h:19
const QMetaObject * enclosingMetaObject() const
Definition qmetaobject.h:47
QByteArray methodSignature() const
MethodType methodType() const
Returns the type of this method (signal, slot, or method).
\inmodule QtCore
Definition qmetatype.h:341
\inmodule QtCore
Definition qobject.h:103
int senderSignalIndex() const
Definition qobject.cpp:2700
const QObjectList & children() const
Returns a list of child objects.
Definition qobject.h:201
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition qobject.cpp:2658
QString objectName
the name of this object
Definition qobject.h:107
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1598
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QThread * currentThread()
Definition qthread.cpp:1039
\inmodule QtCore
Definition qvariant.h:65
QSet< QString >::iterator it
auto mo
[7]
QMetaType message()
Combined button and popup list for selecting options.
@ QueuedConnection
@ DirectConnection
Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2)
#define Q_LIKELY(x)
#define Q_FUNC_INFO
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char * interface
QDBusAdaptorConnector * qDBusCreateAdaptorConnector(QObject *obj)
QDBusAdaptorConnector * qDBusFindAdaptorConnector(QObject *obj)
#define QCLASSINFO_DBUS_INTERFACE
int qDBusParametersForMethod(const QMetaMethod &mm, QList< QMetaType > &metaTypes, QString &errorMsg)
#define qWarning
Definition qlogging.h:166
#define QSIGNAL_CODE
Definition qobjectdefs.h:42
GLsizei GLenum GLenum * types
GLboolean enable
GLhandleARB obj
[2]
GLuint entry
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
#define qPrintable(string)
Definition qstring.h:1531
#define emit
const char className[16]
[1]
Definition qwizard.cpp:100
obj metaObject() -> className()
QXmlStreamReader xml
[0]
QLayoutItem * child
[0]
QJSValueList args
\inmodule QtCore
static bool disconnect(const QObject *sender, int signal_index, const QObject *receiver, int method_index)
Definition qobject.cpp:3641
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
static QByteArray normalizedSignature(const char *method)
Normalizes the signature of the given method.
static Connection connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type=0, int *types=nullptr)
Definition qobject.cpp:3556