[Telepathy-commits] [telepathy-qt4/master] Add and test Connection::selfContact

Olli Salli olli.salli at collabora.co.uk
Wed Feb 4 23:20:32 PST 2009


This particular thing needed a lot of duct taping to work. I'm writing
an email on the particular issues with Connection's API and
implementation - when those are fixed, this should become a lot cleaner.
---
 TelepathyQt4/Client/connection.cpp      |   85 +++++++++++++++++++++++++------
 TelepathyQt4/Client/connection.h        |    5 ++
 TelepathyQt4/Client/contact-manager.cpp |    4 +-
 tests/dbus/contacts.cpp                 |   19 +++++++
 4 files changed, 96 insertions(+), 17 deletions(-)

diff --git a/TelepathyQt4/Client/connection.cpp b/TelepathyQt4/Client/connection.cpp
index ec82be2..dbd8af6 100644
--- a/TelepathyQt4/Client/connection.cpp
+++ b/TelepathyQt4/Client/connection.cpp
@@ -32,6 +32,7 @@
 #include <TelepathyQt4/Client/ContactManager>
 #include <TelepathyQt4/Client/PendingChannel>
 #include <TelepathyQt4/Client/PendingContactAttributes>
+#include <TelepathyQt4/Client/PendingContacts>
 #include <TelepathyQt4/Client/PendingFailure>
 #include <TelepathyQt4/Client/PendingHandles>
 #include <TelepathyQt4/Client/PendingVoidMethodCall>
@@ -42,6 +43,7 @@
 #include <QMutexLocker>
 #include <QPair>
 #include <QQueue>
+#include <QSharedPointer>
 #include <QString>
 #include <QTimer>
 #include <QtGlobal>
@@ -116,6 +118,7 @@ struct Connection::Private
     void introspectMain();
     void introspectContacts();
     void introspectSimplePresence();
+    void introspectSelfContact();
     void introspectSelfPresence();
     void introspectSelfHandle();
 
@@ -160,6 +163,7 @@ struct Connection::Private
     uint statusReason;
     bool haveInitialStatus;
     SimpleStatusSpecMap simplePresenceStatuses;
+    QSharedPointer<Contact> selfContact;
     SimplePresence selfPresence;
     QStringList contactAttributeInterfaces;
 
@@ -240,6 +244,10 @@ Connection::Private::Private(Connection *parent)
 
 Connection::Private::~Private()
 {
+    // Clear selfContact so its handle will be released cleanly before the handleContext
+    selfContact.clear();
+
+    // FIXME: This doesn't look right! In fact, looks absolutely horrendous.
     if (!handleContext) {
         // initial introspection is not done
         return;
@@ -359,6 +367,20 @@ void Connection::Private::introspectSimplePresence()
             SLOT(gotSimpleStatuses(QDBusPendingCallWatcher *)));
 }
 
