[Telepathy-commits] [telepathy-qt4/master] Fixed bug 20583: Contact objects don't work without the Contacts interface.

Andre Moreira Magalhaes (andrunko) andre.magalhaes at collabora.co.uk
Wed Mar 25 10:19:30 PDT 2009


---
 TelepathyQt4/Client/connection.cpp       |    2 +-
 TelepathyQt4/Client/connection.h         |    1 +
 TelepathyQt4/Client/contact-manager.cpp  |   45 ++++--------
 TelepathyQt4/Client/pending-contacts.cpp |  110 +++++++++++++++++++++++++++++-
 TelepathyQt4/Client/pending-contacts.h   |    8 ++-
 TelepathyQt4/Client/referenced-handles.h |    1 +
 6 files changed, 133 insertions(+), 34 deletions(-)

diff --git a/TelepathyQt4/Client/connection.cpp b/TelepathyQt4/Client/connection.cpp
index efabe14..36d8a25 100644
--- a/TelepathyQt4/Client/connection.cpp
+++ b/TelepathyQt4/Client/connection.cpp
@@ -182,7 +182,7 @@ Connection::Private::Private(Connection *parent)
     ReadinessHelper::Introspectable introspectableSelfContact(
         QSet<uint>() << Connection::StatusConnected,                                   // makesSenseForStatuses
         Features() << FeatureCore,                                                     // dependsOnFeatures (core)
-        QStringList() << TELEPATHY_INTERFACE_CONNECTION_INTERFACE_CONTACTS,            // dependsOnInterfaces
+        QStringList(),                                                                 // dependsOnInterfaces
         (ReadinessHelper::IntrospectFunc) &Private::introspectSelfContact,
         this);
     introspectables[FeatureSelfContact] = introspectableSelfContact;
diff --git a/TelepathyQt4/Client/connection.h b/TelepathyQt4/Client/connection.h
index 3cd6928..8e1678d 100644
--- a/TelepathyQt4/Client/connection.h
+++ b/TelepathyQt4/Client/connection.h
@@ -212,6 +212,7 @@ private:
     friend class PendingChannel;
     friend class PendingConnect;
     friend class PendingContactAttributes;
+    friend class PendingContacts;
     friend class PendingHandles;
     friend class ReferencedHandles;
     Private *mPriv;
diff --git a/TelepathyQt4/Client/contact-manager.cpp b/TelepathyQt4/Client/contact-manager.cpp
index 859da76..6de1556 100644
--- a/TelepathyQt4/Client/contact-manager.cpp
+++ b/TelepathyQt4/Client/contact-manager.cpp
@@ -95,12 +95,9 @@ bool ContactManager::isSupported() const
     if (!connection()->isReady()) {
         warning() << "ContactManager::isSupported() used before the connection is ready!";
         return false;
-    } /* FIXME: readd this check when Connection is no longer a steaming pile of junk: else if (connection()->status() != Connection::StatusConnected) {
-        warning() << "ContactManager::isSupported() used before the connection is connected!";
-        return false;
-    } */
+    }
 
-    return connection()->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_CONTACTS);
+    return true;
 }
 
 namespace
@@ -135,7 +132,18 @@ QSet<Contact::Feature> ContactManager::supportedFeatures() const
             << Contact::FeatureAlias
             << Contact::FeatureAvatarToken
             << Contact::FeatureSimplePresence;
-        QStringList interfaces = mPriv->conn->contactAttributeInterfaces();
+        QStringList interfaces;
+        if (mPriv->conn->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_CONTACTS)) {
+            interfaces = mPriv->conn->contactAttributeInterfaces();
+        } else {
+            if (mPriv->conn->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_ALIASING)) {
+                interfaces.append(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_ALIASING);
+            } else if (mPriv->conn->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_AVATARS)) {
+                interfaces.append(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_AVATARS);
+            } else if (mPriv->conn->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE)) {
+                interfaces.append(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE);
+            }
+        }
 
         foreach (Contact::Feature feature, allFeatures) {
             if (interfaces.contains(featureToInterface(feature))) {
@@ -550,22 +558,8 @@ PendingContacts *ContactManager::contactsForHandles(const UIntList &handles,
     }
 
     PendingContacts *contacts =
-        new PendingContacts(this, handles, features, satisfyingContacts);
-
-    if (!otherContacts.isEmpty()) {
-        debug() << " Fetching" << interfaces.size() << "interfaces for"
-                               << otherContacts.size() << "contacts";
-
-        PendingContactAttributes *attributes =
-            mPriv->conn->getContactAttributes(otherContacts.toList(), interfaces.toList(), true);
-
-        contacts->connect(attributes,
-                SIGNAL(finished(Telepathy::Client::PendingOperation*)),
-                SLOT(onAttributesFinished(Telepathy::Client::PendingOperation*)));
-    } else {
-        contacts->allAttributesFetched();
-    }
-
+        new PendingContacts(this, handles, features, interfaces.toList(),
+                satisfyingContacts, otherContacts);
     return contacts;
 }
 
@@ -581,13 +575,7 @@ PendingContacts *ContactManager::contactsForIdentifiers(const QStringList &ident
     debug() << "Building contacts for" << identifiers.size() << "identifiers" << "with" << features.size()
         << "features";
 
-    PendingHandles *handles = mPriv->conn->requestHandles(HandleTypeContact, identifiers);
-
     PendingContacts *contacts = new PendingContacts(this, identifiers, features);
-    contacts->connect(handles,
-            SIGNAL(finished(Telepathy::Client::PendingOperation*)),
-            SLOT(onHandlesFinished(Telepathy::Client::PendingOperation*)));
-
     return contacts;
 }
 
@@ -979,6 +967,5 @@ uint ContactManager::ContactListChannel::typeForIdentifier(const QString &identi
     return (uint) -1;
 }
 
-
 }
 }
