[Telepathy-commits] [telepathy-qt4/master] Add initial connection status tracking to Connection

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


---
 TelepathyQt4/cli-connection.cpp |  112 ++++++++++++++++++++++++++++++++++++--
 TelepathyQt4/cli-connection.h   |   86 +++++++++++++++++++++++++++++-
 2 files changed, 191 insertions(+), 7 deletions(-)

diff --git a/TelepathyQt4/cli-connection.cpp b/TelepathyQt4/cli-connection.cpp
index e1c86e1..b151f63 100644
--- a/TelepathyQt4/cli-connection.cpp
+++ b/TelepathyQt4/cli-connection.cpp
@@ -31,19 +31,51 @@ namespace Client
 
 struct Connection::Private
 {
+    Connection* parent;
     ConnectionInterface interface;
 
-    Private(const QDBusConnection& connection, const QString& serviceName, const QString& objectPath, QObject* parent)
-        : interface(connection, serviceName, objectPath, parent) {}
+    bool ready;
+    long status;
+    uint statusReason;
+    QStringList interfaces;
+
+    Private(Connection *parent,
+            const QDBusConnection& connection,
+            const QString& serviceName,
+            const QString& objectPath)
+        : parent(parent),
+          interface(connection, serviceName, objectPath, parent)
+    {
+        ready = false;
+        status = -1;
+        statusReason = ConnectionStatusReasonNoneSpecified;
+
+        parent->connect(&interface,
+                        SIGNAL(statusChanged(uint, uint)),
+                        SLOT(statusChanged(uint, uint)));
+
+        QDBusPendingCallWatcher* watcher =
+            new QDBusPendingCallWatcher(interface.getStatus(), parent);
+        parent->connect(watcher,
+                        SIGNAL(finished(QDBusPendingCallWatcher*)),
+                        SLOT(gotStatus(QDBusPendingCallWatcher*)));
+    }
 };
 
-Connection::Connection(const QString& serviceName, const QString& objectPath, QObject* parent)
-    : mPriv(new Private(QDBusConnection::sessionBus(), serviceName, objectPath, parent))
+Connection::Connection(const QString& serviceName,
+                       const QString& objectPath,
+                       QObject* parent)
+    : QObject(parent),
+      mPriv(new Private(this, QDBusConnection::sessionBus(), serviceName, objectPath))
 {
 }
 
-Connection::Connection(const QDBusConnection& connection, const QString& serviceName, const QString& objectPath, QObject* parent)
-    : mPriv(new Private(connection, serviceName, objectPath, parent))
+Connection::Connection(const QDBusConnection& connection,
+                       const QString& serviceName,
+                       const QString& objectPath,
+                       QObject* parent)
+    : QObject(parent),
+      mPriv(new Private(this, connection, serviceName, objectPath))
 {
 }
 
@@ -62,5 +94,73 @@ const ConnectionInterface& Connection::interface() const
     return mPriv->interface;
 }
 
+bool Connection::ready() const
+{
+    return mPriv->ready;
+}
+
+long Connection::status() const
+{
+    return mPriv->status;
+}
+
+uint Connection::statusReason() const
+{
+    return mPriv->statusReason;
+}
+
+QStringList Connection::interfaces() const
+{
+    return mPriv->interfaces;
+}
+
+void Connection::statusChanged(uint status, uint reason)
+{
+    if (mPriv->status == -1) {
+        // We've got a StatusChanged before the initial GetStatus reply, ignore it
+        return;
+    }
+
+    mPriv->status = status;
+    mPriv->statusReason = reason;
+
+    emit statusChanged(status, reason);
+
+    if (status == ConnectionStatusConnected) {
+        QDBusPendingCallWatcher* watcher =
+            new QDBusPendingCallWatcher(interface().getInterfaces(), this);
+        connect(watcher,
+                SIGNAL(finished(QDBusPendingCallWatcher*)),
+                SLOT(gotInterfaces(QDBusPendingCallWatcher*)));
+    }
+}
+
+void Connection::gotStatus(QDBusPendingCallWatcher* watcher)
+{
+    QDBusPendingReply<uint, uint> reply = *watcher;
+
+    if (!reply.isError()) {
+        // Avoid early return in statusChanged()
+        mPriv->status = reply.argumentAt<0>();
+        statusChanged(reply.argumentAt<0>(), reply.argumentAt<1>());
+    } else {
+        // TODO error reporting
+    }
+}
+
+void Connection::gotInterfaces(QDBusPendingCallWatcher* watcher)
+{
+    QDBusPendingReply<QStringList> reply = *watcher;
+
+    if (!reply.isError())
+        mPriv->interfaces = reply.value();
+        // TODO error reporting
+
+    // TODO introspect interfaces
+
+    mPriv->ready = true;
+    emit ready();
+}
+
 }
 }
