[Telepathy-commits] [telepathy-qt4/master] Connection: Added initial roster support (FeatureRoster).

Andre Moreira Magalhaes (andrunko) andre.magalhaes at collabora.co.uk
Tue Feb 24 09:26:10 PST 2009


---
 TelepathyQt4/Client/connection.cpp      |  107 +++++++++++++++++++++++++++++++
 TelepathyQt4/Client/connection.h        |    4 +
 TelepathyQt4/Client/contact-manager.cpp |   28 ++++++++
 TelepathyQt4/Client/contact-manager.h   |   43 ++++++++++++
 4 files changed, 182 insertions(+), 0 deletions(-)

diff --git a/TelepathyQt4/Client/connection.cpp b/TelepathyQt4/Client/connection.cpp
index 098e9ab..ff39a7e 100644
--- a/TelepathyQt4/Client/connection.cpp
+++ b/TelepathyQt4/Client/connection.cpp
@@ -36,8 +36,10 @@
 #include <TelepathyQt4/Client/PendingFailure>
 #include <TelepathyQt4/Client/PendingHandles>
 #include <TelepathyQt4/Client/PendingReady>
+#include <TelepathyQt4/Client/PendingReadyChannel>
 #include <TelepathyQt4/Client/PendingVoidMethodCall>
 #include <TelepathyQt4/Client/ReadinessHelper>
+#include <TelepathyQt4/Client/ReferencedHandles>
 
 #include <QMap>
 #include <QMetaObject>
@@ -85,6 +87,7 @@ struct Connection::Private
     void introspectContacts();
     static void introspectSelfContact(Private *self);
     static void introspectSimplePresence(Private *self);
+    static void introspectRoster(Private *self);
 
     struct HandleContext;
 
@@ -115,6 +118,8 @@ struct Connection::Private
     QSharedPointer<Contact> selfContact;
     QStringList contactAttributeInterfaces;
     uint selfHandle;
+    QMap<uint, ContactManager::ContactListChannel> contactListsChannels;
+    uint contactListsChannelsReady;
 
     // (Bus connection name, service name) -> HandleContext
     static QMap<QPair<QString, QString>, HandleContext *> handleContexts;
@@ -162,6 +167,7 @@ Connection::Private::Private(Connection *parent)
       status(Connection::StatusUnknown),
       statusReason(ConnectionStatusReasonNoneSpecified),
       selfHandle(0),
+      contactListsChannelsReady(0),
       handleContext(0),
       contactManager(new ContactManager(parent))
 {
@@ -191,6 +197,14 @@ Connection::Private::Private(Connection *parent)
         this);
     introspectables[FeatureSimplePresence] = introspectableSimplePresence;
 
+    ReadinessHelper::Introspectable introspectableRoster(
+        QSet<uint>() << Connection::StatusConnected,                                   // makesSenseForStatuses
+        QSet<uint>() << 0,                                                             // dependsOnFeatures (core)
+        QStringList() << TELEPATHY_INTERFACE_CONNECTION_INTERFACE_CONTACTS,            // dependsOnInterfaces
+        (ReadinessHelper::IntrospectFunc) &Private::introspectRoster,
+        this);
+    introspectables[FeatureRoster] = introspectableRoster;
+
     readinessHelper = new ReadinessHelper(parent, status,
             introspectables, parent);
     parent->connect(readinessHelper,
@@ -353,6 +367,26 @@ void Connection::Private::introspectSelfHandle()
                     SLOT(gotSelfHandle(QDBusPendingCallWatcher *)));
 }
 
+void Connection::Private::introspectRoster(Connection::Private *self)
+{
+    debug() << "Requesting handles for contact lists";
+
+    QStringList ids;
+    for (uint i = 0; i < ContactManager::ContactListChannel::LastType; ++i) {
+        self->contactListsChannels.insert(i,
+                ContactManager::ContactListChannel(
+                    (ContactManager::ContactListChannel::Type) i));
+        ids << ContactManager::ContactListChannel::identifierForType(
+                (ContactManager::ContactListChannel::Type) i);
+    }
+
+    PendingHandles *pending = self->parent->requestHandles(
+            Telepathy::HandleTypeList, ids);
+    self->parent->connect(pending,
+            SIGNAL(finished(Telepathy::Client::PendingOperation*)),
+            SLOT(gotContactListsHandles(Telepathy::Client::PendingOperation*)));
+}
+
 Connection::PendingConnect::PendingConnect(Connection *parent, const QSet<uint> &requestedFeatures)
     : PendingOperation(parent),
       requestedFeatures(requestedFeatures)
