File r785103.patch of Package libdbus-1-qt3-0

diff -ur libdbus-1-qt3-0.8.1/qdbusintegrator.cpp ../dbus-qt4-qt3backport/qdbusintegrator.cpp
--- libdbus-1-qt3-0.8.1/qdbusintegrator.cpp	2007-12-17 12:34:08.000000000 +0100
+++ ../dbus-qt4-qt3backport/qdbusintegrator.cpp	2008-03-13 10:28:54.000000000 +0100
@@ -121,7 +121,7 @@
     QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
 
     int flags = dbus_watch_get_flags(watch);
-    int fd = dbus_watch_get_fd(watch);
+    int fd = dbus_watch_get_unix_fd(watch);
 
     QDBusConnectionPrivate::Watcher watcher;
     if (flags & DBUS_WATCH_READABLE) {
@@ -163,7 +163,7 @@
     //qDebug("remove watch");
 
     QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
-    int fd = dbus_watch_get_fd(watch);
+    int fd = dbus_watch_get_unix_fd(watch);
 
     QDBusConnectionPrivate::WatcherHash::iterator it = d->watchers.find(fd);
     if (it != d->watchers.end())
@@ -205,7 +205,7 @@
     //qDebug("toggle watch");
 
     QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
-    int fd = dbus_watch_get_fd(watch);
+    int fd = dbus_watch_get_unix_fd(watch);
 
     QDBusConnectionPrivate::WatcherHash::iterator it = d->watchers.find(fd);
     if (it != d->watchers.end()) {
@@ -218,7 +218,7 @@
                 int flags = dbus_watch_get_flags(watch);
 
 //                 qDebug("toggle watch %d to %d (write: %d, read: %d)",
-//                         dbus_watch_get_fd(watch), enabled,
+//                         dbus_watch_get_unix_fd(watch), enabled,
 //                         flags & DBUS_WATCH_WRITABLE, flags & DBUS_WATCH_READABLE);
 
                 if (flags & DBUS_WATCH_READABLE && (*wit).read)
diff -ur libdbus-1-qt3-0.8.1/tools/dbusxml2qt3/classgen.cpp ../dbus-qt4-qt3backport/tools/dbusxml2qt3/classgen.cpp
--- libdbus-1-qt3-0.8.1/tools/dbusxml2qt3/classgen.cpp	2007-12-17 12:34:08.000000000 +0100
+++ ../dbus-qt4-qt3backport/tools/dbusxml2qt3/classgen.cpp	2008-03-13 10:28:54.000000000 +0100
@@ -38,6 +38,11 @@
         insert(key, true);
     }
 
+    void removeString(const QString& key)
+    {
+        erase(key);
+    }
+
     void insertStringList(const QStringList& list)
     {
         QStringList::const_iterator it    = list.begin();
@@ -194,6 +199,14 @@
             forwards.insertString("class QDomElement");
             if (!classData.signals.isEmpty())
                 forwards.insertString("class QString");
+            if (!classData.asyncMethods.isEmpty())
+            {
+                includes["Qt"].insertString("<qmap.h>");
+                forwards.erase("template <typename K, typename V> class QMap");
+
+                includes["qdbus"].insertString("<dbus/qdbusmessage.h>");
+                forwards.erase("class QDBusMessage");
+            }
             break;
 
         case Class::Proxy:
@@ -205,6 +218,11 @@
             forwards.insertString("class QString");
             if (!classData.properties.isEmpty())
                 forwards.insertString("class QDBusVariant");
+            if (!classData.asyncMethods.isEmpty())
+            {
+                includes["Qt"].insertString("<qmap.h>");
+                forwards.erase("template <typename K, typename V> class QMap");
+            }
             break;
 
         case Class::Node:
@@ -345,7 +363,7 @@
         stream << "#include \"" << (*it).name.lower() << ".h\"" << endl;
     }
 
-    stream << "#include \"introspectable.h\"" << endl;
+    stream << "#include \"introspectableinterface.h\"" << endl;
 
     stream << endl;
 }