diff --git a/TelepathyQt4/Client/pending-contacts.cpp b/TelepathyQt4/Client/pending-contacts.cpp
index 43c34c8..e583191 100644
--- a/TelepathyQt4/Client/pending-contacts.cpp
+++ b/TelepathyQt4/Client/pending-contacts.cpp
@@ -22,6 +22,7 @@
 #include <TelepathyQt4/Client/PendingContacts>
 #include "TelepathyQt4/Client/_gen/pending-contacts.moc.hpp"
 
+#include <TelepathyQt4/Client/Connection>
 #include <TelepathyQt4/Client/ContactManager>
 #include <TelepathyQt4/Client/PendingContactAttributes>
 #include <TelepathyQt4/Client/PendingHandles>
@@ -92,6 +93,8 @@ struct PendingContacts::Private
     UIntList invalidHandles;
     QStringList validIds;
     QHash<QString, QPair<QString, QString> > invalidIds;
+
+    ReferencedHandles handlesToInspect;
 };
 
 /**
@@ -235,7 +238,7 @@ void PendingContacts::onAttributesFinished(PendingOperation *operation)
     allAttributesFetched();
 }
 
-void PendingContacts::onHandlesFinished(PendingOperation *operation)
+void PendingContacts::onRequestHandlesFinished(PendingOperation *operation)
 {
     PendingHandles *pendingHandles = qobject_cast<PendingHandles *>(operation);
 
@@ -259,6 +262,45 @@ void PendingContacts::onHandlesFinished(PendingOperation *operation)
             SLOT(onNestedFinished(Telepathy::Client::PendingOperation*)));
 }
 
+void PendingContacts::onReferenceHandlesFinished(PendingOperation *operation)
+{
+    PendingHandles *pendingHandles = qobject_cast<PendingHandles *>(operation);
+
+    debug() << "Reference Handles finished for" << this;
+
+    if (pendingHandles->isError()) {
+        debug() << " error" << operation->errorName()
+                << "message" << operation->errorMessage();
+        setFinishedWithError(operation->errorName(), operation->errorMessage());
+        return;
+    }
+
+    ReferencedHandles validHandles = pendingHandles->handles();
+    UIntList invalidHandles = pendingHandles->invalidHandles();
+    Connection *conn = mPriv->manager->connection();
+    mPriv->handlesToInspect = ReferencedHandles(conn, HandleTypeContact, UIntList());
+    foreach (uint handle, mPriv->handles) {
+        if (!mPriv->satisfyingContacts.contains(handle)) {
+            int indexInValid = validHandles.indexOf(handle);
+            if (indexInValid >= 0) {
+                ReferencedHandles referencedHandle = validHandles.mid(indexInValid, 1);
+                mPriv->handlesToInspect.append(referencedHandle);
+            } else {
+                mPriv->invalidHandles.push_back(handle);
+            }
+        }
+    }
+
+    QDBusPendingCallWatcher *watcher =
+        new QDBusPendingCallWatcher(
+                conn->baseInterface()->InspectHandles(HandleTypeContact,
+                    mPriv->handlesToInspect.toList()),
+                this);
+    connect(watcher,
+            SIGNAL(finished(QDBusPendingCallWatcher *)),
+            SLOT(onInspectHandlesFinished(QDBusPendingCallWatcher *)));
+}
+
 void PendingContacts::onNestedFinished(PendingOperation *operation)
 {
     Q_ASSERT(operation == mPriv->nested);
@@ -277,18 +319,82 @@ void PendingContacts::onNestedFinished(PendingOperation *operation)
     setFinished();
 }
 
+void PendingContacts::onInspectHandlesFinished(QDBusPendingCallWatcher *watcher)
+{
+    QDBusPendingReply<QStringList> reply = *watcher;
+
+    debug() << "Received reply to InspectHandles";
+
+    if (reply.isError()) {
+        debug().nospace() << " Failure: error " << reply.error().name() << ": "
+            << reply.error().message();
+        setFinishedWithError(reply.error());
+        return;
+    }
+
+    QStringList names = reply.value();
+    int i = 0;
+    Connection *conn = mPriv->manager->connection();
+    foreach (uint handle, mPriv->handlesToInspect) {
+        QVariantMap handleAttributes;
+        handleAttributes.insert(TELEPATHY_INTERFACE_CONNECTION "/contact-id", names[i++]);
+        ReferencedHandles referencedHandle(conn, HandleTypeContact,
+                UIntList() << handle);
+        mPriv->satisfyingContacts.insert(handle, manager()->ensureContact(referencedHandle,
+                    features(), handleAttributes));
+    }
+
+    allAttributesFetched();
+
+    watcher->deleteLater();
+}
+
 PendingContacts::PendingContacts(ContactManager *manager,
         const UIntList &handles, const QSet<Contact::Feature> &features,
-        const QMap<uint, ContactPtr> &satisfyingContacts)
+        const QStringList &interfaces,
+        const QMap<uint, ContactPtr> &satisfyingContacts,
+        const QSet<uint> &otherContacts)
     : PendingOperation(manager),
       mPriv(new Private(manager, handles, features, satisfyingContacts))
 {
+    if (!otherContacts.isEmpty()) {
+        debug() << " Fetching" << interfaces.size() << "interfaces for"
+                               << otherContacts.size() << "contacts";
+
+        Connection *conn = manager->connection();
+        if (conn->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_CONTACTS)) {
+            debug() << " Building contacts using contact attributes";
+            PendingContactAttributes *attributes =
+                conn->getContactAttributes(otherContacts.toList(),
+                        interfaces, true);
+
+            connect(attributes,
+                    SIGNAL(finished(Telepathy::Client::PendingOperation*)),
+                    SLOT(onAttributesFinished(Telepathy::Client::PendingOperation*)));
+        } else {
+            debug() << " Falling back to inspect contact handles";
+            // fallback to just create the contacts
+            PendingHandles *handles = conn->referenceHandles(HandleTypeContact,
+                    otherContacts.toList());
+            connect(handles,
+                    SIGNAL(finished(Telepathy::Client::PendingOperation*)),
+                    SLOT(onReferenceHandlesFinished(Telepathy::Client::PendingOperation*)));
+        }
+    } else {
+        allAttributesFetched();
+    }
 }
 
 PendingContacts::PendingContacts(ContactManager *manager,
         const QStringList &identifiers, const QSet<Contact::Feature> &features)
     : PendingOperation(manager), mPriv(new Private(manager, identifiers, features))
 {
+    Connection *conn = manager->connection();
+    PendingHandles *handles = conn->requestHandles(HandleTypeContact, identifiers);
+
+    connect(handles,
+            SIGNAL(finished(Telepathy::Client::PendingOperation*)),
+            SLOT(onRequestHandlesFinished(Telepathy::Client::PendingOperation*)));
 }
 
 PendingContacts::PendingContacts(ContactManager *manager,
diff --git a/TelepathyQt4/Client/pending-contacts.h b/TelepathyQt4/Client/pending-contacts.h
index 2d47f60..2fa6518 100644
--- a/TelepathyQt4/Client/pending-contacts.h
+++ b/TelepathyQt4/Client/pending-contacts.h
@@ -70,15 +70,19 @@ public:
 
 private Q_SLOTS:
     void onAttributesFinished(Telepathy::Client::PendingOperation *);
-    void onHandlesFinished(Telepathy::Client::PendingOperation *);
+    void onRequestHandlesFinished(Telepathy::Client::PendingOperation *);
+    void onReferenceHandlesFinished(Telepathy::Client::PendingOperation *);
     void onNestedFinished(Telepathy::Client::PendingOperation *);
+    void onInspectHandlesFinished(QDBusPendingCallWatcher *);
 
 private:
     Q_DISABLE_COPY(PendingContacts);
 
     PendingContacts(ContactManager *manager, const UIntList &handles,
             const QSet<Contact::Feature> &features,
-            const QMap<uint, ContactPtr> &satisfyingContacts);
+            const QStringList &interfaces,
+            const QMap<uint, ContactPtr> &satisfyingContacts,
+            const QSet<uint> &otherContacts);
     PendingContacts(ContactManager *manager, const QStringList &identifiers,
             const QSet<Contact::Feature> &features);
     PendingContacts(ContactManager *manager, const QList<ContactPtr> &contacts,
diff --git a/TelepathyQt4/Client/referenced-handles.h b/TelepathyQt4/Client/referenced-handles.h
index e539b0b..370ab00 100644
--- a/TelepathyQt4/Client/referenced-handles.h
+++ b/TelepathyQt4/Client/referenced-handles.h
@@ -283,6 +283,7 @@ class ReferencedHandles
     private:
         // For access to the "prime" constructor
         friend class PendingContactAttributes;
+        friend class PendingContacts;
         friend class PendingHandles;
 
         ReferencedHandles(Connection* connection, uint handleType, const UIntList& handles);
-- 
1.5.6.5




More information about the telepathy-commits mailing list