[Telepathy-commits] [telepathy-qt4/master] Connection: Added createChannel/ensureChannel.

Andre Moreira Magalhaes (andrunko) andre.magalhaes at collabora.co.uk
Sun Jan 25 14:01:42 PST 2009


---
 TelepathyQt4/Client/connection.cpp      |  115 +++++++++++++++++++++++++++++--
 TelepathyQt4/Client/connection.h        |   11 +++
 TelepathyQt4/Client/pending-channel.cpp |   92 ++++++++++++++++++++++++-
 TelepathyQt4/Client/pending-channel.h   |    6 ++-
 4 files changed, 217 insertions(+), 7 deletions(-)

diff --git a/TelepathyQt4/Client/connection.cpp b/TelepathyQt4/Client/connection.cpp
index 61aba19..93882b4 100644
--- a/TelepathyQt4/Client/connection.cpp
+++ b/TelepathyQt4/Client/connection.cpp
@@ -28,6 +28,7 @@
 #include "TelepathyQt4/debug-internal.h"
 
 #include <TelepathyQt4/Client/PendingChannel>
+#include <TelepathyQt4/Client/PendingFailure>
 #include <TelepathyQt4/Client/PendingHandles>
 #include <TelepathyQt4/Client/PendingVoidMethodCall>
 