@@ -442,7 +460,30 @@
 static void writeMethodDeclarations(const Class& classData, Class::Role role,
         QTextStream& stream)
 {
-    if (!classData.methods.isEmpty())
+    if (role == Class::Interface && !classData.asyncReplyMethods.isEmpty())
+    {
+        stream << "public:" << endl;
+
+        QValueList<Method>::const_iterator it =
+            classData.asyncReplyMethods.begin();
+        QValueList<Method>::const_iterator endIt =
+            classData.asyncReplyMethods.end();
+        for (; it != endIt; ++it)
+        {
+            Method method = *it;
+            method.name += "AsyncReply";
+
+            stream << "    virtual void ";
+            MethodGenerator::writeMethodDeclaration(method, false, false, stream);
+
+            stream << "    virtual void " << (*it).name
+                   << "AsyncError(int asyncCallId, const QDBusError& error);"
+                   << endl;
+            stream << endl;
+        }
+    }
+
+    if (!classData.methods.isEmpty() || !classData.asyncMethods.isEmpty())
     {
         bool pureVirtual = true;
         switch (role)
@@ -465,9 +506,35 @@
         QValueList<Method>::const_iterator endIt = classData.methods.end();
         for (; it != endIt; ++it)
         {
+            if ((*it).async) continue;
+
             stream << "    virtual bool ";
             MethodGenerator::writeMethodDeclaration(*it, pureVirtual, true, stream);
         }
+
+        it    = classData.asyncMethods.begin();
+        endIt = classData.asyncMethods.end();
+        for (; it != endIt; ++it)
+        {
+            Method method = *it;
+            method.name += "Async";
+
+            switch (role)
+            {
+                case Class::Interface:
+                    stream << "    virtual void ";
+                    MethodGenerator::writeMethodDeclaration(method, pureVirtual, false, stream);
+                    break;
+
+                case Class::Proxy:
+                    stream << "    virtual bool ";
+                    MethodGenerator::writeMethodDeclaration(method, pureVirtual, true, stream);
+                    break;
+
+                case Class::Node: // no async methods
+                    break;
+            }
+        }
     }
 
     if (!classData.properties.isEmpty())
@@ -511,7 +578,7 @@
     switch (role)
     {
         case Class::Interface:
-            if (!classData.methods.isEmpty())
+            if (!classData.methods.isEmpty() || !classData.asyncMethods.isEmpty())
             {
                 stream << "protected: // implement sending replies" << endl;
                 stream << "    virtual void handleMethodReply(const QDBusMessage& reply) = 0;" << endl;
@@ -527,15 +594,35 @@
             break;
 
         case Class::Proxy:
+        {
             if (!classData.signals.isEmpty())
             {
                 stream << "protected slots: // usually no need to reimplement" << endl;
                 stream << "    virtual void slotHandleDBusSignal(const QDBusMessage& message);" << endl;
                 stream << endl;
             }
+
+            if (!classData.asyncReplySignals.isEmpty())
+            {
+                if (classData.signals.isEmpty())
+                {
+                    stream << "protected slots: // usually no need to reimplement" << endl;
+                }
+                stream << "    virtual void slotHandleAsyncReply(int id, const QDBusMessage& message);" << endl;
+                stream << endl;
+            }
+
             stream << "protected:" << endl;
             stream << "    QDBusProxy* m_baseProxy;" << endl;
+
+            if (!classData.asyncMethods.isEmpty())
+            {
+                stream << endl;
+                stream << "    QMap<int, QString> m_asyncCalls;" << endl;
+            }
+
             break;
+        }
 
         case Class::Node: // not variable methods
             break;
@@ -547,7 +634,8 @@
 static void writeSignalDeclarations(const Class& classData, Class::Role role,
         QTextStream& stream)
 {
-    if (classData.signals.isEmpty()) return;
+    if (classData.signals.isEmpty() && classData.asyncReplySignals.isEmpty())
+        return;
 
     QString prefix;
     switch (role)
@@ -578,6 +666,18 @@
         MethodGenerator::writeMethodDeclaration(*it, false, false, stream);
     }
 
+    it    = classData.asyncReplySignals.begin();
+    endIt = classData.asyncReplySignals.end();
+    for (; it != endIt; ++it)
+    {
+        stream << prefix;
+
+        Method signal = *it;
+        signal.name += "AsyncReply";
+
+        MethodGenerator::writeMethodDeclaration(signal, false, false, stream);
+    }
+
     stream << endl;
 }
 
@@ -598,8 +698,6 @@
 static void writeMethodCallDeclarations(const Class& classData,
         QTextStream& stream)
 {
-    if (classData.methods.isEmpty()) return;
-
     QValueList<Method>::const_iterator it    = classData.methods.begin();
     QValueList<Method>::const_iterator endIt = classData.methods.end();
     for (; it != endIt; ++it)
@@ -607,6 +705,26 @@
         stream << "    ";
         MethodGenerator::writeMethodCallDeclaration(*it, stream);
     }
+
+    if (!classData.asyncReplyMethods.isEmpty())
+    {
+        stream << "protected:" << endl;
+        stream << "    QMap<int, QDBusMessage> m_asyncCalls;" << endl;
+        stream << endl;
+    }
+}
+
+static void writeInterfaceAsyncReplyHandlers(const Class& classData,
+    QTextStream& stream)
+{
+    if (classData.asyncReplyMethods.isEmpty()) return;
+
+    QValueList<Method>::const_iterator it    = classData.asyncReplyMethods.begin();
+    QValueList<Method>::const_iterator endIt = classData.asyncReplyMethods.end();
+    for (; it != endIt; ++it)
+    {
+        MethodGenerator::writeInterfaceAsyncReplyHandler(classData, *it, stream);
+    }
 }
 
 static void writeMethodCalls(const Class& classData, QTextStream& stream)
@@ -615,6 +733,15 @@
     QValueList<Method>::const_iterator endIt = classData.methods.end();
     for (; it != endIt; ++it)
     {
+        if ((*it).async) continue;
+
+        MethodGenerator::writeMethodCall(classData, *it, stream);
+    }
+
+    it    = classData.asyncMethods.begin();
+    endIt = classData.asyncMethods.end();
+    for (; it != endIt; ++it)
+    {
         MethodGenerator::writeMethodCall(classData, *it, stream);
     }
 }
