[Telepathy-commits] [telepathy-qt4/master] Add full property tracking to Connection with automatic inspection of optional interface state when the remote object goes Connected

Olli Salli olli.salli at collabora.co.uk
Mon Sep 22 04:58:08 PDT 2008


---
 TelepathyQt4/cli-connection.cpp |  179 +++++++++++++++++++++++++++++++++++----
 TelepathyQt4/cli-connection.h   |   60 +++++++++++++-
 2 files changed, 220 insertions(+), 19 deletions(-)

diff --git a/TelepathyQt4/cli-connection.cpp b/TelepathyQt4/cli-connection.cpp
index 607fe0b..ad7968e 100644
--- a/TelepathyQt4/cli-connection.cpp
+++ b/TelepathyQt4/cli-connection.cpp
@@ -20,10 +20,13 @@
  */
 
 #include <TelepathyQt4/Client/Connection>
-
 #include <TelepathyQt4/_gen/cli-connection-body.hpp>
 #include <TelepathyQt4/_gen/cli-connection.moc.hpp>
 
+#include <QQueue>
+#include <QtGlobal>
+
+#include <TelepathyQt4/Client/DBus>
 #include "debug.hpp"
 
 namespace Telepathy
@@ -33,34 +36,92 @@ namespace Client
 
 struct Connection::Private
 {
-    Connection* parent;
+    Connection& parent;
     ConnectionInterface interface;
+    ConnectionInterfaceAliasingInterface aliasing;
+    ConnectionInterfacePresenceInterface presence;
+    ConnectionInterfaceSimplePresenceInterface simplePresence;
+    DBus::PropertiesInterface properties;
+    QQueue<void (Private::*)()> introspectQueue;
 
     bool ready;
     long status;
     uint statusReason;
     QStringList interfaces;
+    ConnectionAliasFlags aliasFlags;
+    StatusSpecMap presenceStatuses;
+    SimpleStatusSpecMap simplePresenceStatuses;
 
-    Private(Connection *parent,
+    Private(Connection &parent,
             const QDBusConnection& connection,
             const QString& serviceName,
             const QString& objectPath)
         : parent(parent),
-          interface(connection, serviceName, objectPath, parent)
+          interface(connection, serviceName, objectPath, &parent),
+          aliasing(interface),
+          presence(interface),
+          simplePresence(interface),
+          properties(interface)
     {
         ready = false;
         status = -1;
         statusReason = ConnectionStatusReasonNoneSpecified;
 
-        parent->connect(&interface,
-                        SIGNAL(statusChanged(uint, uint)),
-                        SLOT(statusChanged(uint, uint)));
+        parent.connect(&interface,
+                       SIGNAL(statusChanged(uint, uint)),
+                       SLOT(statusChanged(uint, uint)));
+
+        debug() << "Calling GetStatus()";
+
+        QDBusPendingCallWatcher* watcher =
+            new QDBusPendingCallWatcher(interface.getStatus(), &parent);
+        parent.connect(watcher,
+                       SIGNAL(finished(QDBusPendingCallWatcher*)),
+                       SLOT(gotStatus(QDBusPendingCallWatcher*)));
+    }
 
+    void introspectAliasing()
+    {
+        debug() << "Calling GetAliasFlags()";
+        QDBusPendingCallWatcher* watcher =
+            new QDBusPendingCallWatcher(aliasing.getAliasFlags(), &parent);
+        parent.connect(watcher,
+                       SIGNAL(finished(QDBusPendingCallWatcher*)),
+                       SLOT(gotAliasFlags(QDBusPendingCallWatcher*)));
+    }
+
+    void introspectPresence()
+    {
+        debug() << "Calling GetStatuses() (legacy)";
+        QDBusPendingCallWatcher* watcher =
+            new QDBusPendingCallWatcher(presence.getStatuses(), &parent);
+        parent.connect(watcher,
+                       SIGNAL(finished(QDBusPendingCallWatcher*)),
+                       SLOT(gotStatuses(QDBusPendingCallWatcher*)));
+    }
+
+    void introspectSimplePresence()
+    {
+        debug() << "Getting available SimplePresence statuses";
+        QDBusPendingCall call =
+            properties.get(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
+                           "Statuses");
         QDBusPendingCallWatcher* watcher =
-            new QDBusPendingCallWatcher(interface.getStatus(), parent);
-        parent->connect(watcher,
-                        SIGNAL(finished(QDBusPendingCallWatcher*)),
-                        SLOT(gotStatus(QDBusPendingCallWatcher*)));
+            new QDBusPendingCallWatcher(call, &parent);
+        parent.connect(watcher,
+                       SIGNAL(finished(QDBusPendingCallWatcher*)),
+                       SLOT(gotSimpleStatuses(QDBusPendingCallWatcher*)));
+    }
+
+    void continueIntrospection()
+    {
+        if (introspectQueue.isEmpty()) {
+            debug() << "Connection ready";
+            ready = true;
+            emit parent.ready();
+        } else {
+            (this->*introspectQueue.dequeue())();
+        }
     }
 };
 
@@ -68,7 +129,7 @@ Connection::Connection(const QString& serviceName,
                        const QString& objectPath,
                        QObject* parent)
     : QObject(parent),
-      mPriv(new Private(this, QDBusConnection::sessionBus(), serviceName, objectPath))
+      mPriv(new Private(*this, QDBusConnection::sessionBus(), serviceName, objectPath))
 {
 }
 
@@ -77,7 +138,7 @@ Connection::Connection(const QDBusConnection& connection,
                        const QString& objectPath,
                        QObject* parent)
     : QObject(parent),
-      mPriv(new Private(this, connection, serviceName, objectPath))
+      mPriv(new Private(*this, connection, serviceName, objectPath))
 {
 }
 
@@ -116,6 +177,26 @@ QStringList Connection::interfaces() const
     return mPriv->interfaces;
 }
 
