[Telepathy-commits] [telepathy-qt4/master] Return existing Contacts instead of always creating new ones if there are satisfying ones already in existence

Olli Salli olli.salli at collabora.co.uk
Fri Jan 30 10:02:58 PST 2009


---
 TelepathyQt4/Client/contact-manager.cpp  |   74 ++++++++++++++++++++++++++----
 TelepathyQt4/Client/contact-manager.h    |    7 +++
 TelepathyQt4/Client/pending-contacts.cpp |   38 +++++++++++----
 TelepathyQt4/Client/pending-contacts.h   |    7 ++-
 TelepathyQt4/Makefile.am                 |    1 +
 5 files changed, 106 insertions(+), 21 deletions(-)

diff --git a/TelepathyQt4/Client/contact-manager.cpp b/TelepathyQt4/Client/contact-manager.cpp
index 45735b9..14bff60 100644
--- a/TelepathyQt4/Client/contact-manager.cpp
+++ b/TelepathyQt4/Client/contact-manager.cpp
@@ -20,9 +20,12 @@
  */
 
 #include <TelepathyQt4/Client/ContactManager>
+#include "TelepathyQt4/Client/_gen/contact-manager.moc.hpp"
 
 #include <QMap>
 #include <QString>
+#include <QSet>
+#include <QWeakPointer>
 
 #include <TelepathyQt4/Client/Connection>
 #include <TelepathyQt4/Client/PendingContactAttributes>
@@ -64,6 +67,7 @@ namespace Client
 struct ContactManager::Private
 {
     Connection *conn;
+    QMap<uint, QWeakPointer<Contact> > contacts;
 };
 
 Connection *ContactManager::connection() const