@@ -625,6 +752,15 @@
     QValueList<Method>::const_iterator endIt = classData.methods.end();
     for (; it != endIt; ++it)
     {
+        if ((*it).async) continue;
+
+        MethodGenerator::writeProxyMethod(classData.name, *it, stream);
+    }
+
+    it    = classData.asyncMethods.begin();
+    endIt = classData.asyncMethods.end();
+    for (; it != endIt; ++it)
+    {
         MethodGenerator::writeProxyMethod(classData.name, *it, stream);
     }
 }
@@ -643,6 +779,121 @@
     }
 }
 
+static void splitAsyncProxyMethods(Class& classData)
+{
+    // create the async identifier
+    Argument idArgMethod;
+    idArgMethod.name = "asyncCallId";
+    idArgMethod.signature = "int";
+    idArgMethod.isPrimitive = true;
+    idArgMethod.direction = Argument::Out;
+
+    Argument idArgSignal = idArgMethod;
+    idArgSignal.direction = Argument::In;
+
+    QValueList<Method>::iterator it    = classData.methods.begin();
+    QValueList<Method>::iterator endIt = classData.methods.end();
+    for (; it != endIt; ++it)
+    {
+        if (!(*it).async) continue;
+
+        Method method = *it;
+
+        QValueList<Argument> methodArgs;
+        QValueList<Argument> signalArgs;
+
+        // add id argument
+        methodArgs << idArgMethod;
+        signalArgs << idArgSignal;
+
+        // split in/out arguments: "in" belong to the method, "out" to the new signal
+        QValueList<Argument>::const_iterator argIt    = method.arguments.begin();
+        QValueList<Argument>::const_iterator argEndIt = method.arguments.end();
+        for (; argIt != argEndIt; ++argIt)
+        {
+            if ((*argIt).direction == Argument::Out)
+            {
+                // signal parameters are "out" but have "in" signature,
+                // e.g. "const T&"
+                Argument arg = *argIt;
+                arg.direction = Argument::In;
+
+                signalArgs << arg;
+            }
+            else
+                methodArgs << *argIt;
+        }
+
+        // change method
+        method.arguments = methodArgs;
+
+        classData.asyncMethods << method;
+
+        // create "callback" signal
+        Method signal = method;
+        signal.arguments = signalArgs;
+
+        classData.asyncReplySignals << signal;
+    }
+}
+
+static void splitAsyncInterfaceMethods(Class& classData)
+{
+    // create the async identifier
+    Argument idArgMethod;
+    idArgMethod.name = "asyncCallId";
+    idArgMethod.signature = "int";
+    idArgMethod.isPrimitive = true;
+    idArgMethod.direction = Argument::In;
+
+    Argument idArgReply = idArgMethod;
+
+    QValueList<Method>::iterator it    = classData.methods.begin();
+    QValueList<Method>::iterator endIt = classData.methods.end();
+    for (; it != endIt; ++it)
+    {
+        if (!(*it).async) continue;
+
+        Method method = *it;
+
+        QValueList<Argument> methodArgs;
+        QValueList<Argument> replyArgs;
+
+        // add id argument
+        methodArgs << idArgMethod;
+        replyArgs  << idArgReply;
+
+        // split in/out arguments: "in" belong to the call, "out" to the reply
+        QValueList<Argument>::const_iterator argIt    = method.arguments.begin();
+        QValueList<Argument>::const_iterator argEndIt = method.arguments.end();
+        for (; argIt != argEndIt; ++argIt)
+        {
+            if ((*argIt).direction == Argument::Out)
+            {
+                // reply parameters are "out" for the service but "in" for
+                // the reply handler
+                Argument arg = *argIt;
+                arg.direction = Argument::In;
+
+                replyArgs << arg;
+            }
+            else
+                methodArgs << *argIt;
+        }
+
+        // change method
+        method.arguments = methodArgs;
+
+        classData.asyncMethods << method;
+
+        // create reply handler
+        Method reply = method;
+        reply.arguments = replyArgs;
+
+        classData.asyncReplyMethods << reply;
+    }
+}
+
 bool ClassGenerator::initStreams(const QString& baseName,
                                  QTextStream& headerStream,
                                  QTextStream& sourceStream)