@@ -897,6 +931,79 @@ void Connection::gotSelfHandle(QDBusPendingCallWatcher *watcher)
     watcher->deleteLater();
 }
 
+void Connection::gotContactListsHandles(PendingOperation *op)
+{
+    if (op->isError()) {
+        // let's not fail, because the contact lists are not supported
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureRoster, true);
+        return;
+    }
+
+    debug() << "Got handles for contact lists";
+    PendingHandles *pending = qobject_cast<PendingHandles*>(op);
+
+    debug() << "Requesting channels for contact lists";
+    QVariantMap request;
+    request.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType"),
+                   TELEPATHY_INTERFACE_CHANNEL_TYPE_CONTACT_LIST);
+    request.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"),
+                   Telepathy::HandleTypeList);
+
+    ReferencedHandles handles = pending->handles();
+    uint handle;
+    for (int i = 0; i < ContactManager::ContactListChannel::LastType; ++i) {
+        handle = handles[i];
+
+        if (handle == 0) {
+            debug() << "Unable to request handle for contact list" <<
+                ContactManager::ContactListChannel::identifierForType(
+                        (ContactManager::ContactListChannel::Type) i);
+            // let's not fail, because the contact lists are not supported
+            contactListChannelReady();
+            continue;
+        }
+
+        mPriv->contactListsChannels[i].handle = handle;
+        request[QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle")] = handle;
+
+        connect(ensureChannel(request),
+                SIGNAL(finished(Telepathy::Client::PendingOperation*)),
+                SLOT(gotContactListChannel(Telepathy::Client::PendingOperation*)));
+    }
+}
+
+void Connection::gotContactListChannel(PendingOperation *op)
+{
+    if (op->isError()) {
+        contactListChannelReady();
+        return;
+    }
+
+    PendingChannel *pending = qobject_cast<PendingChannel*>(op);
+    QSharedPointer<Channel> channel = pending->channel();
+    uint handle = pending->handle();
+    Q_ASSERT(!channel.isNull());
+    Q_ASSERT(handle);
+    for (int i = 0; i < ContactManager::ContactListChannel::LastType; ++i) {
+        if (mPriv->contactListsChannels[i].handle == handle) {
+            Q_ASSERT(mPriv->contactListsChannels[i].channel.isNull());
+            mPriv->contactListsChannels[i].channel = channel;
+            connect(channel->becomeReady(),
+                    SIGNAL(finished(Telepathy::Client::PendingOperation *)),
+                    SLOT(contactListChannelReady()));
+        }
+    }
+}
+
+void Connection::contactListChannelReady()
+{
+    if (++mPriv->contactListsChannelsReady ==
+            ContactManager::ContactListChannel::LastType) {
+        mPriv->contactManager->setContactListChannels(mPriv->contactListsChannels);
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureRoster, true);
+    }
+}
+
 /**
  * Get the ConnectionInterface for this Connection. This
  * method is protected since the convenience methods provided by this
diff --git a/TelepathyQt4/Client/connection.h b/TelepathyQt4/Client/connection.h
index 38033bf..48dd5dd 100644
--- a/TelepathyQt4/Client/connection.h
+++ b/TelepathyQt4/Client/connection.h
@@ -66,6 +66,7 @@ public:
         FeatureCore = 0,
         FeatureSelfContact = 1,
         FeatureSimplePresence = 2,
+        FeatureRoster = 4,
         _Padding = 0xFFFFFFFF
     };
     Q_DECLARE_FLAGS(Features, Feature)
@@ -198,6 +199,9 @@ private Q_SLOTS:
     void gotSimpleStatuses(QDBusPendingCallWatcher *watcher);
     void gotSelfContact(Telepathy::Client::PendingOperation *);
     void gotSelfHandle(QDBusPendingCallWatcher *watcher);
+    void gotContactListsHandles(Telepathy::Client::PendingOperation *);
+    void gotContactListChannel(Telepathy::Client::PendingOperation *);
+    void contactListChannelReady();
 
     void doReleaseSweep(uint type);
 
diff --git a/TelepathyQt4/Client/contact-manager.cpp b/TelepathyQt4/Client/contact-manager.cpp
index 21b5d5f..ec20af4 100644
--- a/TelepathyQt4/Client/contact-manager.cpp
+++ b/TelepathyQt4/Client/contact-manager.cpp
@@ -74,6 +74,8 @@ struct ContactManager::Private
     void ensureTracking(Contact::Feature feature);
 
     QSet<Contact::Feature> supportedFeatures;
+
+    QMap<uint, ContactListChannel> contactListsChannels;
 };
 
 Connection *ContactManager::connection() const
@@ -140,6 +142,22 @@ QSet<Contact::Feature> ContactManager::supportedFeatures() const
     return mPriv->supportedFeatures;
 }
 
+PendingContacts *ContactManager::allKnownContacts(
+        const QSet<Contact::Feature> &features)
+{
+    QSet<QSharedPointer<Contact> > contacts;
+    foreach (const ContactListChannel &contactListChannel, mPriv->contactListsChannels) {
+        QSharedPointer<Channel> channel = contactListChannel.channel;
+        if (!channel) {
+            continue;
+        }
+        contacts.unite(channel->groupContacts().toSet());
+        contacts.unite(channel->groupLocalPendingContacts().toSet());
+        contacts.unite(channel->groupRemotePendingContacts().toSet());
+    }
+    return upgradeContacts(contacts.toList(), features);
+}
+
 PendingContacts *ContactManager::contactsForHandles(const UIntList &handles,
         const QSet<Contact::Feature> &features)
 {
@@ -296,6 +314,16 @@ QSharedPointer<Contact> ContactManager::ensureContact(const ReferencedHandles &h
     return contact;
 }
 
+void ContactManager::setContactListChannels(
+        const QMap<uint, ContactListChannel> &contactListsChannels)
+{
+    Q_ASSERT(mPriv->contactListsChannels.isEmpty());
+    mPriv->contactListsChannels = contactListsChannels;
+
+    // TODO update contacts subscription, publish state
+    //      connect to groupMembersChanged signal
+}
+
 QSharedPointer<Contact> ContactManager::Private::lookupContactByHandle(uint handle)
 {
     QSharedPointer<Contact> contact;
diff --git a/TelepathyQt4/Client/contact-manager.h b/TelepathyQt4/Client/contact-manager.h
index 917136c..e800aa1 100644
--- a/TelepathyQt4/Client/contact-manager.h
+++ b/TelepathyQt4/Client/contact-manager.h
@@ -34,6 +34,7 @@
 
 #include <TelepathyQt4/Types>
 #include <TelepathyQt4/Client/Contact>
+#include <TelepathyQt4/Client/Channel>
 
 namespace Telepathy
 {
@@ -55,6 +56,9 @@ class ContactManager : public QObject
         bool isSupported() const;
         QSet<Contact::Feature> supportedFeatures() const;
 
+        PendingContacts *allKnownContacts(
+                const QSet<Contact::Feature> &features = QSet<Contact::Feature>());
+
         PendingContacts *contactsForHandles(const UIntList &handles,
                 const QSet<Contact::Feature> &features = QSet<Contact::Feature>());
         PendingContacts *contactsForHandles(const ReferencedHandles &handles,
@@ -72,12 +76,51 @@ class ContactManager : public QObject
         void onPresencesChanged(const Telepathy::SimpleContactPresences &);
 
     private:
+        struct ContactListChannel
+        {
+            enum Type {
+                TypeSubscribe = 0,
+                TypePublish,
+                TypeStored,
+                LastType
+            };
+
+            ContactListChannel()
+                : type((Type) -1), handle(0)
+            {
+            }
+
+            ContactListChannel(Type type, uint handle = 0)
+                : type(type), handle(handle)
+            {
+            }
+
+            ~ContactListChannel()
+            {
+                channel.clear();
+            }
+
+            static QString identifierForType(Type type)
+            {
+                static QString identifiers[LastType] = {
+                    "subscribe", "publish", "stored"
+                };
+                return identifiers[type];
+            }
+
+            Type type;
+            uint handle;
+            QSharedPointer<Channel> channel;
+        };
+
         ContactManager(Connection *parent);
         ~ContactManager();
 
         QSharedPointer<Contact> ensureContact(const ReferencedHandles &handle,
                 const QSet<Contact::Feature> &features, const QVariantMap &attributes);
 
+        void setContactListChannels(const QMap<uint, ContactListChannel> &contactListsChannels);
+
         struct Private;
         friend struct Private;
         friend class Connection;
-- 
1.5.6.5




More information about the telepathy-commits mailing list