src/dbus/qdbusabstractinterface.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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"