@@ -680,7 +931,6 @@
 {
     closeIncludeGuard(baseName, headerStream);
     writeFileFooter(headerStream);
-
     writeFileFooter(sourceStream);
 
     QIODevice* device = headerStream.device();
@@ -717,33 +967,36 @@
                                        QTextStream& headerStream,
                                        QTextStream& sourceStream)
 {
+    Class classDataCopy = classData;
+    splitAsyncInterfaceMethods(classDataCopy);
+
     // create header
-    writeHeaderIncludes(classData, Class::Interface, headerStream);
+    writeHeaderIncludes(classDataCopy, Class::Interface, headerStream);
 
-    openNamespaces(classData.namespaces, headerStream);
-    openClassDeclaration(classData, Class::Interface, headerStream);
+    openNamespaces(classDataCopy.namespaces, headerStream);
+    openClassDeclaration(classDataCopy, Class::Interface, headerStream);
 
-    writeSignalDeclarations(classData, Class::Interface, headerStream);
-    writeMethodDeclarations(classData, Class::Interface, headerStream);
-    writeMethodCallDeclarations(classData, headerStream);
+    writeSignalDeclarations(classDataCopy, Class::Interface, headerStream);
+    writeMethodDeclarations(classDataCopy, Class::Interface, headerStream);
+    writeMethodCallDeclarations(classDataCopy, headerStream);
 
-    closeClassDeclaration(classData, Class::Interface, headerStream);
-    closeNamespaces(classData.namespaces, headerStream);
+    closeClassDeclaration(classDataCopy, Class::Interface, headerStream);
+    closeNamespaces(classDataCopy.namespaces, headerStream);
 
     // create source
-    writeSourceIncludes(classData, Class::Interface, sourceStream);
-
-    openNamespaces(classData.namespaces, sourceStream);
+    writeSourceIncludes(classDataCopy, Class::Interface, sourceStream);
 
-    MethodGenerator::writeIntrospectionDataMethod(classData, sourceStream);
+    openNamespaces(classDataCopy.namespaces, sourceStream);
 
-    writeSignalEmitters(classData, sourceStream);
+    MethodGenerator::writeIntrospectionDataMethod(classDataCopy, sourceStream);
 
-    writeMethodCalls(classData, sourceStream);
+    writeSignalEmitters(classDataCopy, sourceStream);
+    writeInterfaceAsyncReplyHandlers(classDataCopy, sourceStream);
+    writeMethodCalls(classDataCopy, sourceStream);
 
-    MethodGenerator::writeInterfaceMainMethod(classData, sourceStream);
+    MethodGenerator::writeInterfaceMainMethod(classDataCopy, sourceStream);
 
-    closeNamespaces(classData.namespaces, sourceStream);
+    closeNamespaces(classDataCopy.namespaces, sourceStream);
 
     return true;
 }