+ConnectionAliasFlags Connection::aliasFlags() const
+{
+    return mPriv->aliasFlags;
+}
+
+StatusSpecMap Connection::presenceStatuses() const
+{
+    return mPriv->presenceStatuses;
+}
+
+SimpleStatusSpecMap Connection::simplePresenceStatuses() const
+{
+    if (!ready() && mPriv->simplePresenceStatuses.isEmpty()) {
+        debug() << "Getting the simple presence statuses available before connecting";
+        mPriv->simplePresenceStatuses = mPriv->simplePresence.statuses();
+    }
+
+    return mPriv->simplePresenceStatuses;
+}
+
 void Connection::statusChanged(uint status, uint reason)
 {
     if (mPriv->status == -1) {
@@ -123,12 +204,15 @@ void Connection::statusChanged(uint status, uint reason)
         return;
     }
 
+    debug().nospace() << "New status (" << status << ", " << reason << ')';
+
     mPriv->status = status;
     mPriv->statusReason = reason;
 
     emit statusChanged(status, reason);
 
     if (status == ConnectionStatusConnected) {
+        debug() << "Calling GetInterfaces()";
         QDBusPendingCallWatcher* watcher =
             new QDBusPendingCallWatcher(interface().getInterfaces(), this);
         connect(watcher,
@@ -142,6 +226,7 @@ void Connection::gotStatus(QDBusPendingCallWatcher* watcher)
     QDBusPendingReply<uint, uint> reply = *watcher;
 
     if (!reply.isError()) {
+        debug() << "Got reply to initial GetStatus()";
         // Avoid early return in statusChanged()
         mPriv->status = reply.argumentAt<0>();
         statusChanged(reply.argumentAt<0>(), reply.argumentAt<1>());
@@ -154,15 +239,73 @@ void Connection::gotInterfaces(QDBusPendingCallWatcher* watcher)
 {
     QDBusPendingReply<QStringList> reply = *watcher;
 
-    if (!reply.isError())
+    if (!reply.isError()) {
         mPriv->interfaces = reply.value();
-    else
+        debug() << "Got reply to initial GetInterfaces():";
+        debug() << mPriv->interfaces;
+    } else {
         warning().nospace() << "GetInterfaces() failed with " << reply.error().name() << ": " << reply.error().message() << " - assuming no interfaces";
+    }
+
+    for (QStringList::const_iterator i  = mPriv->interfaces.constBegin();
+                                     i != mPriv->interfaces.constEnd();
+                                     ++i) {
+        void (Private::*introspectFunc)() = 0;
+
+        if (*i == TELEPATHY_INTERFACE_CONNECTION_INTERFACE_ALIASING)
+            introspectFunc = &Private::introspectAliasing;
+        else if (*i == TELEPATHY_INTERFACE_CONNECTION_INTERFACE_PRESENCE)
+            introspectFunc = &Private::introspectPresence;
+        else if (*i == TELEPATHY_INTERFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE)
+            introspectFunc = &Private::introspectSimplePresence;
+
+        if (introspectFunc)
+            mPriv->introspectQueue.enqueue(introspectFunc);
+    }
+
+    mPriv->continueIntrospection();
+}
+
+void Connection::gotAliasFlags(QDBusPendingCallWatcher* watcher)
+{
+    QDBusPendingReply<uint> reply = *watcher;
+
+    if (!reply.isError()) {
+        mPriv->aliasFlags = static_cast<ConnectionAliasFlag>(reply.value());
+        debug().nospace() << "Got initial alias flags 0x" << hex << mPriv->aliasFlags;
+    } else {
+        warning().nospace() << "GetAliasFlags() failed with " << reply.error().name() << ": " << reply.error().message();
+    }
 
-    // TODO introspect interfaces
+    mPriv->continueIntrospection();
+}
+
+void Connection::gotStatuses(QDBusPendingCallWatcher* watcher)
+{
+    QDBusPendingReply<StatusSpecMap> reply = *watcher;
+
+    if (!reply.isError()) {
+        mPriv->presenceStatuses = reply.value();
+        debug() << "Got initial legacy presence statuses";
+    } else {
+        warning().nospace() << "GetStatuses() failed with " << reply.error().name() << ": " << reply.error().message();
+    }
+
+    mPriv->continueIntrospection();
+}
+
+void Connection::gotSimpleStatuses(QDBusPendingCallWatcher* watcher)
+{
+    QDBusPendingReply<QDBusVariant> reply = *watcher;
+
+    if (!reply.isError()) {
+        mPriv->simplePresenceStatuses = qdbus_cast<SimpleStatusSpecMap>(reply.value().variant());
+        debug() << "Got initial simple presence statuses";
+    } else {
+        warning().nospace() << "Getting initial simple presence statuses failed with " << reply.error().name() << ": " << reply.error().message();
+    }
 
-    mPriv->ready = true;
-    emit ready();
+    mPriv->continueIntrospection();
 }
 
 }
diff --git a/TelepathyQt4/cli-connection.h b/TelepathyQt4/cli-connection.h
index 5dc8be5..b526fb9 100644
--- a/TelepathyQt4/cli-connection.h
+++ b/TelepathyQt4/cli-connection.h
@@ -164,7 +164,7 @@ public:
     uint statusReason() const;
 
     /**
-     * List of interfaces implemented by the remote object.
+     * List of interfaces implemented by the connection.
      *
      * The value is undefined until the property #ready is <code>true</code>.
      */
@@ -177,6 +177,61 @@ public:
      */
     QStringList interfaces() const;
 
+    /**
+     * Bitwise OR of flags detailing the behaviour of aliases on the
+     * connection.
+     *
+     * The value is undefined if the value of the property #ready is
+     * <code>false</code> or the connection doesn't support the Aliasing
+     * interface.
+     */
+    Q_PROPERTY(Telepathy::ConnectionAliasFlags aliasFlags READ aliasFlags)
+
+    /**
+     * Getter for the property #aliasFlags.
+     *
+     * \return Bitfield of the alias flags, as specified in
+     * #ConnectionAliasFlag.
+     */
+    ConnectionAliasFlags aliasFlags() const;
+
+    /**
+     * Dictionary of the valid presence statuses for the connection for use with
+     * the legacy Telepathy Presence interface.
+     *
+     * The value is undefined if the value of the property #ready is
+     * <code>false</code> or the connection doesn't support the Presence
+     * interface.
+     */
+    Q_PROPERTY(Telepathy::StatusSpecMap presenceStatuses READ presenceStatuses)
+
+    /**
+     * Getter for the property #presenceStatuses.
+     *
+     * \return Dictionary mapping string identifiers to structs for each status.
+     */
+    StatusSpecMap presenceStatuses() const;
+
+    /**
+     * Dictionary of the valid presence statuses for the connection for use with
+     * the new simplified Telepathy SimplePresence interface.
+     *
+     * Getting the value of this property before the connection is ready (as
+     * signified by the property #ready) may cause a synchronous call to the
+     * remote service to be made.
+     *
+     * The value is undefined if the connection doesn't support the
+     * SimplePresence interface.
+     */
+    Q_PROPERTY(Telepathy::SimpleStatusSpecMap simplePresenceStatuses READ simplePresenceStatuses)
+
+    /**
+     * Getter for the property #simplePresenceStatuses.
+     *
+     * \return Dictionary mapping string identifiers to structs for each status.
+     */
+    SimpleStatusSpecMap simplePresenceStatuses() const;
+
 Q_SIGNALS:
     /**
      * Emitted when the value of the property #ready changes to
@@ -188,6 +243,9 @@ private Q_SLOTS:
     void statusChanged(uint, uint);
     void gotStatus(QDBusPendingCallWatcher* watcher);
     void gotInterfaces(QDBusPendingCallWatcher* watcher);
+    void gotAliasFlags(QDBusPendingCallWatcher* watcher);
+    void gotStatuses(QDBusPendingCallWatcher* watcher);
+    void gotSimpleStatuses(QDBusPendingCallWatcher* watcher);
 
 private:
     struct Private;
-- 
1.5.6.5




More information about the Telepathy-commits mailing list