|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtDBus module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qdbusabstractinterface.h" |
|
43 #include "qdbusabstractinterface_p.h" |
|
44 |
|
45 #include "qdbusargument.h" |
|
46 #include "qdbuspendingcall.h" |
|
47 #include "qdbusmessage_p.h" |
|
48 #include "qdbusmetaobject_p.h" |
|
49 #include "qdbusmetatype_p.h" |
|
50 #include "qdbusutil_p.h" |
|
51 |
|
52 #include <qdebug.h> |
|
53 |
|
54 QT_BEGIN_NAMESPACE |
|
55 |
|
56 static QDBusError checkIfValid(const QString &service, const QString &path, |
|
57 const QString &interface, bool isDynamic) |
|
58 { |
|
59 // We should be throwing exceptions here... oh well |
|
60 QDBusError error; |
|
61 |
|
62 // dynamic interfaces (QDBusInterface) can have empty interfaces, but not service and object paths |
|
63 // non-dynamic is the opposite: service and object paths can be empty, but not the interface |
|
64 if (!isDynamic) { |
|
65 // use assertion here because this should never happen, at all |
|
66 Q_ASSERT_X(!interface.isEmpty(), "QDBusAbstractInterface", "Interface name cannot be empty"); |
|
67 } |
|
68 if (!QDBusUtil::checkBusName(service, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error)) |
|
69 return error; |
|
70 if (!QDBusUtil::checkObjectPath(path, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error)) |
|
71 return error; |
|
72 if (!QDBusUtil::checkInterfaceName(interface, QDBusUtil::EmptyAllowed, &error)) |
|
73 return error; |
|
74 |
|
75 // no error |
|
76 return QDBusError(); |
|
77 } |
|
78 |
|
79 QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv, |
|
80 const QString &p, |
|
81 const QString &iface, |
|
82 const QDBusConnection& con, |
|
83 bool isDynamic) |
|
84 : connection(con), service(serv), path(p), interface(iface), |
|
85 lastError(checkIfValid(serv, p, iface, isDynamic)), |
|
86 isValid(!lastError.isValid()) |
|
87 { |
|
88 if (!isValid) |
|
89 return; |
|
90 |
|
91 if (!connection.isConnected()) { |
|
92 lastError = QDBusError(QDBusError::Disconnected, |
|
93 QLatin1String("Not connected to D-Bus server")); |
|
94 } else if (!service.isEmpty()) { |
|
95 currentOwner = connectionPrivate()->getNameOwner(service); // verify the name owner |
|
96 if (currentOwner.isEmpty()) { |
|
97 lastError = connectionPrivate()->lastError; |
|
98 } |
|
99 } |
|
100 } |
|
101 |
|
102 bool QDBusAbstractInterfacePrivate::canMakeCalls() const |
|
103 { |
|
104 // recheck only if we have a wildcard (i.e. empty) service or path |
|
105 // if any are empty, set the error message according to QDBusUtil |
|
106 if (service.isEmpty()) |
|
107 return QDBusUtil::checkBusName(service, QDBusUtil::EmptyNotAllowed, &lastError); |
|
108 if (path.isEmpty()) |
|
109 return QDBusUtil::checkObjectPath(path, QDBusUtil::EmptyNotAllowed, &lastError); |
|
110 return true; |
|
111 } |
|
112 |
|
113 void QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp, QVariant &where) const |
|
114 { |
|
115 if (!isValid || !canMakeCalls()) { // can't make calls |
|
116 where.clear(); |
|
117 return; |
|
118 } |
|
119 |
|
120 // is this metatype registered? |
|
121 const char *expectedSignature = ""; |
|
122 if (mp.type() != 0xff) { |
|
123 expectedSignature = QDBusMetaType::typeToSignature(where.userType()); |
|
124 if (expectedSignature == 0) { |
|
125 qWarning("QDBusAbstractInterface: type %s must be registered with QtDBus before it can be " |
|
126 "used to read property %s.%s", |
|
127 mp.typeName(), qPrintable(interface), mp.name()); |
|
128 lastError = QDBusError(QDBusError::Failed, |
|
129 QString::fromLatin1("Unregistered type %1 cannot be handled") |
|
130 .arg(QLatin1String(mp.typeName()))); |
|
131 where.clear(); |
|
132 return; |
|
133 } |
|
134 } |
|
135 |
|
136 // try to read this property |
|
137 QDBusMessage msg = QDBusMessage::createMethodCall(service, path, |
|
138 QLatin1String(DBUS_INTERFACE_PROPERTIES), |
|
139 QLatin1String("Get")); |
|
140 QDBusMessagePrivate::setParametersValidated(msg, true); |
|
141 msg << interface << QString::fromUtf8(mp.name()); |
|
142 QDBusMessage reply = connection.call(msg, QDBus::Block); |
|
143 |
|
144 if (reply.type() != QDBusMessage::ReplyMessage) { |
|
145 lastError = reply; |
|
146 where.clear(); |
|
147 return; |
|
148 } |
|
149 if (reply.signature() != QLatin1String("v")) { |
|
150 QString errmsg = QLatin1String("Invalid signature `%1' in return from call to " |
|
151 DBUS_INTERFACE_PROPERTIES); |
|
152 lastError = QDBusError(QDBusError::InvalidSignature, errmsg.arg(reply.signature())); |
|
153 where.clear(); |
|
154 return; |
|
155 } |
|
156 |
|
157 QByteArray foundSignature; |
|
158 const char *foundType = 0; |
|
159 QVariant value = qvariant_cast<QDBusVariant>(reply.arguments().at(0)).variant(); |
|
160 |
|
161 if (value.userType() == where.userType() || mp.type() == 0xff |
|
162 || (expectedSignature[0] == 'v' && expectedSignature[1] == '\0')) { |
|
163 // simple match |
|
164 where = value; |
|
165 return; |
|
166 } |
|
167 |
|
168 if (value.userType() == qMetaTypeId<QDBusArgument>()) { |
|
169 QDBusArgument arg = qvariant_cast<QDBusArgument>(value); |
|
170 |
|
171 foundType = "user type"; |
|
172 foundSignature = arg.currentSignature().toLatin1(); |
|
173 if (foundSignature == expectedSignature) { |
|
174 // signatures match, we can demarshall |
|
175 QDBusMetaType::demarshall(arg, where.userType(), where.data()); |
|
176 return; |
|
177 } |
|
178 } else { |
|
179 foundType = value.typeName(); |
|
180 foundSignature = QDBusMetaType::typeToSignature(value.userType()); |
|
181 } |
|
182 |
|
183 // there was an error... |
|
184 QString errmsg = QLatin1String("Unexpected `%1' (%2) when retrieving property `%3.%4' " |
|
185 "(expected type `%5' (%6))"); |
|
186 lastError = QDBusError(QDBusError::InvalidSignature, |
|
187 errmsg.arg(QString::fromLatin1(foundType), |
|
188 QString::fromLatin1(foundSignature), |
|
189 interface, |
|
190 QString::fromUtf8(mp.name()), |
|
191 QString::fromLatin1(mp.typeName()), |
|
192 QString::fromLatin1(expectedSignature))); |
|
193 where.clear(); |
|
194 return; |
|
195 } |
|
196 |
|
197 bool QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const QVariant &value) |
|
198 { |
|
199 if (!isValid || !canMakeCalls()) // can't make calls |
|
200 return false; |
|
201 |
|
202 // send the value |
|
203 QDBusMessage msg = QDBusMessage::createMethodCall(service, path, |
|
204 QLatin1String(DBUS_INTERFACE_PROPERTIES), |
|
205 QLatin1String("Set")); |
|
206 QDBusMessagePrivate::setParametersValidated(msg, true); |
|
207 msg << interface << QString::fromUtf8(mp.name()) << qVariantFromValue(QDBusVariant(value)); |
|
208 QDBusMessage reply = connection.call(msg, QDBus::Block); |
|
209 |
|
210 if (reply.type() != QDBusMessage::ReplyMessage) { |
|
211 lastError = reply; |
|
212 return false; |
|
213 } |
|
214 return true; |
|
215 } |
|
216 |
|
217 void QDBusAbstractInterfacePrivate::_q_serviceOwnerChanged(const QString &name, |
|
218 const QString &oldOwner, |
|
219 const QString &newOwner) |
|
220 { |
|
221 Q_UNUSED(oldOwner); |
|
222 //qDebug() << "QDBusAbstractInterfacePrivate serviceOwnerChanged" << name << oldOwner << newOwner; |
|
223 if (name == service) { |
|
224 currentOwner = newOwner; |
|
225 } |
|
226 } |
|
227 |
|
228 QDBusAbstractInterfaceBase::QDBusAbstractInterfaceBase(QDBusAbstractInterfacePrivate &d, QObject *parent) |
|
229 : QObject(d, parent) |
|
230 { |
|
231 } |
|
232 |
|
233 int QDBusAbstractInterfaceBase::qt_metacall(QMetaObject::Call _c, int _id, void **_a) |
|
234 { |
|
235 int saved_id = _id; |
|
236 _id = QObject::qt_metacall(_c, _id, _a); |
|
237 if (_id < 0) |
|
238 return _id; |
|
239 |
|
240 if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty) { |
|
241 QMetaProperty mp = metaObject()->property(saved_id); |
|
242 int &status = *reinterpret_cast<int *>(_a[2]); |
|
243 QVariant &variant = *reinterpret_cast<QVariant *>(_a[1]); |
|
244 |
|
245 if (_c == QMetaObject::WriteProperty) { |
|
246 status = d_func()->setProperty(mp, variant) ? 1 : 0; |
|
247 } else { |
|
248 d_func()->property(mp, variant); |
|
249 status = variant.isValid() ? 1 : 0; |
|
250 } |
|
251 _id = -1; |
|
252 } |
|
253 return _id; |
|
254 } |
|
255 |
|
256 /*! |
|
257 \class QDBusAbstractInterface |
|
258 \inmodule QtDBus |
|
259 \since 4.2 |
|
260 |
|
261 \brief The QDBusAbstractInterface class is the base class for all D-Bus interfaces in the QtDBus binding, allowing access to remote interfaces |
|
262 |
|
263 Generated-code classes also derive from QDBusAbstractInterface, |
|
264 all methods described here are also valid for generated-code |
|
265 classes. In addition to those described here, generated-code |
|
266 classes provide member functions for the remote methods, which |
|
267 allow for compile-time checking of the correct parameters and |
|
268 return values, as well as property type-matching and signal |
|
269 parameter-matching. |
|
270 |
|
271 \sa {qdbusxml2cpp.html}{The QDBus compiler}, QDBusInterface |
|
272 */ |
|
273 |
|
274 /*! |
|
275 \internal |
|
276 This is the constructor called from QDBusInterface::QDBusInterface. |
|
277 */ |
|
278 QDBusAbstractInterface::QDBusAbstractInterface(QDBusAbstractInterfacePrivate &d, QObject *parent) |
|
279 : QDBusAbstractInterfaceBase(d, parent) |
|
280 { |
|
281 // keep track of the service owner |
|
282 if (!d_func()->currentOwner.isEmpty()) |
|
283 QObject::connect(d_func()->connectionPrivate(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), |
|
284 this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); |
|
285 } |
|
286 |
|
287 /*! |
|
288 \internal |
|
289 This is the constructor called from static classes derived from |
|
290 QDBusAbstractInterface (i.e., those generated by dbusxml2cpp). |
|
291 */ |
|
292 QDBusAbstractInterface::QDBusAbstractInterface(const QString &service, const QString &path, |
|
293 const char *interface, const QDBusConnection &con, |
|
294 QObject *parent) |
|
295 : QDBusAbstractInterfaceBase(*new QDBusAbstractInterfacePrivate(service, path, QString::fromLatin1(interface), |
|
296 con, false), parent) |
|
297 { |
|
298 // keep track of the service owner |
|
299 if (d_func()->connection.isConnected()) |
|
300 QObject::connect(d_func()->connectionPrivate(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), |
|
301 this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); |
|
302 } |
|
303 |
|
304 /*! |
|
305 Releases this object's resources. |
|
306 */ |
|
307 QDBusAbstractInterface::~QDBusAbstractInterface() |
|
308 { |
|
309 } |
|
310 |
|
311 /*! |
|
312 Returns true if this is a valid reference to a remote object. It returns false if |
|
313 there was an error during the creation of this interface (for instance, if the remote |
|
314 application does not exist). |
|
315 |
|
316 Note: when dealing with remote objects, it is not always possible to determine if it |
|
317 exists when creating a QDBusInterface. |
|
318 */ |
|
319 bool QDBusAbstractInterface::isValid() const |
|
320 { |
|
321 return !d_func()->currentOwner.isEmpty(); |
|
322 } |
|
323 |
|
324 /*! |
|
325 Returns the connection this interface is assocated with. |
|
326 */ |
|
327 QDBusConnection QDBusAbstractInterface::connection() const |
|
328 { |
|
329 return d_func()->connection; |
|
330 } |
|
331 |
|
332 /*! |
|
333 Returns the name of the service this interface is associated with. |
|
334 */ |
|
335 QString QDBusAbstractInterface::service() const |
|
336 { |
|
337 return d_func()->service; |
|
338 } |
|
339 |
|
340 /*! |
|
341 Returns the object path that this interface is associated with. |
|
342 */ |
|
343 QString QDBusAbstractInterface::path() const |
|
344 { |
|
345 return d_func()->path; |
|
346 } |
|
347 |
|
348 /*! |
|
349 Returns the name of this interface. |
|
350 */ |
|
351 QString QDBusAbstractInterface::interface() const |
|
352 { |
|
353 return d_func()->interface; |
|
354 } |
|
355 |
|
356 /*! |
|
357 Returns the error the last operation produced, or an invalid error if the last operation did not |
|
358 produce an error. |
|
359 */ |
|
360 QDBusError QDBusAbstractInterface::lastError() const |
|
361 { |
|
362 return d_func()->lastError; |
|
363 } |
|
364 |
|
365 /*! |
|
366 Places a call to the remote method specified by \a method on this interface, using \a args as |
|
367 arguments. This function returns the message that was received as a reply, which can be a normal |
|
368 QDBusMessage::ReplyMessage (indicating success) or QDBusMessage::ErrorMessage (if the call |
|
369 failed). The \a mode parameter specifies how this call should be placed. |
|
370 |
|
371 If the call succeeds, lastError() will be cleared; otherwise, it will contain the error this |
|
372 call produced. |
|
373 |
|
374 Normally, you should place calls using call(). |
|
375 |
|
376 \warning If you use \c UseEventLoop, your code must be prepared to deal with any reentrancy: |
|
377 other method calls and signals may be delivered before this function returns, as well |
|
378 as other Qt queued signals and events. |
|
379 |
|
380 \threadsafe |
|
381 */ |
|
382 QDBusMessage QDBusAbstractInterface::callWithArgumentList(QDBus::CallMode mode, |
|
383 const QString& method, |
|
384 const QList<QVariant>& args) |
|
385 { |
|
386 Q_D(QDBusAbstractInterface); |
|
387 |
|
388 if (!d->isValid || !d->canMakeCalls()) |
|
389 return QDBusMessage::createError(d->lastError); |
|
390 |
|
391 QString m = method; |
|
392 // split out the signature from the method |
|
393 int pos = method.indexOf(QLatin1Char('.')); |
|
394 if (pos != -1) |
|
395 m.truncate(pos); |
|
396 |
|
397 if (mode == QDBus::AutoDetect) { |
|
398 // determine if this a sync or async call |
|
399 mode = QDBus::Block; |
|
400 const QMetaObject *mo = metaObject(); |
|
401 QByteArray match = m.toLatin1() + '('; |
|
402 |
|
403 for (int i = staticMetaObject.methodCount(); i < mo->methodCount(); ++i) { |
|
404 QMetaMethod mm = mo->method(i); |
|
405 if (QByteArray(mm.signature()).startsWith(match)) { |
|
406 // found a method with the same name as what we're looking for |
|
407 // hopefully, nobody is overloading asynchronous and synchronous methods with |
|
408 // the same name |
|
409 |
|
410 QList<QByteArray> tags = QByteArray(mm.tag()).split(' '); |
|
411 if (tags.contains("Q_NOREPLY")) |
|
412 mode = QDBus::NoBlock; |
|
413 |
|
414 break; |
|
415 } |
|
416 } |
|
417 } |
|
418 |
|
419 // qDebug() << "QDBusAbstractInterface" << "Service" << service() << "Path:" << path(); |
|
420 QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), m); |
|
421 QDBusMessagePrivate::setParametersValidated(msg, true); |
|
422 msg.setArguments(args); |
|
423 |
|
424 QDBusMessage reply = d->connection.call(msg, mode); |
|
425 d->lastError = reply; // will clear if reply isn't an error |
|
426 |
|
427 // ensure that there is at least one element |
|
428 if (reply.arguments().isEmpty()) |
|
429 reply << QVariant(); |
|
430 |
|
431 return reply; |
|
432 } |
|
433 |
|
434 /*! |
|
435 \since 4.5 |
|
436 Places a call to the remote method specified by \a method on this |
|
437 interface, using \a args as arguments. This function returns a |
|
438 QDBusPendingCall object that can be used to track the status of the |
|
439 reply and access its contents once it has arrived. |
|
440 |
|
441 Normally, you should place calls using asyncCall(). |
|
442 |
|
443 \threadsafe |
|
444 */ |
|
445 QDBusPendingCall QDBusAbstractInterface::asyncCallWithArgumentList(const QString& method, |
|
446 const QList<QVariant>& args) |
|
447 { |
|
448 Q_D(QDBusAbstractInterface); |
|
449 |
|
450 if (!d->isValid || !d->canMakeCalls()) |
|
451 return QDBusPendingCall::fromError(d->lastError); |
|
452 |
|
453 QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), method); |
|
454 QDBusMessagePrivate::setParametersValidated(msg, true); |
|
455 msg.setArguments(args); |
|
456 return d->connection.asyncCall(msg); |
|
457 } |
|
458 |
|
459 /*! |
|
460 Places a call to the remote method specified by \a method |
|
461 on this interface, using \a args as arguments. This function |
|
462 returns immediately after queueing the call. The reply from |
|
463 the remote function is delivered to the \a returnMethod on |
|
464 object \a receiver. If an error occurs, the \a errorMethod |
|
465 on object \a receiver is called instead. |
|
466 |
|
467 This function returns true if the queueing succeeds. It does |
|
468 not indicate that the executed call succeeded. If it fails, |
|
469 the \a errorMethod is called. If the queueing failed, this |
|
470 function returns false and no slot will be called. |
|
471 |
|
472 The \a returnMethod must have as its parameters the types returned |
|
473 by the function call. Optionally, it may have a QDBusMessage |
|
474 parameter as its last or only parameter. The \a errorMethod must |
|
475 have a QDBusError as its only parameter. |
|
476 |
|
477 \since 4.3 |
|
478 \sa QDBusError, QDBusMessage |
|
479 */ |
|
480 bool QDBusAbstractInterface::callWithCallback(const QString &method, |
|
481 const QList<QVariant> &args, |
|
482 QObject *receiver, |
|
483 const char *returnMethod, |
|
484 const char *errorMethod) |
|
485 { |
|
486 Q_D(QDBusAbstractInterface); |
|
487 |
|
488 if (!d->isValid || !d->canMakeCalls()) |
|
489 return false; |
|
490 |
|
491 QDBusMessage msg = QDBusMessage::createMethodCall(service(), |
|
492 path(), |
|
493 interface(), |
|
494 method); |
|
495 QDBusMessagePrivate::setParametersValidated(msg, true); |
|
496 msg.setArguments(args); |
|
497 |
|
498 d->lastError = 0; |
|
499 return d->connection.callWithCallback(msg, |
|
500 receiver, |
|
501 returnMethod, |
|
502 errorMethod); |
|
503 } |
|
504 |
|
505 /*! |
|
506 \overload |
|
507 |
|
508 This function is deprecated. Please use the overloaded version. |
|
509 |
|
510 Places a call to the remote method specified by \a method |
|
511 on this interface, using \a args as arguments. This function |
|
512 returns immediately after queueing the call. The reply from |
|
513 the remote function or any errors emitted by it are delivered |
|
514 to the \a slot slot on object \a receiver. |
|
515 |
|
516 This function returns true if the queueing succeeded: it does |
|
517 not indicate that the call succeeded. If it failed, the slot |
|
518 will be called with an error message. lastError() will not be |
|
519 set under those circumstances. |
|
520 |
|
521 \sa QDBusError, QDBusMessage |
|
522 */ |
|
523 bool QDBusAbstractInterface::callWithCallback(const QString &method, |
|
524 const QList<QVariant> &args, |
|
525 QObject *receiver, |
|
526 const char *slot) |
|
527 { |
|
528 return callWithCallback(method, args, receiver, slot, 0); |
|
529 } |
|
530 |
|
531 /*! |
|
532 \internal |
|
533 Catch signal connections. |
|
534 */ |
|
535 void QDBusAbstractInterface::connectNotify(const char *signal) |
|
536 { |
|
537 // someone connecting to one of our signals |
|
538 Q_D(QDBusAbstractInterface); |
|
539 if (!d->isValid) |
|
540 return; |
|
541 |
|
542 // we end up recursing here, so optimise away |
|
543 if (qstrcmp(signal + 1, "destroyed(QObject*)") == 0) |
|
544 return; |
|
545 |
|
546 QDBusConnectionPrivate *conn = d->connectionPrivate(); |
|
547 if (conn) |
|
548 conn->connectRelay(d->service, d->currentOwner, d->path, d->interface, |
|
549 this, signal); |
|
550 } |
|
551 |
|
552 /*! |
|
553 \internal |
|
554 Catch signal disconnections. |
|
555 */ |
|
556 void QDBusAbstractInterface::disconnectNotify(const char *signal) |
|
557 { |
|
558 // someone disconnecting from one of our signals |
|
559 Q_D(QDBusAbstractInterface); |
|
560 if (!d->isValid) |
|
561 return; |
|
562 |
|
563 QDBusConnectionPrivate *conn = d->connectionPrivate(); |
|
564 if (conn) |
|
565 conn->disconnectRelay(d->service, d->currentOwner, d->path, d->interface, |
|
566 this, signal); |
|
567 } |
|
568 |
|
569 /*! |
|
570 \internal |
|
571 Get the value of the property \a propname. |
|
572 */ |
|
573 QVariant QDBusAbstractInterface::internalPropGet(const char *propname) const |
|
574 { |
|
575 // assume this property exists and is readable |
|
576 // we're only called from generated code anyways |
|
577 |
|
578 return property(propname); |
|
579 } |
|
580 |
|
581 /*! |
|
582 \internal |
|
583 Set the value of the property \a propname to \a value. |
|
584 */ |
|
585 void QDBusAbstractInterface::internalPropSet(const char *propname, const QVariant &value) |
|
586 { |
|
587 setProperty(propname, value); |
|
588 } |
|
589 |
|
590 /*! |
|
591 Calls the method \a method on this interface and passes the parameters to this function to the |
|
592 method. |
|
593 |
|
594 The parameters to \c call are passed on to the remote function via D-Bus as input |
|
595 arguments. Output arguments are returned in the QDBusMessage reply. If the reply is an error |
|
596 reply, lastError() will also be set to the contents of the error message. |
|
597 |
|
598 This function can be used with up to 8 parameters, passed in arguments \a arg1, \a arg2, |
|
599 \a arg3, \a arg4, \a arg5, \a arg6, \a arg7 and \a arg8. If you need more than 8 |
|
600 parameters or if you have a variable number of parameters to be passed, use |
|
601 callWithArgumentList(). |
|
602 |
|
603 It can be used the following way: |
|
604 |
|
605 \snippet doc/src/snippets/code/src_qdbus_qdbusabstractinterface.cpp 0 |
|
606 |
|
607 This example illustrates function calling with 0, 1 and 2 parameters and illustrates different |
|
608 parameter types passed in each (the first call to \c "ProcessWorkUnicode" will contain one |
|
609 Unicode string, the second call to \c "ProcessWork" will contain one string and one byte array). |
|
610 */ |
|
611 QDBusMessage QDBusAbstractInterface::call(const QString &method, const QVariant &arg1, |
|
612 const QVariant &arg2, |
|
613 const QVariant &arg3, |
|
614 const QVariant &arg4, |
|
615 const QVariant &arg5, |
|
616 const QVariant &arg6, |
|
617 const QVariant &arg7, |
|
618 const QVariant &arg8) |
|
619 { |
|
620 return call(QDBus::AutoDetect, method, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); |
|
621 } |
|
622 |
|
623 /*! |
|
624 \overload |
|
625 |
|
626 Calls the method \a method on this interface and passes the |
|
627 parameters to this function to the method. If \a mode is \c |
|
628 NoWaitForReply, then this function will return immediately after |
|
629 placing the call, without waiting for a reply from the remote |
|
630 method. Otherwise, \a mode indicates whether this function should |
|
631 activate the Qt Event Loop while waiting for the reply to arrive. |
|
632 |
|
633 This function can be used with up to 8 parameters, passed in arguments \a arg1, \a arg2, |
|
634 \a arg3, \a arg4, \a arg5, \a arg6, \a arg7 and \a arg8. If you need more than 8 |
|
635 parameters or if you have a variable number of parameters to be passed, use |
|
636 callWithArgumentList(). |
|
637 |
|
638 If this function reenters the Qt event loop in order to wait for the |
|
639 reply, it will exclude user input. During the wait, it may deliver |
|
640 signals and other method calls to your application. Therefore, it |
|
641 must be prepared to handle a reentrancy whenever a call is placed |
|
642 with call(). |
|
643 */ |
|
644 QDBusMessage QDBusAbstractInterface::call(QDBus::CallMode mode, const QString &method, |
|
645 const QVariant &arg1, |
|
646 const QVariant &arg2, |
|
647 const QVariant &arg3, |
|
648 const QVariant &arg4, |
|
649 const QVariant &arg5, |
|
650 const QVariant &arg6, |
|
651 const QVariant &arg7, |
|
652 const QVariant &arg8) |
|
653 { |
|
654 QList<QVariant> argList; |
|
655 int count = 0 + arg1.isValid() + arg2.isValid() + arg3.isValid() + arg4.isValid() + |
|
656 arg5.isValid() + arg6.isValid() + arg7.isValid() + arg8.isValid(); |
|
657 |
|
658 switch (count) { |
|
659 case 8: |
|
660 argList.prepend(arg8); |
|
661 case 7: |
|
662 argList.prepend(arg7); |
|
663 case 6: |
|
664 argList.prepend(arg6); |
|
665 case 5: |
|
666 argList.prepend(arg5); |
|
667 case 4: |
|
668 argList.prepend(arg4); |
|
669 case 3: |
|
670 argList.prepend(arg3); |
|
671 case 2: |
|
672 argList.prepend(arg2); |
|
673 case 1: |
|
674 argList.prepend(arg1); |
|
675 } |
|
676 |
|
677 return callWithArgumentList(mode, method, argList); |
|
678 } |
|
679 |
|
680 |
|
681 /*! |
|
682 \since 4.5 |
|
683 Calls the method \a method on this interface and passes the parameters to this function to the |
|
684 method. |
|
685 |
|
686 The parameters to \c call are passed on to the remote function via D-Bus as input |
|
687 arguments. The returned QDBusPendingCall object can be used to find out information about |
|
688 the reply. |
|
689 |
|
690 This function can be used with up to 8 parameters, passed in arguments \a arg1, \a arg2, |
|
691 \a arg3, \a arg4, \a arg5, \a arg6, \a arg7 and \a arg8. If you need more than 8 |
|
692 parameters or if you have a variable number of parameters to be passed, use |
|
693 asyncCallWithArgumentList(). |
|
694 |
|
695 It can be used the following way: |
|
696 |
|
697 \snippet doc/src/snippets/code/src_qdbus_qdbusabstractinterface.cpp 1 |
|
698 |
|
699 This example illustrates function calling with 0, 1 and 2 parameters and illustrates different |
|
700 parameter types passed in each (the first call to \c "ProcessWorkUnicode" will contain one |
|
701 Unicode string, the second call to \c "ProcessWork" will contain one string and one byte array). |
|
702 */ |
|
703 QDBusPendingCall QDBusAbstractInterface::asyncCall(const QString &method, const QVariant &arg1, |
|
704 const QVariant &arg2, |
|
705 const QVariant &arg3, |
|
706 const QVariant &arg4, |
|
707 const QVariant &arg5, |
|
708 const QVariant &arg6, |
|
709 const QVariant &arg7, |
|
710 const QVariant &arg8) |
|
711 { |
|
712 QList<QVariant> argList; |
|
713 int count = 0 + arg1.isValid() + arg2.isValid() + arg3.isValid() + arg4.isValid() + |
|
714 arg5.isValid() + arg6.isValid() + arg7.isValid() + arg8.isValid(); |
|
715 |
|
716 switch (count) { |
|
717 case 8: |
|
718 argList.prepend(arg8); |
|
719 case 7: |
|
720 argList.prepend(arg7); |
|
721 case 6: |
|
722 argList.prepend(arg6); |
|
723 case 5: |
|
724 argList.prepend(arg5); |
|
725 case 4: |
|
726 argList.prepend(arg4); |
|
727 case 3: |
|
728 argList.prepend(arg3); |
|
729 case 2: |
|
730 argList.prepend(arg2); |
|
731 case 1: |
|
732 argList.prepend(arg1); |
|
733 } |
|
734 |
|
735 return asyncCallWithArgumentList(method, argList); |
|
736 } |
|
737 |
|
738 /*! |
|
739 \internal |
|
740 */ |
|
741 QDBusMessage QDBusAbstractInterface::internalConstCall(QDBus::CallMode mode, |
|
742 const QString &method, |
|
743 const QList<QVariant> &args) const |
|
744 { |
|
745 // ### move the code here, and make the other functions call this |
|
746 return const_cast<QDBusAbstractInterface*>(this)->callWithArgumentList(mode, method, args); |
|
747 } |
|
748 |
|
749 QT_END_NAMESPACE |
|
750 |
|
751 #include "moc_qdbusabstractinterface.cpp" |