@@ -1058,18 +1059,122 @@ ConnectionInterface *Connection::baseInterface() const
 PendingChannel *Connection::requestChannel(const QString &channelType,
         uint handleType, uint handle)
 {
+    if (mPriv->readiness != Private::ReadinessFull) {
+        warning() << "Calling requestChannel with connection not yet connected";
+        return new PendingChannel(this, TELEPATHY_ERROR_NOT_AVAILABLE,
+                "Connection not yet connected");
+    }
+
     debug() << "Requesting a Channel with type" << channelType
             << "and handle" << handle << "of type" << handleType;
 
     PendingChannel *channel =
         new PendingChannel(this, channelType, handleType, handle);
-    QDBusPendingCallWatcher *watcher =
-        new QDBusPendingCallWatcher(mPriv->baseInterface->RequestChannel(
-                    channelType, handleType, handle, true), channel);
 
-    channel->connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher *)),
-                              SLOT(onCallFinished(QDBusPendingCallWatcher *)));
+    return channel;
+}
+
+/**
+ * Asynchronously creates a channel satisfying the given request.
+ *
+ * The request MUST contain the following keys:
+ *   org.freedesktop.Telepathy.Account.ChannelType
+ *   org.freedesktop.Telepathy.Account.TargetHandleType
+ *
+ * Upon completion, the reply to the request can be retrieved through the
+ * returned PendingChannel object. The object also provides access to the
+ * parameters with which the call was made and a signal to connect to get
+ * notification of the request finishing processing. See the documentation
+ * for that class for more info.
+ *
+ * The returned PendingChannel object should be freed using
+ * its QObject::deleteLater() method after it is no longer used. However,
+ * all PendingChannel objects resulting from requests to a particular
+ * Connection will be freed when the Connection itself is freed. Conversely,
+ * this means that the PendingChannel object should not be used after the
+ * Connection is destroyed.
+ *
+ * \sa PendingChannel
+ *
+ * \param request A dictionary containing the desirable properties.
+ * \return Pointer to a newly constructed PendingChannel object, tracking
+ *         the progress of the request.
+ */
+PendingChannel *Connection::createChannel(const QVariantMap &request)
+{
+    if (mPriv->readiness != Private::ReadinessFull) {
+        warning() << "Calling createChannel with connection not yet connected";
+        return new PendingChannel(this, TELEPATHY_ERROR_NOT_AVAILABLE,
+                "Connection not yet connected");
+    }
+
+    if (!mPriv->interfaces.contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_REQUESTS)) {
+        warning() << "Requests interface is not support by this connection";
+        return new PendingChannel(this, TELEPATHY_ERROR_NOT_IMPLEMENTED,
+                "Connection does not support Requests Interface");
+    }
+
+    if (!request.contains(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType")) ||
+        !request.contains(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"))) {
+        return new PendingChannel(this, TELEPATHY_ERROR_INVALID_ARGUMENT,
+                "Invalid 'request' argument");
+    }
+
+    debug() << "Creating a Channel";
+    PendingChannel *channel =
+        new PendingChannel(this, request, true);
+    return channel;
+}
+
+/**
+ * Asynchronously ensures a channel exists satisfying the given request.
+ *
+ * The request MUST contain the following keys:
+ *   org.freedesktop.Telepathy.Account.ChannelType
+ *   org.freedesktop.Telepathy.Account.TargetHandleType
+ *
+ * Upon completion, the reply to the request can be retrieved through the
+ * returned PendingChannel object. The object also provides access to the
+ * parameters with which the call was made and a signal to connect to get
+ * notification of the request finishing processing. See the documentation
+ * for that class for more info.
+ *
+ * The returned PendingChannel object should be freed using
+ * its QObject::deleteLater() method after it is no longer used. However,
+ * all PendingChannel objects resulting from requests to a particular
+ * Connection will be freed when the Connection itself is freed. Conversely,
+ * this means that the PendingChannel object should not be used after the
+ * Connection is destroyed.
+ *
+ * \sa PendingChannel
+ *
+ * \param request A dictionary containing the desirable properties.
+ * \return Pointer to a newly constructed PendingChannel object, tracking
+ *         the progress of the request.
+ */
+PendingChannel *Connection::ensureChannel(const QVariantMap &request)
+{
+    if (mPriv->readiness != Private::ReadinessFull) {
+        warning() << "Calling ensureChannel with connection not yet connected";
+        return new PendingChannel(this, TELEPATHY_ERROR_NOT_AVAILABLE,
+                "Connection not yet connected");
+    }
+
+    if (!mPriv->interfaces.contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_REQUESTS)) {
+        warning() << "Requests interface is not support by this connection";
+        return new PendingChannel(this, TELEPATHY_ERROR_NOT_IMPLEMENTED,
+                "Connection does not support Requests Interface");
+    }
+
+    if (!request.contains(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType")) ||
+        !request.contains(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"))) {
+        return new PendingChannel(this, TELEPATHY_ERROR_INVALID_ARGUMENT,
+                "Invalid 'request' argument");
+    }
 
+    debug() << "Creating a Channel";
+    PendingChannel *channel =
+        new PendingChannel(this, request, false);
     return channel;
 }
 
diff --git a/TelepathyQt4/Client/connection.h b/TelepathyQt4/Client/connection.h
index 8950085..c58cfca 100644
--- a/TelepathyQt4/Client/connection.h
+++ b/TelepathyQt4/Client/connection.h
@@ -130,6 +130,12 @@ public:
         return optionalInterface<ConnectionInterfaceSimplePresenceInterface>(check);
     }
 
+    inline ConnectionInterfaceRequestsInterface *requestsInterface(
+            InterfaceSupportedChecking check = CheckInterfaceSupported) const
+    {
+        return optionalInterface<ConnectionInterfaceRequestsInterface>(check);
+    }
+
     inline DBus::PropertiesInterface *propertiesInterface() const
     {
         return optionalInterface<DBus::PropertiesInterface>(BypassInterfaceCheck);
@@ -138,6 +144,10 @@ public:
     PendingChannel *requestChannel(const QString &channelType,
                                    uint handleType, uint handle);
 
+    PendingChannel *createChannel(const QVariantMap &request);
+
+    PendingChannel *ensureChannel(const QVariantMap &request);
+
     PendingOperation *requestConnect();
 
     PendingOperation *requestDisconnect();
@@ -175,6 +185,7 @@ private:
 
     struct Private;
     friend struct Private;
+    friend class PendingChannel;
     friend class PendingHandles;
     friend class ReferencedHandles;
     Private *mPriv;
diff --git a/TelepathyQt4/Client/pending-channel.cpp b/TelepathyQt4/Client/pending-channel.cpp
index 16221d3..2a1d253 100644
--- a/TelepathyQt4/Client/pending-channel.cpp
+++ b/TelepathyQt4/Client/pending-channel.cpp
@@ -40,12 +40,54 @@ struct PendingChannel::Private
     QDBusObjectPath objectPath;
 };
 
+PendingChannel::PendingChannel(Connection* connection, const QString& errorName,
+        const QString& errorMessage)
+    : PendingOperation(connection),
+      mPriv(new Private)
+{
+    mPriv->handleType = 0;
+    mPriv->handle = 0;
+
+    setFinishedWithError(errorName, errorMessage);
+}
+
 PendingChannel::PendingChannel(Connection* connection, const QString& channelType, uint handleType, uint handle)
     : PendingOperation(connection), mPriv(new Private)
 {
     mPriv->channelType = channelType;
     mPriv->handleType = handleType;
     mPriv->handle = handle;
+
+    QDBusPendingCallWatcher *watcher =
+        new QDBusPendingCallWatcher(connection->baseInterface()->RequestChannel(
+                    channelType, handleType, handle, true), this);
+    connect(watcher,
+            SIGNAL(finished(QDBusPendingCallWatcher *)),
+            SLOT(onCallRequestChannelFinished(QDBusPendingCallWatcher *)));
+}
+
+PendingChannel::PendingChannel(Connection* connection, const QVariantMap& request, bool create)
+    : PendingOperation(connection),
+      mPriv(new Private)
+{
+    mPriv->channelType = request.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType")).toString();
+    mPriv->handleType = request.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType")).toUInt();
+    mPriv->handle = request.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle")).toUInt();
+
+    if (create) {
+        QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
+                connection->requestsInterface()->CreateChannel(request), this);
+        connect(watcher,
+                SIGNAL(finished(QDBusPendingCallWatcher *)),
+                SLOT(onCallCreateChannelFinished(QDBusPendingCallWatcher *)));
+    }
+    else {
+        QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
+                connection->requestsInterface()->EnsureChannel(request), this);
+        connect(watcher,
+                SIGNAL(finished(QDBusPendingCallWatcher *)),
+                SLOT(onCallEnsureChannelFinished(QDBusPendingCallWatcher *)));
+    }
 }
 
 PendingChannel::~PendingChannel()