diff --git a/TelepathyQt4/cli-connection.h b/TelepathyQt4/cli-connection.h
index fb8d561..5dc8be5 100644
--- a/TelepathyQt4/cli-connection.h
+++ b/TelepathyQt4/cli-connection.h
@@ -43,6 +43,11 @@
 
 #include <TelepathyQt4/_gen/cli-connection.h>
 
+#include <QDBusPendingCallWatcher>
+#include <QStringList>
+
+#include <TelepathyQt4/Constants>
+
 namespace Telepathy
 {
 namespace Client
@@ -98,16 +103,95 @@ public:
      * easy direct access to the D-Bus properties, methods and signals on the
      * remote object.
      *
-     * Note that this class provides a more convenient interface for some
+     * Note that this class provides a more convenient way to access some
      * functionality than using the interface class directly.
      *
      * \return A reference to the underlying ConnectionInterface instance.
+     *
+     * \{
      */
     ConnectionInterface& interface();
     const ConnectionInterface& interface() const;
 
+    /**
+     * \}
+     */
+
+    /**
+     * Initially <code>false</code>, changes to <code>true</code> when the
+     * connection has gone to the Connected status, introspection is finished
+     * and it's ready for use.
+     *
+     * By the time this property becomes true, the property #interfaces will
+     * have been populated.
+     */
+    Q_PROPERTY(bool ready READ ready)
+
+    /**
+     * Getter for the property #ready.
+     *
+     * \return If the object is ready for use.
+     */
+    bool ready() const;
+
+    /**
+     * The connection's status (one of the values of #ConnectionStatus), or -1
+     * if we don't know it yet.
+     *
+     * Connect to the signal <code>statusChanged</code> on the underlying
+     * #interface to watch for changes.
+     */
+    Q_PROPERTY(long status READ status)
+
+    /**
+     * Getter for the property #status.
+     *
+     * \return The status of the connection.
+     */
+    long status() const;
+
+    /**
+     * The reason why #status changed to its current value, or
+     * #ConnectionStatusReasonNoneSpecified if the status is still unknown.
+     */
+    Q_PROPERTY(uint statusReason READ statusReason)
+
+    /**
+     * Getter for the property #statusReason.
+     *
+     * \return The reason for the current status.
+     */
+    uint statusReason() const;
+
+    /**
+     * List of interfaces implemented by the remote object.
+     *
+     * The value is undefined until the property #ready is <code>true</code>.
+     */
+    Q_PROPERTY(QStringList interfaces READ interfaces)
+
+    /**
+     * Getter for the property #interfaces.
+     *
+     * \return D-Bus interface names of the implemented interfaces.
+     */
+    QStringList interfaces() const;
+
+Q_SIGNALS:
+    /**
+     * Emitted when the value of the property #ready changes to
+     * <code>true</code>.
+     */
+    void ready();
+
+private Q_SLOTS:
+    void statusChanged(uint, uint);
+    void gotStatus(QDBusPendingCallWatcher* watcher);
+    void gotInterfaces(QDBusPendingCallWatcher* watcher);
+
 private:
     struct Private;
+    friend struct Private;
     Private *mPriv;
 };
 
-- 
1.5.6.5




More information about the Telepathy-commits mailing list