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