+void Connection::Private::introspectSelfContact()
+{
+    debug() << "Building self contact";
+    // FIXME: these should be features when Connection is sanitized
+    PendingContacts *contacts = contactManager->contactsForHandles(
+            UIntList() << selfHandle,
+            QSet<Contact::Feature>() << Contact::FeatureAlias
+                                     << Contact::FeatureAvatarToken
+                                     << Contact::FeatureSimplePresence);
+    parent->connect(contacts,
+            SIGNAL(finished(Telepathy::Client::PendingOperation *)),
+            SLOT(gotSelfContact(Telepathy::Client::PendingOperation *)));
+}
+
 void Connection::Private::introspectSelfPresence()
 {
     if (!simplePresence) {
@@ -739,6 +761,17 @@ Telepathy::SimplePresence Connection::selfPresence() const
     return mPriv->selfPresence;
 }
 
+QSharedPointer<Contact> Connection::selfContact() const
+{
+    if (!isReady()) {
+        warning() << "Connection::selfContact() used before the connection is ready!";
+    }
+    // FIXME: add checks for the SelfContact feature having been requested when Connection features
+    // actually work sensibly and selfContact is made a feature
+
+    return mPriv->selfContact;
+}
+
 /**
  * \fn Connection::optionalInterface(InterfaceSupportedChecking check) const
  *
@@ -980,9 +1013,8 @@ void Connection::gotInterfaces(QDBusPendingCallWatcher *watcher)
         debug() << "Got reply to GetInterfaces():" << mPriv->interfaces;
         mPriv->interfaces = reply.value();
 
-        if (mPriv->pendingStatus == ConnectionStatusConnected
-                && mPriv->interfaces.contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_CONTACTS)) {
-            mPriv->introspectQueue.enqueue(&Private::introspectContacts);
+        if (mPriv->pendingStatus == ConnectionStatusConnected) {
+            mPriv->introspectQueue.enqueue(&Private::introspectSelfHandle);
         } else {
             debug() << "Connection basic functionality is ready";
             mPriv->ready = true;
@@ -1009,16 +1041,19 @@ void Connection::gotInterfaces(QDBusPendingCallWatcher *watcher)
 
 void Connection::gotContactAttributeInterfaces(QDBusPendingCallWatcher *watcher)
 {
+    QDBusPendingReply<QDBusVariant> reply = *watcher;
+
+    // This is junk, but need to do this to make ContactManager behave - ideally, the self contact
+    // wouldn't be core, but CAI would, so isReady(<nothing but core>) should return true already
+    // at this point, and ContactManager should be happy
     debug() << "Connection basic functionality is ready (Got CAI)";
     mPriv->ready = true;
 
-    QDBusPendingReply<QDBusVariant> reply = *watcher;
-
     if (!reply.isError()) {
         mPriv->contactAttributeInterfaces = qdbus_cast<QStringList>(reply.value().variant());
         debug() << "Got" << mPriv->contactAttributeInterfaces.size() << "contact attribute interfaces";
-    }
-    else {
+        mPriv->introspectQueue.enqueue(&Private::introspectSelfContact);
+    } else {
         warning().nospace() << "Getting contact attribute interfaces failed with " <<
             reply.error().name() << ":" << reply.error().message();
     }
@@ -1028,6 +1063,24 @@ void Connection::gotContactAttributeInterfaces(QDBusPendingCallWatcher *watcher)
     watcher->deleteLater();
 }
 
+void Connection::gotSelfContact(PendingOperation *op)
+{
+    PendingContacts *pending = qobject_cast<PendingContacts *>(op);
+
+    debug() << "Connection basic functionality is ready (Got SelfContact)";
+    mPriv->ready = true;
+
+    if (pending->isValid()) {
+        Q_ASSERT(pending->contacts().size() == 1);
+        mPriv->selfContact = pending->contacts()[0];
+    } else {
+        warning().nospace() << "Getting self contact failed with " <<
+            pending->errorName() << ":" << pending->errorMessage();
+    }
+
+    continueIntrospection();
+}
+
 void Connection::gotSimpleStatuses(QDBusPendingCallWatcher *watcher)
 {
     QDBusPendingReply<QDBusVariant> reply = *watcher;
@@ -1079,12 +1132,18 @@ void Connection::gotSelfHandle(QDBusPendingCallWatcher *watcher)
     if (!reply.isError()) {
         mPriv->selfHandle = reply.value();
         debug() << "Got self handle" << mPriv->selfHandle;
-    }
-    else {
+    } else {
         warning().nospace() << "Getting self handle failed with " <<
             reply.error().name() << ":" << reply.error().message();
     }
 
+    if (mPriv->interfaces.contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_CONTACTS)) {
+        mPriv->introspectQueue.enqueue(&Private::introspectContacts);
+    } else {
+        debug() << "Connection basic functionality is ready (Don't have Contacts)";
+        mPriv->ready = true;
+    }
+
     continueIntrospection();
 
     watcher->deleteLater();
@@ -1495,12 +1554,12 @@ PendingContactAttributes *Connection::getContactAttributes(const UIntList &handl
         warning() << "Connection::getContactAttributes() used when not ready";
         pending->failImmediately(TELEPATHY_ERROR_NOT_AVAILABLE, "The connection isn't ready");
         return pending;
-    } else if (status() != StatusConnected) {
+    } /* FIXME: readd this check when Connection isn't FSCKING broken anymore: else if (status() != StatusConnected) {
         warning() << "Connection::getContactAttributes() used with status" << status() << "!= StatusConnected";
         pending->failImmediately(TELEPATHY_ERROR_NOT_AVAILABLE,
                 "The connection isn't Connected");
         return pending;
-    } else if (!this->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_CONTACTS)) {
+    } */else if (!this->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_CONTACTS)) {
         warning() << "Connection::getContactAttributes() used without the remote object supporting"
                   << "the Contacts interface";
         pending->failImmediately(TELEPATHY_ERROR_NOT_IMPLEMENTED,
@@ -1639,8 +1698,6 @@ void Connection::continueIntrospection()
                 mPriv->readiness != Private::ReadinessFull) {
                 mPriv->changeReadiness(Private::ReadinessFull);
 
-                mPriv->introspectQueue.enqueue(&Private::introspectSelfHandle);
-
                 // we should have all interfaces now, so if an interface is not
                 // present and we have a feature for it, add the feature to missing
                 // features.
@@ -1657,8 +1714,6 @@ void Connection::continueIntrospection()
                         mPriv->introspectQueue.enqueue(&Private::introspectSelfPresence);
                     }
                 }