@@ -752,33 +1005,39 @@
                                    QTextStream& headerStream,
                                    QTextStream& sourceStream)
 {
+    Class classDataCopy = classData;
+    splitAsyncProxyMethods(classDataCopy);
+
     // create header
-    writeHeaderIncludes(classData, Class::Proxy, headerStream);
+    writeHeaderIncludes(classDataCopy, Class::Proxy, headerStream);
 
-    openNamespaces(classData.namespaces, headerStream);
-    openClassDeclaration(classData, Class::Proxy, headerStream);
+    openNamespaces(classDataCopy.namespaces, headerStream);
+    openClassDeclaration(classDataCopy, Class::Proxy, headerStream);
 
-    writeSignalDeclarations(classData, Class::Proxy, headerStream);
-    writeMethodDeclarations(classData, Class::Proxy, headerStream);
+    writeSignalDeclarations(classDataCopy, Class::Proxy, headerStream);
+    writeMethodDeclarations(classDataCopy, Class::Proxy, headerStream);
 
-    closeClassDeclaration(classData, Class::Proxy, headerStream);
-    closeNamespaces(classData.namespaces, headerStream);
+    closeClassDeclaration(classDataCopy, Class::Proxy, headerStream);
+    closeNamespaces(classDataCopy.namespaces, headerStream);
 
     // create source
-    writeSourceIncludes(classData, Class::Proxy, sourceStream);
+    writeSourceIncludes(classDataCopy, Class::Proxy, sourceStream);
 
-    openNamespaces(classData.namespaces, sourceStream);
+    openNamespaces(classDataCopy.namespaces, sourceStream);
 
-    MethodGenerator::writeProxyBegin(classData, sourceStream);
+    MethodGenerator::writeProxyBegin(classDataCopy, sourceStream);
 
-    writeProxyMethods(classData, sourceStream);
+    writeProxyMethods(classDataCopy, sourceStream);
 
-    writeProxyProperties(classData, sourceStream);
+    writeProxyProperties(classDataCopy, sourceStream);
 
-    if (!classData.signals.isEmpty())
-        MethodGenerator::writeSignalHandler(classData, sourceStream);
+    if (!classDataCopy.signals.isEmpty())
+        MethodGenerator::writeSignalHandler(classDataCopy, sourceStream);
 
-    closeNamespaces(classData.namespaces, sourceStream);
+    if (!classDataCopy.asyncReplySignals.isEmpty())
+        MethodGenerator::writeProxyAsyncReplyHandler(classDataCopy, sourceStream);
+
+    closeNamespaces(classDataCopy.namespaces, sourceStream);
 
     return true;
 }
@@ -796,7 +1055,6 @@
 
     closeClassDeclaration(classData, Class::Node, headerStream);
     closeNamespaces(classData.namespaces, headerStream);
-    closeIncludeGuard(classData.name, headerStream);
 
     // create source
     writeSourceIncludes(classData, Class::Node, sourceStream);
diff -ur libdbus-1-qt3-0.8.1/tools/dbusxml2qt3/main.cpp ../dbus-qt4-qt3backport/tools/dbusxml2qt3/main.cpp
--- libdbus-1-qt3-0.8.1/tools/dbusxml2qt3/main.cpp	2007-12-17 12:34:08.000000000 +0100
+++ ../dbus-qt4-qt3backport/tools/dbusxml2qt3/main.cpp	2008-03-13 10:28:54.000000000 +0100
@@ -153,12 +153,16 @@
             exit(3);
         }
 
-        QStringList nameParts = QStringList::split("::", options["classname"]);
+        // class name for node is handled differently later on
+        if (!generateNode)
+        {
+            QStringList nameParts = QStringList::split("::", options["classname"]);
 
-        interfaces[0].name = nameParts.back();
+            interfaces[0].name = nameParts.back();
 
-        nameParts.pop_back();
-        interfaces[0].namespaces = nameParts;
+            nameParts.pop_back();
+            interfaces[0].namespaces = nameParts;
+        }
     }
 
     if (checkForOption(options, "namespace"))
@@ -284,6 +288,7 @@
             Method method;
             method.name = "Introspect";
             method.noReply = false;
+            method.async = false;
 
             Argument argument;
             argument.name = "data";
diff -ur libdbus-1-qt3-0.8.1/tools/dbusxml2qt3/methodgen.cpp ../dbus-qt4-qt3backport/tools/dbusxml2qt3/methodgen.cpp
--- libdbus-1-qt3-0.8.1/tools/dbusxml2qt3/methodgen.cpp	2007-12-17 12:34:08.000000000 +0100
+++ ../dbus-qt4-qt3backport/tools/dbusxml2qt3/methodgen.cpp	2008-03-13 10:28:54.000000000 +0100
@@ -279,6 +279,24 @@
     return annotations;
 }
 
