Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
// Qt-Security score:significant reason:default
5
6
#
include
"qdbusabstractadaptor.h"
7
#
include
"qdbusabstractadaptor_p.h"
8
9
#
include
<
QtCore
/
qcoreapplication
.
h
>
10
#
include
<
QtCore
/
qmetaobject
.
h
>
11
#
include
<
QtCore
/
qset
.
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
23
QT_BEGIN_NAMESPACE
24
25
int
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
32
QDBusAdaptorConnector
*
qDBusFindAdaptorConnector
(QObject *obj)
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
47
QDBusAdaptorConnector
*
qDBusFindAdaptorConnector
(QDBusAbstractAdaptor *adaptor)
48
{
49
return
qDBusFindAdaptorConnector(adaptor->parent());
50
}
51
52
QDBusAdaptorConnector
*
qDBusCreateAdaptorConnector
(QObject *obj)
53
{
54
QDBusAdaptorConnector
*connector =
qDBusFindAdaptorConnector
(
obj
)
;
55
if
(connector)
56
return
connector;
57
return
new
QDBusAdaptorConnector(obj);
58
}
59
60
QString
QDBusAbstractAdaptorPrivate
::retrieveIntrospectionXml(QDBusAbstractAdaptor *adaptor)
61
{
62
return
adaptor->d_func()->xml;
63
}
64
65
void
QDBusAbstractAdaptorPrivate
::saveIntrospectionXml(QDBusAbstractAdaptor *adaptor,
66
const
QString &xml)
67
{
68
adaptor->d_func()->xml = xml;
69
}
70
71
/*!
72
\class QDBusAbstractAdaptor
73
\inmodule QtDBus
74
\since 4.2
75
76
\brief The QDBusAbstractAdaptor class is the base class of D-Bus adaptor classes.
77
78
The QDBusAbstractAdaptor class is the starting point for all objects intending to provide
79
interfaces to the external world using D-Bus. This is accomplished by attaching a one or more
80
classes derived from QDBusAbstractAdaptor to a normal QObject and then registering that QObject
81
with QDBusConnection::registerObject. QDBusAbstractAdaptor objects are intended to be
82
light-weight wrappers, mostly just relaying calls into the real object (its parent) and the
83
signals from it.
84
85
Each QDBusAbstractAdaptor-derived class should define the D-Bus interface it is implementing
86
using the Q_CLASSINFO macro in the class definition. Note that only one interface can be
87
exposed in this way.
88
89
QDBusAbstractAdaptor uses the standard QObject mechanism of signals, slots and properties to
90
determine what signals, methods and properties to export to the bus. Any signal emitted by
91
QDBusAbstractAdaptor-derived classes will be automatically be relayed through any D-Bus
92
connections the object is registered on.
93
94
Classes derived from QDBusAbstractAdaptor must be created on the heap using the \a new operator
95
and must not be deleted by the user (they will be deleted automatically when the object they are
96
connected to is also deleted).
97
98
\sa {usingadaptors.html}{Using adaptors}, QDBusConnection
99
*/
100
101
/*!
102
Constructs a QDBusAbstractAdaptor with \a obj as the parent object.
103
*/
104
QDBusAbstractAdaptor::QDBusAbstractAdaptor(QObject* obj)
105
: QObject(*
new
QDBusAbstractAdaptorPrivate, obj)
106
{
107
108
Q_ASSERT_X(obj, Q_FUNC_INFO,
"Expected non-null parent"
);
109
110
QDBusAdaptorConnector *connector = qDBusCreateAdaptorConnector(obj);
111
112
connector->waitingForPolish =
true
;
113
QMetaObject::invokeMethod(connector, &QDBusAdaptorConnector::polish, Qt::QueuedConnection);
114
}
115
116
/*!
117
Destroys the adaptor.
118
119
\warning Adaptors are destroyed automatically when the real object they refer to is
120
destroyed. Do not delete the adaptors yourself.
121
*/
122
QDBusAbstractAdaptor::~QDBusAbstractAdaptor()
123
{
124
}
125
126
/*!
127
Toggles automatic signal relaying from the real object (see object()).
128
129
Automatic signal relaying consists of signal-to-signal connection of the signals on the parent
130
that have the exact same method signature in both classes.
131
132
If \a enable is set to true, connect the signals; if set to false, disconnect all signals.
133
*/
134
void
QDBusAbstractAdaptor::setAutoRelaySignals(
bool
enable)
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
142
if
(mm.methodType() != QMetaMethod::Signal)
143
continue
;
144
145
// try to connect/disconnect to a signal on the parent that has the same method signature
146
QByteArray sig = QMetaObject::normalizedSignature(mm.methodSignature().constData());
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
157
/*!
158
Returns \c true if automatic signal relaying from the real object (see object()) is enabled,
159
otherwiser returns \c false.
160
161
\sa setAutoRelaySignals()
162
*/
163
bool
QDBusAbstractAdaptor::autoRelaySignals()
const
164
{
165
return
d_func()->autoRelaySignals;
166
}
167
168
QDBusAdaptorConnector
::QDBusAdaptorConnector(QObject *obj)
169
: QObject(obj),
waitingForPolish
(
false
)
170
{
171
}
172
173
QDBusAdaptorConnector
::~
QDBusAdaptorConnector
()
174
{
175
}
176
177
void
QDBusAdaptorConnector
::
addAdaptor
(QDBusAbstractAdaptor *adaptor)
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(),
188
QByteArrayView(interface));
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
199
AdaptorData entry;
200
entry.interface = interface;
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
211
void
QDBusAdaptorConnector
::disconnectAllSignals(QObject *obj)
212
{
213
QMetaObject::disconnect(obj, -1,
this
, relaySlotMethodIndex());
214
}
215
216
void
QDBusAdaptorConnector
::connectAllSignals(QObject *obj)
217
{
218
QMetaObject::connect(obj, -1,
this
, relaySlotMethodIndex(), Qt::DirectConnection);
219
}
220
221
void
QDBusAdaptorConnector
::
polish
()
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
237
void
QDBusAdaptorConnector
::relaySlot(QMethodRawArguments argv)
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\")."
,
245
parent()->metaObject()->className(), parent(), qPrintable(parent()->objectName()),
246
parent()->thread()->metaObject()->className(), parent()->thread(), qPrintable(parent()->thread()->objectName()),
247
QThread::currentThread()->metaObject()->className(), QThread::currentThread(), qPrintable(QThread::currentThread()->objectName()));
248
}
249
}
250
251
void
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
284
QVariantList args;
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
294
QT_END_NAMESPACE
295
296
#
include
"moc_qdbusabstractadaptor_p.cpp"
297
#
include
"moc_qdbusabstractadaptor.cpp"
298
299
#
endif
// QT_NO_DBUS
QDBusAbstractAdaptorPrivate
Definition
qdbusabstractadaptor_p.h:47
QDBusAdaptorConnector
Definition
qdbusabstractadaptor_p.h:59
QDBusAdaptorConnector::addAdaptor
void addAdaptor(QDBusAbstractAdaptor *adaptor)
Definition
qdbusabstractadaptor.cpp:177
QDBusAdaptorConnector::polish
void polish()
Definition
qdbusabstractadaptor.cpp:221
QDBusAdaptorConnector::waitingForPolish
bool waitingForPolish
Definition
qdbusabstractadaptor_p.h:95
QDBusAdaptorConnector::~QDBusAdaptorConnector
~QDBusAdaptorConnector()
Definition
qdbusabstractadaptor.cpp:173
QDBusAdaptorConnector::adaptors
AdaptorMap adaptors
Definition
qdbusabstractadaptor_p.h:94
std
[33]
Definition
src_corelib_tools_qhash.cpp:421
qDBusFindAdaptorConnector
QDBusAdaptorConnector * qDBusFindAdaptorConnector(QDBusAbstractAdaptor *adaptor)
Definition
qdbusabstractadaptor.cpp:47
qDBusCreateAdaptorConnector
QDBusAdaptorConnector * qDBusCreateAdaptorConnector(QObject *obj)
Definition
qdbusabstractadaptor.cpp:52
qDBusFindAdaptorConnector
QDBusAdaptorConnector * qDBusFindAdaptorConnector(QObject *obj)
Definition
qdbusabstractadaptor.cpp:32
QCLASSINFO_DBUS_INTERFACE
#define QCLASSINFO_DBUS_INTERFACE
Definition
qdbusabstractadaptor_p.h:30
qtbase
src
dbus
qdbusabstractadaptor.cpp
Generated on
for Qt by
1.18.0