Index: trunk/src/dbus/qdbusinterface.cpp
===================================================================
--- trunk/src/dbus/qdbusinterface.cpp	(revision 5)
+++ trunk/src/dbus/qdbusinterface.cpp	(revision 561)
@@ -2,5 +2,6 @@
 **
 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
 **
 ** This file is part of the QtDBus module of the Qt Toolkit.
@@ -21,8 +22,7 @@
 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 **
 ** GNU General Public License Usage
@@ -34,6 +34,6 @@
 ** met: http://www.gnu.org/copyleft/gpl.html.
 **
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
 ** $QT_END_LICENSE$
 **
@@ -42,5 +42,5 @@
 #include "qdbusinterface.h"
 
-#include <qdbus_symbols_p.h>
+#include "qdbus_symbols_p.h"
 #include <QtCore/qpointer.h>
 #include <QtCore/qstringlist.h>
@@ -52,4 +52,100 @@
 QT_BEGIN_NAMESPACE
 
+static void copyArgument(void *to, int id, const QVariant &arg)
+{
+    if (id == arg.userType()) {
+        switch (id) {
+        case QVariant::Bool:
+            *reinterpret_cast<bool *>(to) = arg.toBool();
+            return;
+
+        case QMetaType::UChar:
+            *reinterpret_cast<uchar *>(to) = arg.value<uchar>();
+            return;
+
+        case QMetaType::Short:
+            *reinterpret_cast<short *>(to) = arg.value<short>();
+            return;
+
+        case QMetaType::UShort:
+            *reinterpret_cast<ushort *>(to) = arg.value<ushort>();
+            return;
+
+        case QVariant::Int:
+            *reinterpret_cast<int *>(to) = arg.toInt();
+            return;
+
+        case QVariant::UInt:
+            *reinterpret_cast<uint *>(to) = arg.toUInt();
+            return;
+
+        case QVariant::LongLong:
+            *reinterpret_cast<qlonglong *>(to) = arg.toLongLong();
+            return;
+
+        case QVariant::ULongLong:
+            *reinterpret_cast<qulonglong *>(to) = arg.toULongLong();
+            return;
+
+        case QVariant::Double:
+            *reinterpret_cast<double *>(to) = arg.toDouble();
+            return;
+
+        case QVariant::String:
+            *reinterpret_cast<QString *>(to) = arg.toString();
+            return;
+
+        case QVariant::ByteArray:
+            *reinterpret_cast<QByteArray *>(to) = arg.toByteArray();
+            return;
+
+        case QVariant::StringList:
+            *reinterpret_cast<QStringList *>(to) = arg.toStringList();
+            return;
+        }
+
+        if (id == QDBusMetaTypeId::variant) {
+            *reinterpret_cast<QDBusVariant *>(to) = arg.value<QDBusVariant>();
+            return;
+        } else if (id == QDBusMetaTypeId::objectpath) {
+            *reinterpret_cast<QDBusObjectPath *>(to) = arg.value<QDBusObjectPath>();
+            return;
+        } else if (id == QDBusMetaTypeId::signature) {
+            *reinterpret_cast<QDBusSignature *>(to) = arg.value<QDBusSignature>();
+            return;
+        }
+
+        // those above are the only types possible
+        // the demarshaller code doesn't demarshall anything else
+        qFatal("Found a decoded basic type in a D-Bus reply that shouldn't be there");
+    }
+
+    // if we got here, it's either an un-dermarshalled type or a mismatch
+    if (arg.userType() != QDBusMetaTypeId::argument) {
+        // it's a mismatch
+        //qWarning?
+        return;
+    }
+
+    // is this type registered?
+    const char *userSignature = QDBusMetaType::typeToSignature(id);
+    if (!userSignature || !*userSignature) {
+        // type not registered
+        //qWarning?
+        return;
+    }
+
+    // is it the same signature?
+    QDBusArgument dbarg = arg.value<QDBusArgument>();
+    if (dbarg.currentSignature() != QLatin1String(userSignature)) {
+        // not the same signature, another mismatch
+        //qWarning?
+        return;
+    }
+
+    // we can demarshall
+    QDBusMetaType::demarshall(dbarg, id, to);
+}
+
 QDBusInterfacePrivate::QDBusInterfacePrivate(const QString &serv, const QString &p,
                                              const QString &iface, const QDBusConnection &con)
@@ -62,5 +158,7 @@
         if (!metaObject) {
             // creation failed, somehow
-            isValid = false;
+            // most common causes are that the service doesn't exist or doesn't support introspection
+            // those are not fatal errors, so we continue working
+
             if (!lastError.isValid())
                 lastError = QDBusError(QDBusError::InternalError, QLatin1String("Unknown error"));
@@ -137,5 +235,5 @@
 const QMetaObject *QDBusInterface::metaObject() const
 {
-    return d_func()->isValid ? d_func()->metaObject : &QDBusAbstractInterface::staticMetaObject;
+    return d_func()->metaObject ? d_func()->metaObject : &QDBusAbstractInterface::staticMetaObject;
 }
 
@@ -187,43 +285,37 @@
             // we will assume that the input arguments were passed correctly
             QVariantList args;
-            for (int i = 1; i <= inputTypesCount; ++i)
+            int i = 1;
+            for ( ; i <= inputTypesCount; ++i)
                 args << QVariant(inputTypes[i], argv[i]);
 
             // make the call
-            QPointer<QDBusInterface> qq = q;
             QDBusMessage reply = q->callWithArgumentList(QDBus::Block, methodName, args);
-            args.clear();
-
-            // we ignore return values
-
-            // access to "this" or to "q" below this point must check for "qq"
-            // we may have been deleted!
-
-            if (!qq.isNull())
-                lastError = reply;
+
+            if (reply.type() == QDBusMessage::ReplyMessage) {
+                // attempt to demarshall the return values
+                args = reply.arguments();
+                QVariantList::ConstIterator it = args.constBegin();
+                const int *outputTypes = metaObject->outputTypesForMethod(id);
+                int outputTypesCount = *outputTypes++;
+
+                if (*mm.typeName()) {
+                    // this method has a return type
+                    if (argv[0] && it != args.constEnd())
+                        copyArgument(argv[0], *outputTypes++, *it);
+
+                    // skip this argument even if we didn't copy it
+                    --outputTypesCount;
+                    ++it;
+                }
+
+                for (int j = 0; j < outputTypesCount && it != args.constEnd(); ++i, ++j, ++it) {
+                    copyArgument(argv[i], outputTypes[j], *it);
+                }
+            }
 
             // done
+            lastError = reply;
             return -1;
         }
-    } else if (c == QMetaObject::ReadProperty) {
-        // Qt doesn't support non-readable properties
-        // we have to re-check
-        QMetaProperty mp = metaObject->property(id + metaObject->propertyOffset());
-        if (!mp.isReadable())
-            return -1;          // don't read
-
-        QVariant *value = reinterpret_cast<QVariant*>(argv[1]);
-        argv[1] = 0;
-        *value = property(mp);
-
-        return -1;              // handled, error or not
-    } else if (c == QMetaObject::WriteProperty) {
-        // QMetaProperty::write has already checked that we're writable
-        // it has also checked that the type is right
-        QVariant *value = reinterpret_cast<QVariant *>(argv[1]);
-        QMetaProperty mp = metaObject->property(id + metaObject->propertyOffset());
-
-        setProperty(mp, *value);
-        return -1;
     }
     return id;