+static bool hasAnnotation(const QDomElement& element, const QString& annotation, QString* value = 0)
+{
+    for (QDomNode node = element.firstChild(); !node.isNull();
+         node = node.nextSibling())
+    {
+        if (!node.isElement()) continue;
+
+        QDomElement childElement = node.toElement();
+        if (childElement.tagName() != "annotation") continue;
+        if (childElement.attribute("name") != annotation) continue;
+
+        if (value != 0) *value = childElement.attribute("value");
+        return true;
+    }
+
+    return false;
+}
+
 static QValueList<Argument> extractArguments(const QDomElement& methodElement,
         Class& classData)
 {
@@ -568,9 +586,13 @@
             method.name = element.attribute("name");
             method.arguments = extractArguments(element, classData);
             method.noReply = false;
+            method.async = false;
 
             if (element.tagName() == "method")
+            {
+                method.async = hasAnnotation(element, "org.freedesktop.DBus.GLib.Async");
                 classData.methods.append(method);
+            }
             else
                 classData.signals.append(method);
         }
@@ -689,36 +711,85 @@
 void MethodGenerator::writeMethodCallDeclaration(const Method& method,
         QTextStream& stream)
 {
-    stream << "QDBusMessage call" << method.name
-           << "(const QDBusMessage& mesage);" << endl;
+    if (method.async)
+        stream << "void call" << method.name << "Async";
+    else
+        stream << "QDBusMessage call" << method.name;
+
+    stream << "(const QDBusMessage& message);" << endl;
     stream << endl;
 }
 
 void MethodGenerator::writeMethodCall(const Class& classData,
         const Method& method, QTextStream& stream)
 {
-    stream << "QDBusMessage " << classData.name << "::call" << method.name
-           << "(const QDBusMessage& message)" << endl;;
+    if (method.async)
+        stream << "void " << classData.name << "::call" << method.name << "Async";
+    else
+        stream << "QDBusMessage " << classData.name << "::call" << method.name;
+
+    stream << "(const QDBusMessage& message)" << endl;
 
     stream << "{" << endl;
-    stream << "    QDBusError   error;" << endl;
-    stream << "    QDBusMessage reply;" << endl;
-    stream << endl;
 
-    writeVariables("    ", method, stream);
+    if (method.async)
+    {
+        // FIXME: using writeVariables by removing asyncCallId argument
+        Method reducedMethod = method;
+        reducedMethod.arguments.pop_front();
+
+        writeVariables("    ", reducedMethod, stream);
+    }
+    else
+    {
+        stream << "    QDBusError   error;" << endl;
+        stream << "    QDBusMessage reply;" << endl;
+        stream << endl;
+
+        writeVariables("    ", method, stream);
+    }
 
     stream << endl;
-    stream << "    if (" << method.name << "(";
+
+    if (method.async)
+    {
+        stream << "    int _asyncCallId = 0;" << endl;
+        stream << "    while (m_asyncCalls.find(_asyncCallId) != m_asyncCalls.end())"
+               << endl;
+        stream << "    {" << endl;
+        stream << "        ++_asyncCallId;" << endl;
+        stream << "    }" << endl;
+        stream << "    m_asyncCalls.insert(_asyncCallId, message);" << endl;
+        stream << endl;
+
+        stream << "    " << method.name << "Async(";
+    }
+    else
+        stream << "    if (" << method.name << "(";
 
     QValueList<Argument>::const_iterator it    = method.arguments.begin();
     QValueList<Argument>::const_iterator endIt = method.arguments.end();
-    for (; it != endIt; ++it)
+    while (it != endIt)
     {
-        stream << "_" << (*it).name << ", ";
+        stream << "_" << (*it).name;
+
+        ++it;
+        if (it != endIt) stream << ", ";
     }
 
-    stream << "error))" << endl;
+    if (method.async)
+    {
+        stream << ");" << endl;
+        stream << endl;
+
+        stream << "    return;" << endl;
+        stream << "}" << endl;
+        stream << endl;
+        return;
+    }
 
+	if (method.arguments.count() > 0) stream << ", ";
+    stream << "error))" << endl;
 
     stream << "    {" << endl;
     stream << "        reply = QDBusMessage::methodReply(message);" << endl;
@@ -878,6 +949,102 @@
     stream << endl;
 }
 