@@ -104,20 +108,58 @@ PendingContacts *ContactManager::contactsForHandles(const UIntList &handles,
     debug() << "Building contacts for" << handles.size() << "handles" << "with" << features.size()
         << "features";
 
-    QSet<QString> interfaces;
-    foreach (Contact::Feature feature, features) {
-        if (true) { // TODO when not naive: if one or more of the contacts doesn't have the feature
-            interfaces.insert(featureToInterface(feature));
+    QMap<uint, QSharedPointer<Contact> > satisfyingContacts;
+    QSet<uint> otherContacts;
+    QSet<Contact::Feature> missingFeatures;
+
+    foreach (uint handle, handles) {
+        QSharedPointer<Contact> contact = mPriv->contacts[handle].toStrongRef();
+        if (contact) {
+            if (true /* TODO: contact->hasFeatures(features) */) {
+                // Contact exists and has all the requested features
+                satisfyingContacts.insert(handle, contact);
+            } else {
+                // Contact exists but is missing features
+                otherContacts.insert(handle);
+                missingFeatures.unite(features /* TODO:- contact->features() */);
+            }
+        } else {
+            // Contact doesn't exist - we need to get all of the features (same as unite(features))
+            missingFeatures = features;
+            // It might be a weak pointer with 0 refs, make sure to remove it
+            mPriv->contacts.remove(handle);
+            // In either case, the contact needs to be fetched
+            otherContacts.insert(handle);
         }
     }
 
-    PendingContactAttributes *attributes =
-        mPriv->conn->getContactAttributes(handles, interfaces.toList(), true);
+    debug() << " " << satisfyingContacts.size() << "satisfying and"
+                   << otherContacts.size() << "other contacts";
+    debug() << " " << missingFeatures.size() << "features missing";
 
-    PendingContacts *contacts = new PendingContacts(this, handles, features);
-    contacts->connect(attributes,
-            SIGNAL(finished(Telepathy::Client::PendingOperation*)),
-            SLOT(onAttributesFinished(Telepathy::Client::PendingOperation*)));
+    QSet<QString> interfaces;
+    foreach (Contact::Feature feature, missingFeatures) {
+        interfaces.insert(featureToInterface(feature));
+    }
+
+    PendingContacts *contacts = new PendingContacts(this, handles, features, satisfyingContacts);
+    connect(contacts,
+            SIGNAL(finished(Telepathy::Client::PendingOperation *)),
+            SLOT(onPendingContactsFinished(Telepathy::Client::PendingOperation *)));
+
+    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();
+    }
 
     return contacts;
 }
@@ -144,6 +186,18 @@ PendingContacts *ContactManager::contactsForIdentifiers(const QStringList &ident
     return contacts;
 }
 
+void ContactManager::onPendingContactsFinished(Telepathy::Client::PendingOperation *operation)
+{
+    PendingContacts *contacts = qobject_cast<PendingContacts *>(operation);
+
+    if (contacts->isValid()) {
+        debug() << this << "Caching" << contacts->contacts().size() << "contacts";
+        foreach (QSharedPointer<Contact> contact, contacts->contacts()) {
+            mPriv->contacts.insert(contact->handle()[0], contact);
+        }
+    }
+}
+
 ContactManager::ContactManager(Connection *parent)
     : QObject(parent), mPriv(new Private)
 {
diff --git a/TelepathyQt4/Client/contact-manager.h b/TelepathyQt4/Client/contact-manager.h
index cd0ce17..dd1727d 100644
--- a/TelepathyQt4/Client/contact-manager.h
+++ b/TelepathyQt4/Client/contact-manager.h
@@ -29,6 +29,7 @@
 #include <QObject>
 
 #include <QSet>
+#include <QSharedPointer>
 
 #include <TelepathyQt4/Types>
 #include <TelepathyQt4/Client/Contact>
@@ -40,9 +41,12 @@ namespace Client
 
 class Connection;
 class PendingContacts;
+class PendingOperation;
 
 class ContactManager : public QObject
 {
+    Q_OBJECT
+
     public:
 
         Connection *connection() const;
@@ -57,6 +61,9 @@ class ContactManager : public QObject
         PendingContacts *contactsForIdentifiers(const QStringList &identifiers,
                 const QSet<Contact::Feature> &features = QSet<Contact::Feature>());
 
+    private Q_SLOTS:
+        void onPendingContactsFinished(Telepathy::Client::PendingOperation *);
+
     private:
         ContactManager(Connection *parent);
         ~ContactManager();
diff --git a/TelepathyQt4/Client/pending-contacts.cpp b/TelepathyQt4/Client/pending-contacts.cpp
index d5188c2..91b8dc9 100644
--- a/TelepathyQt4/Client/pending-contacts.cpp
+++ b/TelepathyQt4/Client/pending-contacts.cpp
@@ -37,9 +37,11 @@ namespace Client
 struct PendingContacts::Private
 {
     Private(ContactManager *manager, const UIntList &handles,
-            const QSet<Contact::Feature> &features)
+            const QSet<Contact::Feature> &features,
+            const QMap<uint, QSharedPointer<Contact> > &satisfyingContacts)
         : manager(manager),
           features(features),
+          satisfyingContacts(satisfyingContacts),
           isForIdentifiers(false),
           handles(handles),
           nested(0)
@@ -58,6 +60,7 @@ struct PendingContacts::Private
 
     ContactManager *manager;
     QSet<Contact::Feature> features;
+    QMap<uint, QSharedPointer<Contact> > satisfyingContacts;
 
     bool isForIdentifiers;
     UIntList handles;
@@ -153,20 +156,23 @@ void PendingContacts::onAttributesFinished(PendingOperation *operation)
     }
 
     ReferencedHandles validHandles = pendingAttributes->validHandles();
-    mPriv->invalidHandles = pendingAttributes->invalidHandles();
     ContactAttributesMap attributes = pendingAttributes->attributes();
 
     debug() << " Success:" << validHandles.size() << "valid and"
                            << mPriv->invalidHandles.size() << "invalid handles";
 
-    for (int i = 0; i < validHandles.size(); i++) {
-        uint handle = validHandles[i];
-        ReferencedHandles referenced = validHandles.mid(i, 1);
-        mPriv->contacts.push_back(QSharedPointer<Contact>(new Contact(mPriv->manager, referenced,
-                        attributes[handle])));
+    foreach (uint handle, mPriv->handles) {
+        int indexInValid = validHandles.indexOf(handle);
+        if (indexInValid >= 0) {
+            ReferencedHandles referenced = validHandles.mid(indexInValid, 1);
+            mPriv->satisfyingContacts.insert(handle, QSharedPointer<Contact>(new Contact(
+                            mPriv->manager, referenced, attributes[handle])));
+        } else if (!mPriv->satisfyingContacts.contains(handle)) {
+            mPriv->invalidHandles.push_back(handle);
+        }
     }
 
-    setFinished();
+    allAttributesFetched();
 }
 
 void PendingContacts::onHandlesFinished(PendingOperation *operation)
@@ -209,9 +215,10 @@ void PendingContacts::onNestedFinished(PendingOperation *operation)
 }
 
 PendingContacts::PendingContacts(ContactManager *manager,
-        const UIntList &handles, const QSet<Contact::Feature> &features)
+        const UIntList &handles, const QSet<Contact::Feature> &features,
+        const QMap<uint, QSharedPointer<Contact> > &satisfyingContacts)
     : PendingOperation(manager),
