Qt 4.8
qdbusabstractadaptor.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtDBus module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qdbusabstractadaptor.h"
43 
44 #include <QtCore/qcoreapplication.h>
45 #include <QtCore/qmetaobject.h>
46 #include <QtCore/qset.h>
47 #include <QtCore/qtimer.h>
48 #include <QtCore/qthread.h>
49 
50 #include "qdbusconnection.h"
51 
52 #include "qdbusconnection_p.h" // for qDBusParametersForMethod
53 #include "qdbusabstractadaptor_p.h"
54 #include "qdbusmetatype_p.h"
55 
56 #ifndef QT_NO_DBUS
57 
59 
61 {
62  if (!obj)
63  return 0;
64  const QObjectList &children = obj->children();
67  for ( ; it != end; ++it) {
69  if (connector) {
70  connector->polish();
71  return connector;
72  }
73  }
74  return 0;
75 }
76 
78 {
79  return qDBusFindAdaptorConnector(adaptor->parent());
80 }
81 
83 {
85  if (connector)
86  return connector;
87  return new QDBusAdaptorConnector(obj);
88 }
89 
91 {
92  return adaptor->d_func()->xml;
93 }
94 
96  const QString &xml)
97 {
98  adaptor->d_func()->xml = xml;
99 }
100 
139 {
141 
142  connector->waitingForPolish = true;
143  QMetaObject::invokeMethod(connector, "polish", Qt::QueuedConnection);
144 }
145 
153 {
154 }
155 
165 {
166  const QMetaObject *us = metaObject();
167  const QMetaObject *them = parent()->metaObject();
168  bool connected = false;
169  for (int idx = staticMetaObject.methodCount(); idx < us->methodCount(); ++idx) {
170  QMetaMethod mm = us->method(idx);
171 
172  if (mm.methodType() != QMetaMethod::Signal)
173  continue;
174 
175  // try to connect/disconnect to a signal on the parent that has the same method signature
177  if (them->indexOfSignal(sig) == -1)
178  continue;
179  sig.prepend(QSIGNAL_CODE + '0');
180  parent()->disconnect(sig, this, sig);
181  if (enable)
182  connected = connect(parent(), sig, sig) || connected;
183  }
184  d_func()->autoRelaySignals = connected;
185 }
186 
194 {
195  return d_func()->autoRelaySignals;
196 }
197 
199  : QObject(obj), waitingForPolish(false)
200 {
201 }
202 
204 {
205 }
206 
208 {
209  // find the interface name
210  const QMetaObject *mo = adaptor->metaObject();
212  if (ciid != -1) {
213  QMetaClassInfo mci = mo->classInfo(ciid);
214  if (*mci.value()) {
215  // find out if this interface exists first
216  const char *interface = mci.value();
218  QByteArray(interface));
219  if (it != adaptors.end() && qstrcmp(interface, it->interface) == 0) {
220  // exists. Replace it (though it's probably the same)
221  if (it->adaptor != adaptor) {
222  // reconnect the signals
223  disconnectAllSignals(it->adaptor);
224  connectAllSignals(adaptor);
225  }
226  it->adaptor = adaptor;
227  } else {
228  // create a new one
229  AdaptorData entry;
230  entry.interface = interface;
231  entry.adaptor = adaptor;
232  adaptors << entry;
233 
234  // connect the adaptor's signals to our relaySlot slot
235  connectAllSignals(adaptor);
236  }
237  }
238  }
239 }
240 
242 {
243  QMetaObject::disconnect(obj, -1, this, metaObject()->methodOffset());
244 }
245 
247 {
248  QMetaObject::connect(obj, -1, this, metaObject()->methodOffset(), Qt::DirectConnection);
249 }
250 
252 {
253  if (!waitingForPolish)
254  return; // avoid working multiple times if multiple adaptors were added
255 
256  waitingForPolish = false;
257  const QObjectList &objs = parent()->children();
260  for ( ; it != end; ++it) {
262  if (adaptor)
263  addAdaptor(adaptor);
264  }
265 
266  // sort the adaptor list
267  qSort(adaptors);
268 }
269 
271 {
272  QObjectPrivate *d = static_cast<QObjectPrivate *>(d_ptr.data());
273  if (Q_LIKELY(d->currentSender)) {
275  } else {
276  qWarning("QtDBus: cannot relay signals from parent %s(%p \"%s\") unless they are emitted in the object's thread %s(%p \"%s\"). "
277  "Current thread is %s(%p \"%s\").",
281  }
282 }
283 
284 void QDBusAdaptorConnector::relay(QObject *senderObj, int lastSignalIdx, void **argv)
285 {
286  if (lastSignalIdx < QObject::staticMetaObject.methodCount())
287  // QObject signal (destroyed(QObject *)) -- ignore
288  return;
289 
290  const QMetaObject *senderMetaObject = senderObj->metaObject();
291  QMetaMethod mm = senderMetaObject->method(lastSignalIdx);
292 
293  QObject *realObject = senderObj;
294  if (qobject_cast<QDBusAbstractAdaptor *>(senderObj))
295  // it's an adaptor, so the real object is in fact its parent
296  realObject = realObject->parent();
297 
298  // break down the parameter list
300  int inputCount = qDBusParametersForMethod(mm, types);
301  if (inputCount == -1)
302  // invalid signal signature
303  // qDBusParametersForMethod has already complained
304  return;
305  if (inputCount + 1 != types.count() ||
306  types.at(inputCount) == QDBusMetaTypeId::message) {
307  // invalid signal signature
308  // qDBusParametersForMethod has not yet complained about this one
309  qWarning("QDBusAbstractAdaptor: Cannot relay signal %s::%s",
310  senderMetaObject->className(), mm.signature());
311  return;
312  }
313 
314  QVariantList args;
315  for (int i = 1; i < types.count(); ++i)
316  args << QVariant(types.at(i), argv[i]);
317 
318  // now emit the signal with all the information
319  emit relaySignal(realObject, senderMetaObject, lastSignalIdx, args);
320 }
321 
322 // our Meta Object
323 // modify carefully: this has been hand-edited!
324 // the relaySlot slot has local ID 0 (we use this when calling QMetaObject::connect)
325 // it also gets called with the void** array
326 
328  // content:
329  1, // revision
330  0, // classname
331  0, 0, // classinfo
332  3, 10, // methods
333  0, 0, // properties
334  0, 0, // enums/sets
335 
336  // slots: signature, parameters, type, tag, flags
337  106, 22, 22, 22, 0x0a,
338  118, 22, 22, 22, 0x0a,
339 
340  // signals: signature, parameters, type, tag, flags
341  47, 23, 22, 22, 0x05,
342 
343  0 // eod
344 };
345 
347  "QDBusAdaptorConnector\0\0obj,metaobject,sid,args\0"
348  "relaySignal(QObject*,const QMetaObject*,int,QVariantList)\0\0relaySlot()\0"
349  "polish()\0"
350 };
351 
355 };
356 
358 {
359  return &staticMetaObject;
360 }
361 
362 void *QDBusAdaptorConnector::qt_metacast(const char *_clname)
363 {
364  if (!_clname) return 0;
365  if (!strcmp(_clname, qt_meta_stringdata_QDBusAdaptorConnector))
366  return static_cast<void*>(const_cast<QDBusAdaptorConnector*>(this));
367  return QObject::qt_metacast(_clname);
368 }
369 
370 int QDBusAdaptorConnector::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
371 {
372  _id = QObject::qt_metacall(_c, _id, _a);
373  if (_id < 0)
374  return _id;
375  if (_c == QMetaObject::InvokeMetaMethod) {
376  switch (_id) {
377  case 0: relaySlot(_a); break; // HAND EDIT: add the _a parameter
378  case 1: polish(); break;
379  case 2: relaySignal((*reinterpret_cast< QObject*(*)>(_a[1])),(*reinterpret_cast< const QMetaObject*(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3])),(*reinterpret_cast< const QVariantList(*)>(_a[4]))); break;
380  }
381  _id -= 3;
382  }
383  return _id;
384 }
385 
386 // SIGNAL 0
387 void QDBusAdaptorConnector::relaySignal(QObject * _t1, const QMetaObject * _t2, int _t3, const QVariantList & _t4)
388 {
389  void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)), const_cast<void*>(reinterpret_cast<const void*>(&_t3)), const_cast<void*>(reinterpret_cast<const void*>(&_t4)) };
391 }
392 
394 
395 #endif // QT_NO_DBUS
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
double d
Definition: qnumeric_p.h:62
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:304
static bool connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type=0, int *types=0)
Definition: qobject.cpp:3194
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QDBusAdaptorConnector * qDBusFindAdaptorConnector(QObject *obj)
static QByteArray normalizedSignature(const char *method)
Normalizes the signature of the given method.
T * data() const
Returns the value of the pointer referenced by this object.
#define it(className, varName)
The QDBusAbstractAdaptor class is the base class of D-Bus adaptor classes.
QDBusAdaptorConnector * qDBusCreateAdaptorConnector(QObject *obj)
void setAutoRelaySignals(bool enable)
Toggles automatic signal relaying from the real object (see object()).
QMetaClassInfo classInfo(int index) const
Returns the meta-data for the item of class information with the given index.
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
void disconnectAllSignals(QObject *object)
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qlist.h:269
static const QMetaObject staticMetaObject
This variable stores the meta-object for the class.
Definition: qobject.h:128
~QDBusAbstractAdaptor()
Destroys the adaptor.
bool autoRelaySignals() const
Returns true if automatic signal relaying from the real object (see object()) is enabled, otherwiser returns false.
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
QByteArray & prepend(char c)
Prepends the character ch to this byte array.
The QString class provides a Unicode character string.
Definition: qstring.h:83
T * qobject_cast(QObject *object)
Definition: qobject.h:375
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
const char * value() const
Returns the value of this item.
Sender * currentSender
Definition: qobject_p.h:200
iterator Iterator
Qt-style synonym for QVector::iterator.
Definition: qvector.h:278
const char * className
Definition: qwizard.cpp:137
void connectAllSignals(QObject *object)
int qDBusParametersForMethod(const QMetaMethod &mm, QList< int > &metaTypes)
Definition: qdbusmisc.cpp:137
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the vector...
Definition: qvector.h:250
QDBusAdaptorConnector(QObject *parent)
static QThread * currentThread()
Returns a pointer to a QThread which manages the currently executing thread.
Definition: qthread.cpp:419
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static QIntfbScreen * connected
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
static int message
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
#define QCLASSINFO_DBUS_INTERFACE
Q_CORE_EXPORT void qWarning(const char *,...)
unsigned int uint
Definition: qglobal.h:996
QDBusAbstractAdaptor(QObject *parent)
Constructs a QDBusAbstractAdaptor with obj as the parent object.
static bool disconnect(const QObject *sender, int signal_index, const QObject *receiver, int method_index)
Definition: qobject.cpp:3276
int indexOfSignal(const char *signal) const
Finds signal and returns its index; otherwise returns -1.
void qSort(RandomAccessIterator start, RandomAccessIterator end)
Definition: qalgorithms.h:177
MethodType methodType() const
Returns the type of this method (signal, slot, or method).
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Disconnects signal in object sender from method in object receiver.
Definition: qobject.cpp:2895
#define QSIGNAL_CODE
Definition: qobjectdefs.h:244
Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
Definition: qalgorithms.h:227
static const struct @32 types[]
iterator begin()
Returns an STL-style iterator pointing to the first item in the vector.
Definition: qvector.h:247
static const uint qt_meta_data_QDBusAdaptorConnector[]
The QMetaClassInfo class provides additional information about a class.
Definition: qmetaobject.h:224
static void activate(QObject *sender, int signal_index, void **argv)
Definition: qobject.cpp:3690
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
static const char qt_meta_stringdata_QDBusAdaptorConnector[]
const_iterator ConstIterator
Qt-style synonym for QList::const_iterator.
Definition: qlist.h:279
const char * className() const
Returns the class name.
Definition: qobjectdefs.h:491
QString objectName() const
static void saveIntrospectionXml(QDBusAbstractAdaptor *adaptor, const QString &xml)
const QObjectList & children() const
Returns a list of child objects.
Definition: qobject.h:197
void relaySignal(QObject *obj, const QMetaObject *metaObject, int sid, const QVariantList &args)
#define Q_LIKELY(x)
Hints to the compiler that the enclosed condition, expr, is likely to evaluate to true...
Definition: qglobal.h:820
QScopedPointer< QObjectData > d_ptr
Definition: qobject.h:320
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(0), 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())
Invokes the member (a signal or a slot name) on the object obj.
QMetaMethod method(int index) const
Returns the meta-data for the method with the given index.
int qstrcmp(const QByteArray &str1, const char *str2)
Definition: qbytearray.cpp:336
const char * signature() const
Returns the signature of this method (e.g., setValue(double)).
QThread * thread() const
Returns the thread in which the object lives.
Definition: qobject.cpp:1419
void relay(QObject *sender, int id, void **)
static const KeyPair *const end
#define qPrintable(string)
Definition: qglobal.h:1750
int indexOfClassInfo(const char *name) const
Finds class information item name and returns its index; otherwise returns -1.
int methodCount() const
Returns the number of methods known to the meta-object system in this class, including the number of ...
The QMetaMethod class provides meta-data about a member function.
Definition: qmetaobject.h:56
virtual const QMetaObject * metaObject() const
Returns a pointer to the meta-object of this object.
static QString retrieveIntrospectionXml(QDBusAbstractAdaptor *adaptor)
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:272
void addAdaptor(QDBusAbstractAdaptor *adaptor)