Qt 6.x
The Qt SDK
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
26
27int QDBusAdaptorConnector::relaySlotMethodIndex()
28{
30 cachedRelaySlotMethodIndex = staticMetaObject.indexOfMethod("relaySlot()");
31 Q_ASSERT(cachedRelaySlotMethodIndex != 0); // 0 should be deleteLater() or destroyed()
32 }
34}
35
37{
38 if (!obj)
39 return nullptr;
40
41 for (QObject *child : std::as_const(obj->children())) {
42 QDBusAdaptorConnector *connector = qobject_cast<QDBusAdaptorConnector *>(child);
43 if (connector) {
44 connector->polish();
45 return connector;
46 }
47 }
48 return nullptr;
49}
50
52{
53 return qDBusFindAdaptorConnector(adaptor->parent());
54}
55
57{
59 if (connector)
60 return connector;
61 return new QDBusAdaptorConnector(obj);
62}
63
65{
66 return adaptor->d_func()->xml;
67}
68
70 const QString &xml)
71{
72 adaptor->d_func()->xml = xml;
73}
74
110{
112
113 connector->waitingForPolish = true;
115}
116
124{
125}
126
136{
137 const QMetaObject *us = metaObject();
138 const QMetaObject *them = parent()->metaObject();
139 bool connected = false;
140 for (int idx = staticMetaObject.methodCount(); idx < us->methodCount(); ++idx) {
141 QMetaMethod mm = us->method(idx);
142
144 continue;
145
146 // try to connect/disconnect to a signal on the parent that has the same method signature
148 if (them->indexOfSignal(sig) == -1)
149 continue;
150 sig.prepend(QSIGNAL_CODE + '0');
151 parent()->disconnect(sig, this, sig);
152 if (enable)
153 connected = connect(parent(), sig, sig) || connected;
154 }
155 d_func()->autoRelaySignals = connected;
156}
157
165{
166 return d_func()->autoRelaySignals;
167}
168
170 : QObject(obj), waitingForPolish(false)
171{
172}
173
175{
176}
177
179{
180 // find the interface name
181 const QMetaObject *mo = adaptor->metaObject();
182 int ciid = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE);
183 if (ciid != -1) {
184 QMetaClassInfo mci = mo->classInfo(ciid);
185 if (*mci.value()) {
186 // find out if this interface exists first
187 const char *interface = mci.value();
188 AdaptorMap::Iterator it = std::lower_bound(adaptors.begin(), adaptors.end(),
190 if (it != adaptors.end() && qstrcmp(interface, it->interface) == 0) {
191 // exists. Replace it (though it's probably the same)
192 if (it->adaptor != adaptor) {
193 // reconnect the signals
194 disconnectAllSignals(it->adaptor);
195 connectAllSignals(adaptor);
196 }
197 it->adaptor = adaptor;
198 } else {
199 // create a new one
201 entry.interface = interface;
202 entry.adaptor = adaptor;
203 adaptors << entry;
204
205 // connect the adaptor's signals to our relaySlot slot
206 connectAllSignals(adaptor);
207 }
208 }
209 }
210}
211
213{
214 QMetaObject::disconnect(obj, -1, this, relaySlotMethodIndex());
215}
216
218{
219 QMetaObject::connect(obj, -1, this, relaySlotMethodIndex(), Qt::DirectConnection);
220}
221
223{
224 if (!waitingForPolish)
225 return; // avoid working multiple times if multiple adaptors were added
226
227 waitingForPolish = false;
228 for (QObject *child : std::as_const(parent()->children())) {
229 QDBusAbstractAdaptor *adaptor = qobject_cast<QDBusAbstractAdaptor *>(child);
230 if (adaptor)
231 addAdaptor(adaptor);
232 }
233
234 // sort the adaptor list
235 std::sort(adaptors.begin(), adaptors.end());
236}
237
239{
240 QObject *sndr = sender();
241 if (Q_LIKELY(sndr)) {
242 relay(sndr, senderSignalIndex(), argv.arguments);
243 } else {
244 qWarning("QtDBus: cannot relay signals from parent %s(%p \"%s\") unless they are emitted in the object's thread %s(%p \"%s\"). "
245 "Current thread is %s(%p \"%s\").",
249 }
250}
251
252void QDBusAdaptorConnector::relay(QObject *senderObj, int lastSignalIdx, void **argv)
253{
254 if (lastSignalIdx < QObject::staticMetaObject.methodCount())
255 // QObject signal (destroyed(QObject *)) -- ignore
256 return;
257
258 QMetaMethod mm = senderObj->metaObject()->method(lastSignalIdx);
259 const QMetaObject *senderMetaObject = mm.enclosingMetaObject();
260
261 QObject *realObject = senderObj;
262 if (qobject_cast<QDBusAbstractAdaptor *>(senderObj))
263 // it's an adaptor, so the real object is in fact its parent
264 realObject = realObject->parent();
265
266 // break down the parameter list
268 QString errorMsg;
269 int inputCount = qDBusParametersForMethod(mm, types, errorMsg);
270 if (inputCount == -1) {
271 // invalid signal signature
272 qWarning("QDBusAbstractAdaptor: Cannot relay signal %s::%s: %s",
273 senderMetaObject->className(), mm.methodSignature().constData(),
274 qPrintable(errorMsg));
275 return;
276 }
277 if (inputCount + 1 != types.size() ||
278 types.at(inputCount) == QDBusMetaTypeId::message()) {
279 // invalid signal signature
280 qWarning("QDBusAbstractAdaptor: Cannot relay signal %s::%s",
281 senderMetaObject->className(), mm.methodSignature().constData());
282 return;
283 }
284
286 const int numTypes = types.size();
287 args.reserve(numTypes - 1);
288 for (int i = 1; i < numTypes; ++i)
289 args << QVariant(QMetaType(types.at(i)), argv[i]);
290
291 // now emit the signal with all the information
292 emit relaySignal(realObject, senderMetaObject, lastSignalIdx, args);
293}
294
296
297#include "moc_qdbusabstractadaptor_p.cpp"
298#include "moc_qdbusabstractadaptor.cpp"
299
300#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:216
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
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)
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
iterator Iterator
Definition qlist.h:250
iterator end()
Definition qlist.h:609
iterator begin()
Definition qlist.h:608
void reserve(qsizetype size)
Definition qlist.h:746
\inmodule QtCore
const char * value() const
Returns the value of this item.
\inmodule QtCore
Definition qmetaobject.h:18
const QMetaObject * enclosingMetaObject() const
Definition qmetaobject.h:46
QByteArray methodSignature() const
MethodType methodType() const
Returns the type of this method (signal, slot, or method).
\inmodule QtCore
Definition qmetatype.h:320
\inmodule QtCore
Definition qobject.h:90
int senderSignalIndex() const
Definition qobject.cpp:2563
const QObjectList & children() const
Returns a list of child objects.
Definition qobject.h:171
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
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:2521
QString objectName
the name of this object
Definition qobject.h:94
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1561
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QThread * currentThread()
Definition qthread.cpp:966
\inmodule QtCore
Definition qvariant.h:64
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)
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
static QT_BEGIN_NAMESPACE int cachedRelaySlotMethodIndex
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:162
#define QSIGNAL_CODE
Definition qobjectdefs.h:41
GLsizei GLenum GLenum * types
GLboolean enable
GLhandleARB obj
[2]
GLuint entry
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1391
#define emit
const char className[16]
[1]
Definition qwizard.cpp:100
obj metaObject() -> className()
QXmlStreamReader xml
[0]
QLayoutItem * child
[0]
QJSValueList args
\inmodule QtCore
const char * className() const
Returns the class name.
int indexOfSignal(const char *signal) const
Finds signal and returns its index; otherwise returns -1.
static bool disconnect(const QObject *sender, int signal_index, const QObject *receiver, int method_index)
Definition qobject.cpp:3504
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.
int methodCount() const
Returns the number of methods in this class, including the number of methods provided by each base cl...
static Connection connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type=0, int *types=nullptr)
Definition qobject.cpp:3419
QMetaMethod method(int index) const
Returns the meta-data for the method with the given index.