-      mPriv(new Private(manager, handles, features))
+      mPriv(new Private(manager, handles, features, satisfyingContacts))
 {
 }
 
@@ -221,5 +228,16 @@ PendingContacts::PendingContacts(ContactManager *manager,
 {
 }
 
+void PendingContacts::allAttributesFetched()
+{
+    foreach (uint handle, mPriv->handles) {
+        if (mPriv->satisfyingContacts.contains(handle)) {
+            mPriv->contacts.push_back(mPriv->satisfyingContacts[handle]);
+        }
+    }
+
+    setFinished();
+}
+
 } // Telepathy::Client
 } // Telepathy
diff --git a/TelepathyQt4/Client/pending-contacts.h b/TelepathyQt4/Client/pending-contacts.h
index b19f6a6..2123ffe 100644
--- a/TelepathyQt4/Client/pending-contacts.h
+++ b/TelepathyQt4/Client/pending-contacts.h
@@ -29,6 +29,7 @@
 #include <TelepathyQt4/Client/PendingOperation>
 
 #include <QList>
+#include <QMap>
 #include <QSet>
 #include <QSharedPointer>
 #include <QStringList>
@@ -69,11 +70,15 @@ private Q_SLOTS:
 
 private:
     Q_DISABLE_COPY(PendingContacts);
+
     PendingContacts(ContactManager *manager, const UIntList &handles,
-            const QSet<Contact::Feature> &features);
+            const QSet<Contact::Feature> &features,
+            const QMap<uint, QSharedPointer<Contact> > &satisfyingContacts);
     PendingContacts(ContactManager *manager, const QStringList &identifiers,
             const QSet<Contact::Feature> &features);
 
+    void allAttributesFetched();
+
     struct Private;
     friend struct Private;
     friend class ContactManager;
diff --git a/TelepathyQt4/Makefile.am b/TelepathyQt4/Makefile.am
index fa50f82..77ef0c3 100644
--- a/TelepathyQt4/Makefile.am
+++ b/TelepathyQt4/Makefile.am
@@ -96,6 +96,7 @@ nodist_libtelepathy_qt4_la_SOURCES = \
     Client/_gen/connection-internal.moc.hpp \
     Client/_gen/connection-manager-internal.moc.hpp \
     Client/_gen/contact.moc.hpp \
+    Client/_gen/contact-manager.moc.hpp \
     Client/_gen/dbus-proxy.moc.hpp \
     Client/_gen/pending-account.moc.hpp \
     Client/_gen/pending-channel.moc.hpp \
-- 
1.5.6.5




More information about the telepathy-commits mailing list