@@ -90,7 +132,7 @@ Channel* PendingChannel::channel(QObject* parent) const
     return channel;
 }
 
-void PendingChannel::onCallFinished(QDBusPendingCallWatcher* watcher)
+void PendingChannel::onCallRequestChannelFinished(QDBusPendingCallWatcher* watcher)
 {
     QDBusPendingReply<QDBusObjectPath> reply = *watcher;
 
@@ -108,5 +150,53 @@ void PendingChannel::onCallFinished(QDBusPendingCallWatcher* watcher)
     watcher->deleteLater();
 }
 
+void PendingChannel::onCallCreateChannelFinished(QDBusPendingCallWatcher* watcher)
+{
+    QDBusPendingReply<QDBusObjectPath, QVariantMap> reply = *watcher;
+
+    debug() << "Received reply to RequestChannel";
+
+    if (!reply.isError()) {
+        mPriv->objectPath = reply.argumentAt<0>();
+        debug() << " Success: object path" << mPriv->objectPath.path();
+
+        QVariantMap map = reply.argumentAt<1>();
+        mPriv->channelType = map.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType")).toString();
+        mPriv->handleType = map.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType")).toUInt();
+        mPriv->handle = map.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle")).toUInt();
+
+        setFinished();
+    } else {
+        debug().nospace() << " Failure: error " << reply.error().name() << ": " << reply.error().message();
+        setFinishedWithError(reply.error());
+    }
+
+    watcher->deleteLater();
+}
+
+void PendingChannel::onCallEnsureChannelFinished(QDBusPendingCallWatcher* watcher)
+{
+    QDBusPendingReply<bool, QDBusObjectPath, QVariantMap> reply = *watcher;
+
+    debug() << "Received reply to RequestChannel";
+
+    if (!reply.isError()) {
+        mPriv->objectPath = reply.argumentAt<1>();
+        debug() << " Success: object path" << mPriv->objectPath.path();
+
+        QVariantMap map = reply.argumentAt<2>();
+        mPriv->channelType = map.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType")).toString();
+        mPriv->handleType = map.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType")).toUInt();
+        mPriv->handle = map.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle")).toUInt();
+
+        setFinished();
+    } else {
+        debug().nospace() << " Failure: error " << reply.error().name() << ": " << reply.error().message();
+        setFinishedWithError(reply.error());
+    }
+
+    watcher->deleteLater();
+}
+
 } // Telepathy::Client
 } // Telepathy
diff --git a/TelepathyQt4/Client/pending-channel.h b/TelepathyQt4/Client/pending-channel.h
index 6e93f8d..3956388 100644
--- a/TelepathyQt4/Client/pending-channel.h
+++ b/TelepathyQt4/Client/pending-channel.h
@@ -122,12 +122,16 @@ public:
     Channel* channel(QObject* parent = 0) const;
 
 private Q_SLOTS:
-    void onCallFinished(QDBusPendingCallWatcher* watcher);
+    void onCallRequestChannelFinished(QDBusPendingCallWatcher* watcher);
+    void onCallCreateChannelFinished(QDBusPendingCallWatcher* watcher);
+    void onCallEnsureChannelFinished(QDBusPendingCallWatcher* watcher);
 
 private:
     friend class Connection;
 
+    PendingChannel(Connection* connection, const QString& errorName, const QString& errorMessage);
     PendingChannel(Connection* connection, const QString& type, uint handleType, uint handle);
+    PendingChannel(Connection* connection, const QVariantMap& request, bool create);
 
     struct Private;
     friend struct Private;
-- 
1.5.6.5




More information about the Telepathy-commits mailing list