+
+void MethodGenerator::writeInterfaceAsyncReplyHandler(const Class& classData,
+    const Method& method, QTextStream& stream)
+{
+    stream << "void " << classData.name << "::" << method.name
+           << "AsyncReply(";
+
+    QValueList<Argument>::const_iterator it    = method.arguments.begin();
+    QValueList<Argument>::const_iterator endIt = method.arguments.end();
+    while (it != endIt)
+    {
+        if (!(*it).isPrimitive && (*it).direction == Argument::In)
+            stream << "const ";
+
+        stream << (*it).signature;
+
+        if (!(*it).isPrimitive || (*it).direction == Argument::Out) stream << "&";
+
+        stream << " " << (*it).name;
+
+        ++it;
+        if (it != endIt) stream << ", ";
+    }
+    stream << ")" << endl;
+    stream << endl;
+    stream << "{" << endl;
+
+    stream << "    QMap<int, QDBusMessage>::iterator findIt = m_asyncCalls.find(asyncCallId);" << endl;
+    stream << "    if (findIt == m_asyncCalls.end()) return;" << endl;
+    stream << endl;
+
+    stream << "    QDBusMessage call = findIt.data();" << endl;
+    stream << "    m_asyncCalls.erase(findIt);" << endl;
+    stream << endl;
+
+    stream << "    QDBusMessage reply = QDBusMessage::methodReply(call);"
+           << endl;
+
+    it = method.arguments.begin();
+    for (++it; it != endIt; ++it) // skip asyncCallId at beginning
+    {
+        if (!(*it).annotatedType.isEmpty())
+        {
+            stream << "    QDBusData " << (*it).name << "Data;" << endl;
+
+            // TODO error handling
+            stream << "    if (QDBusDataConverter::convertToQDBusData<"
+                   << (*it).annotatedType << ">(" << (*it).name << ", "
+                   << (*it).name << "Data"
+                   << ") != QDBusDataConverter::Success) return false;"
+                   << endl;
+            stream << "    reply << " << (*it).name << "Data;" << endl;
+        }
+        else if (!(*it).accessor.isEmpty())
+        {
+            stream << "    reply << QDBusData::from" << (*it).accessor << "(";
+
+            if ((*it).subAccessor.isEmpty())
+                stream << (*it).name;
+            else
+                stream << (*it).containerClass << "(" << (*it).name << ")";
+
+            stream << ");" << endl;
+        }
+        else
+            stream << "    reply << " << (*it).name << ";" << endl;
+    }
+    stream << endl;
+
+    stream << "    handleMethodReply(reply);" << endl;
+
+    stream << "}" << endl;
+    stream << endl;
+
+    stream << "void " << classData.name << "::" << method.name
+           << "AsyncError(int asyncCallId, const QDBusError& error)";
+    stream << endl;
+
+    stream << "{" << endl;
+
+    stream << "    QMap<int, QDBusMessage>::iterator findIt = m_asyncCalls.find(asyncCallId);" << endl;
+    stream << "    if (findIt == m_asyncCalls.end()) return;" << endl;
+    stream << endl;
+
+    stream << "    QDBusMessage call = findIt.data();" << endl;
+    stream << "    m_asyncCalls.erase(findIt);" << endl;
+    stream << endl;
+
+    stream << "    QDBusMessage reply = QDBusMessage::methodError(call, error);"
+           << endl;
+    stream << "    handleMethodReply(reply);" << endl;
+
+    stream << "}" << endl;
+    stream << endl;
+}
+
 void MethodGenerator::writeInterfaceMainMethod(const Class& classData,
         QTextStream& stream)
 {
@@ -897,10 +1064,19 @@
     {
         stream << "    if (message.member() == \"" << (*it).name << "\")" << endl;
         stream << "    {" << endl;
-        stream << "        QDBusMessage reply = call" << (*it).name << "(message);"
-               << endl;
-        stream << "        handleMethodReply(reply);" << endl;
-        stream << endl;
+
+        if ((*it).async)
+        {
+            stream << "        call" << (*it).name << "Async(message);" << endl;
+            stream << endl;
+        }
+        else
+        {
+            stream << "        QDBusMessage reply = call" << (*it).name
+                   << "(message);" << endl;
+            stream << "        handleMethodReply(reply);" << endl;
+            stream << endl;
+        }
         stream << "        return true;" << endl;
         stream << "    }" << endl;
         stream << endl;
@@ -967,6 +1143,15 @@
                << endl;
     }
 
+    if (!classData.asyncReplySignals.isEmpty())
+    {
+        stream << "    QObject::connect(m_baseProxy, "
+               << "SIGNAL(asyncReply(int, const QDBusMessage&))," << endl;
+        stream << "                     this, "
+               << "       SLOT(slotHandleAsyncReply(int, const QDBusMessage&)));"
+               << endl;
+    }
+
     stream << "}" << endl;
 
     stream << endl;
@@ -988,7 +1173,8 @@
 void MethodGenerator::writeProxyMethod(const QString& className,
         const Method& method, QTextStream& stream)
 {
-    stream << "bool " << className << "::" << method.name << "(";
+    stream << "bool " << className << "::" << method.name
+           << (method.async ? "Async(" : "(");
 
     QValueList<Argument>::const_iterator it    = method.arguments.begin();
     QValueList<Argument>::const_iterator endIt = method.arguments.end();
@@ -1064,6 +1250,22 @@
         return;
     }
 
+    if (method.async)
+    {
+        stream << "    asyncCallId = m_baseProxy->sendWithAsyncReply(\"";
+        stream << method.name << "\", parameters);" << endl;
+        stream << endl;
+
+        stream << "    if (asyncCallId != 0) m_asyncCalls[asyncCallId] = \""
+               << method.name << "\";" << endl;
+        stream << endl;
+
+        stream << "    return (asyncCallId != 0);" << endl;
+        stream << "}" << endl;
+        stream << endl;
+        return;
+    }
+
     stream << "    QDBusMessage reply = m_baseProxy->sendWithReply(\"";
     stream << method.name << "\", parameters, &error);" << endl;
     stream << endl;
@@ -1335,6 +1537,58 @@
     }
 }
 