-
-                (mPriv->*(mPriv->introspectQueue.dequeue()))();
             }
         }
     }
diff --git a/TelepathyQt4/Client/connection.h b/TelepathyQt4/Client/connection.h
index 306d694..b96fd3e 100644
--- a/TelepathyQt4/Client/connection.h
+++ b/TelepathyQt4/Client/connection.h
@@ -35,6 +35,7 @@
 #include <TelepathyQt4/Constants>
 #include <TelepathyQt4/Types>
 
+#include <QSharedPointer>
 #include <QString>
 #include <QStringList>
 
@@ -44,6 +45,7 @@ namespace Client
 {
 
 class Channel;
+class Contact;
 class ContactManager;
 class PendingChannel;
 class PendingContactAttributes;
@@ -93,6 +95,8 @@ public:
     PendingOperation *setSelfPresence(const QString &status, const QString &statusMessage);
     Telepathy::SimplePresence selfPresence() const;
 
+    QSharedPointer<Contact> selfContact() const;
+
     template <class Interface>
     inline Interface *optionalInterface(
             InterfaceSupportedChecking check = CheckInterfaceSupported) const
@@ -183,6 +187,7 @@ private Q_SLOTS:
     void gotInterfaces(QDBusPendingCallWatcher *watcher);
     void gotContactAttributeInterfaces(QDBusPendingCallWatcher *watcher);
     void gotSimpleStatuses(QDBusPendingCallWatcher *watcher);
+    void gotSelfContact(Telepathy::Client::PendingOperation *);
     void gotSelfPresence(QDBusPendingCallWatcher *watcher);
     void gotSelfHandle(QDBusPendingCallWatcher *watcher);
 
diff --git a/TelepathyQt4/Client/contact-manager.cpp b/TelepathyQt4/Client/contact-manager.cpp
index 5a428c3..21b5d5f 100644
--- a/TelepathyQt4/Client/contact-manager.cpp
+++ b/TelepathyQt4/Client/contact-manager.cpp
@@ -86,10 +86,10 @@ bool ContactManager::isSupported() const
     if (!connection()->isReady()) {
         warning() << "ContactManager::isSupported() used before the connection is ready!";
         return false;
-    } else if (connection()->status() != Connection::StatusConnected) {
+    } /* 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);
 }
diff --git a/tests/dbus/contacts.cpp b/tests/dbus/contacts.cpp
index 172d41f..7ae3c58 100644
--- a/tests/dbus/contacts.cpp
+++ b/tests/dbus/contacts.cpp
@@ -42,6 +42,7 @@ private Q_SLOTS:
     void init();
 
     void testSupport();
+    void testSelfContact();
     void testForHandles();
     void testForIdentifiers();
     void testFeatures();
@@ -200,6 +201,24 @@ void TestContacts::testSupport()
     QVERIFY(supportedFeatures.contains(Contact::FeatureSimplePresence));
 }
 
+void TestContacts::testSelfContact()
+{
+    QSharedPointer<Contact> selfContact = mConn->selfContact();
+    QVERIFY(selfContact != 0);
+
+    QCOMPARE(selfContact->handle()[0], mConn->selfHandle());
+    QCOMPARE(selfContact->id(), QString("me at example.com"));
+
+    QCOMPARE(selfContact->alias(), QString("me at example.com"));
+
+    QVERIFY(!selfContact->isAvatarTokenKnown());
+
+    QCOMPARE(selfContact->presenceStatus(), QString("available"));
+    QCOMPARE(selfContact->presenceType(), uint(Telepathy::ConnectionPresenceTypeAvailable));
+    QCOMPARE(selfContact->presenceMessage(), QString(""));
+
+}
+
 void TestContacts::testForHandles()
 {
     Telepathy::UIntList handles;
-- 
1.5.6.5




More information about the telepathy-commits mailing list