+void MethodGenerator::writeProxyAsyncReplyHandler(const Class& classData,
+        QTextStream& stream)
+{
+    stream << "void " << classData.name
+           << "::slotHandleAsyncReply(int asyncCallId, const QDBusMessage& message)" << endl;
+    stream << "{" << endl;
+
+    stream << "    QMap<int, QString>::iterator findIt = "
+           << "m_asyncCalls.find(asyncCallId);" << endl;
+    stream << "    if (findIt == m_asyncCalls.end()) return;" << endl;
+    stream << endl;
+    stream << "    const QString signalName = findIt.data();" << endl;
+    stream << "    m_asyncCalls.erase(findIt);" << endl;
+    stream << endl;
+
+    QValueList<Method>::const_iterator it    = classData.asyncReplySignals.begin();
+    QValueList<Method>::const_iterator endIt = classData.asyncReplySignals.end();
+    bool first = true;
+    for (; it != endIt; ++it)
+    {
+        stream << "    ";
+
+        if (!first)
+            stream << "else ";
+        else
+            first = false;
+
+        stream << "if (signalName == \"" << (*it).name << "\")" << endl;
+        stream << "    {" << endl;
+
+        // FIXME tricking writeVariables and writeSignalEmit into writing
+        // the reply emit code by manipulating arguments and name
+        stream << "        int _asyncCallId = asyncCallId;" << endl;
+
+        Method signal = *it;
+        signal.arguments.pop_front();
+
+        writeVariables("        ", signal, stream);
+        stream << endl;
+
+        signal = *it;
+        signal.name += "AsyncReply";
+
+        writeSignalEmit(signal, stream);
+
+        stream << "    }" << endl;
+    }
+
+    stream << "}" << endl;
+    stream << endl;
+}
+
 void MethodGenerator::writeIntrospectionDataMethod(const Class& classData,
     QTextStream& stream)
 {
diff -ur libdbus-1-qt3-0.8.1/tools/dbusxml2qt3/methodgen.h ../dbus-qt4-qt3backport/tools/dbusxml2qt3/methodgen.h
--- libdbus-1-qt3-0.8.1/tools/dbusxml2qt3/methodgen.h	2007-12-17 12:34:08.000000000 +0100
+++ ../dbus-qt4-qt3backport/tools/dbusxml2qt3/methodgen.h	2008-03-13 10:28:55.000000000 +0100
@@ -61,6 +61,7 @@
     QString name;
     QValueList<Argument> arguments;
     bool noReply;
+    bool async;
 };
 
 class Property : public Argument
@@ -86,6 +87,10 @@
     QValueList<Method> methods;
     QValueList<Method> signals;
     QValueList<Property> properties;
+
+    QValueList<Method> asyncMethods;
+    QValueList<Method> asyncReplySignals;
+    QValueList<Method> asyncReplyMethods;
 };
 
 class MethodGenerator
@@ -109,6 +114,10 @@
     static void writeSignalEmitter(const Class& classData, const Method& method,
                                    QTextStream& stream);
 
+    static void writeInterfaceAsyncReplyHandler(const Class& classData,
+                                                const Method& method,
+                                                QTextStream& stream);
+
     static void writeInterfaceMainMethod(const Class& classData,
                                          QTextStream& stream);
 
@@ -125,6 +134,9 @@
     static void writeProxyProperty(const Class& classData, const Property& property,
                                    QTextStream& stream);
 
+    static void writeProxyAsyncReplyHandler(const Class& classData,
+                                            QTextStream& stream);
+
     static void writeIntrospectionDataMethod(const Class& classData,
                                              QTextStream& stream);