[Telepathy-commits] [telepathy-qt4/master] Channel/TextChannel: Use Readiness helper class.

Andre Moreira Magalhaes (andrunko) andre.magalhaes at collabora.co.uk
Thu Mar 5 14:06:55 PST 2009


Use Readiness helper class on Channel/TextChannel and removed PendingReadyChannel.
---
 TelepathyQt4/Client/PendingReadyChannel       |   13 -
 TelepathyQt4/Client/channel.cpp               |  137 ++++----
 TelepathyQt4/Client/channel.h                 |   18 +-
 TelepathyQt4/Client/connection.cpp            |    1 -
 TelepathyQt4/Client/pending-ready-channel.cpp |  110 ------
 TelepathyQt4/Client/pending-ready-channel.h   |   63 ---
 TelepathyQt4/Client/text-channel.cpp          |  522 ++++++++++--------------
 TelepathyQt4/Client/text-channel.h            |   29 +-
 TelepathyQt4/Makefile.am                      |    4 -
 tests/dbus/chan-basics.cpp                    |    1 -
 tests/dbus/chan-group.cpp                     |    1 -
 tests/dbus/text-chan.cpp                      |   33 +-
 12 files changed, 327 insertions(+), 605 deletions(-)
 delete mode 100644 TelepathyQt4/Client/PendingReadyChannel
 delete mode 100644 TelepathyQt4/Client/pending-ready-channel.cpp
 delete mode 100644 TelepathyQt4/Client/pending-ready-channel.h

diff --git a/TelepathyQt4/Client/PendingReadyChannel b/TelepathyQt4/Client/PendingReadyChannel
deleted file mode 100644
index 3a5529e..0000000
--- a/TelepathyQt4/Client/PendingReadyChannel
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _TelepathyQt4_Client_PendingReadyChannel_HEADER_GUARD_
-#define _TelepathyQt4_Client_PendingReadyChannel_HEADER_GUARD_
-
-#ifndef IN_TELEPATHY_QT4_HEADER
-#define IN_TELEPATHY_QT4_HEADER
-#endif
-
-#include <TelepathyQt4/Client/pending-ready-channel.h>
-
-#undef IN_TELEPATHY_QT4_HEADER
-
-#endif
-// vim:set ft=cpp:
diff --git a/TelepathyQt4/Client/channel.cpp b/TelepathyQt4/Client/channel.cpp
index 0a8ee5a..0a8685a 100644
--- a/TelepathyQt4/Client/channel.cpp
+++ b/TelepathyQt4/Client/channel.cpp
@@ -31,7 +31,7 @@
 #include <TelepathyQt4/Client/PendingContacts>
 #include <TelepathyQt4/Client/PendingFailure>
 #include <TelepathyQt4/Client/PendingOperation>
-#include <TelepathyQt4/Client/PendingReadyChannel>
+#include <TelepathyQt4/Client/PendingReady>
 #include <TelepathyQt4/Client/PendingSuccess>
 #include <TelepathyQt4/Client/ReferencedHandles>
 #include <TelepathyQt4/Constants>
@@ -69,7 +69,7 @@ struct Channel::Private
     Private(Channel *parent, Connection *connection);
     ~Private();
 
-    void introspectMain();
+    static void introspectMain(Private *self);
     void introspectMainFallbackChannelType();
     void introspectMainFallbackHandle();
     void introspectMainFallbackInterfaces();
@@ -109,15 +109,12 @@ struct Channel::Private
     ChannelInterfaceGroupInterface *group;
     DBus::PropertiesInterface *properties;
 
-    bool ready;
-    PendingReadyChannel *pendingReady;
+    ReadinessHelper *readinessHelper;
 
     // Introspection
     QStringList interfaces;
     QQueue<void (Private::*)()> introspectQueue;
 
-    Channel::Features features;
-
     // Introspected properties
 
     // Main interface
@@ -207,9 +204,6 @@ Channel::Private::Private(Channel *parent, Connection *connection)
       connection(connection),
       group(0),
       properties(0),
-      ready(false),
-      pendingReady(0),
-      features(0),
       targetHandleType(0),
       targetHandle(0),
       requested(false),
@@ -224,7 +218,7 @@ Channel::Private::Private(Channel *parent, Connection *connection)
       groupIsSelfHandleTracked(false),
       groupSelfHandle(0)
 {
-    debug() << "Creating new Channel";
+    debug() << "Creating new Channel:" << parent->busName();
 
     if (connection->isValid()) {
         debug() << " Connecting to Channel::Closed() signal";
@@ -248,6 +242,21 @@ Channel::Private::Private(Channel *parent, Connection *connection)
         parent->invalidate(TELEPATHY_ERROR_INVALID_ARGUMENT,
                    "Connection given as the owner of this channel was invalid");
     }
+
+    ReadinessHelper::Introspectables introspectables;
+
+    // As Channel does not have predefined statuses let's simulate one (0)
+    ReadinessHelper::Introspectable introspectableCore(
+        QSet<uint>() << 0,                                           // makesSenseForStatuses
+        Features(),                                                  // dependsOnFeatures
+        QStringList(),                                               // dependsOnInterfaces
+        (ReadinessHelper::IntrospectFunc) &Private::introspectMain,
+        this);
+    introspectables[FeatureCore] = introspectableCore;
+
+    readinessHelper = new ReadinessHelper(parent, 0 /* status */,
+            introspectables, parent);
+    readinessHelper->becomeReady(Features() << FeatureCore);
 }
 
 Channel::Private::~Private()
@@ -258,20 +267,21 @@ Channel::Private::~Private()
     }
 }
 
-void Channel::Private::introspectMain()
+void Channel::Private::introspectMain(Channel::Private *self)
 {
-    if (!properties) {
-        properties = parent->propertiesInterface();
-        Q_ASSERT(properties != 0);
+    if (!self->properties) {
+        self->properties = self->parent->propertiesInterface();
+        Q_ASSERT(self->properties != 0);
     }
 
     debug() << "Calling Properties::GetAll(Channel)";
     QDBusPendingCallWatcher *watcher =
         new QDBusPendingCallWatcher(
-                properties->GetAll(TELEPATHY_INTERFACE_CHANNEL), parent);
-    parent->connect(watcher,
-                    SIGNAL(finished(QDBusPendingCallWatcher*)),
-                    SLOT(gotMainProperties(QDBusPendingCallWatcher*)));
+                self->properties->GetAll(TELEPATHY_INTERFACE_CHANNEL),
+                self->parent);
+    self->parent->connect(watcher,
+            SIGNAL(finished(QDBusPendingCallWatcher*)),
+            SLOT(gotMainProperties(QDBusPendingCallWatcher*)));
 }
 
 void Channel::Private::introspectMainFallbackChannelType()
@@ -492,7 +502,7 @@ void Channel::Private::nowHaveInterfaces()
 void Channel::Private::nowHaveInitialMembers()
 {
     // Must be called with no contacts anywhere in the first place
-    Q_ASSERT(!ready);
+    Q_ASSERT(!parent->isReady());
     Q_ASSERT(!buildingContacts);
 
     Q_ASSERT(pendingGroupMembers.isEmpty());
@@ -626,7 +636,7 @@ void Channel::Private::buildContacts()
     if (toBuild.isEmpty()) {
         if (!groupSelfHandle && groupSelfContact) {
             groupSelfContact.clear();
-            if (ready) {
+            if (parent->isReady()) {
                 emit parent->groupSelfContactChanged();
             }
         }
@@ -655,7 +665,7 @@ void Channel::Private::processMembersChanged()
             return;
         }
 
-        if (!ready) {
+        if (!parent->isReady()) {
             if (introspectQueue.isEmpty()) {
                 debug() << "Both the MCD and the introspect queue empty for the first time. Ready!";
 
@@ -827,7 +837,7 @@ void Channel::Private::updateContacts(const QList<QSharedPointer<Contact> > &con
         GroupMemberChangeDetails details(
                 actorContact,
                 currentGroupMembersChangedInfo->details);
-        if (ready) {
+        if (parent->isReady()) {
             // Channel is ready, we can signal membership changes to the outside world without
             // confusing anyone's fragile logic.
             emit parent->groupMembersChanged(
@@ -841,7 +851,7 @@ void Channel::Private::updateContacts(const QList<QSharedPointer<Contact> > &con
     delete currentGroupMembersChangedInfo;
     currentGroupMembersChangedInfo = 0;
 
-    if (selfContactUpdated && ready) {
+    if (selfContactUpdated && parent->isReady()) {
         emit parent->groupSelfContactChanged();
     }
 
@@ -876,15 +886,7 @@ bool Channel::Private::fakeGroupInterfaceIfNeeded()
 
 void Channel::Private::setReady()
 {
-    Q_ASSERT(!ready);
-
-    ready = true;
-
-    if (pendingReady) {
-        pendingReady->setFinished();
-        // it will delete itself later
-        pendingReady = 0;
-    }
+    Q_ASSERT(!parent->isReady());
 
     debug() << "Channel fully ready";
     debug() << " Channel type" << channelType;
@@ -909,6 +911,8 @@ void Channel::Private::setReady()
         debug() << " Group: Self handle" << groupSelfHandle <<
             "tracked:" << (groupIsSelfHandleTracked ? "yes" : "no");
     }
+
+    readinessHelper->setIntrospectCompleted(FeatureCore, true);
 }
 
 /**
@@ -945,6 +949,8 @@ void Channel::Private::setReady()
  * will transition to closed too.
  */
 
+const Feature Channel::FeatureCore = Feature(Channel::staticMetaObject.className(), 0);
+
 /**
  * Construct a new Channel object.
  *
@@ -968,11 +974,6 @@ Channel::Channel(Connection *connection,
     // FIXME: remember the immutableProperties, and use them to reduce the
     // number of D-Bus calls we need to make (but we should make at least
     // one, to check that the channel does in fact exist)
-    // no need to start introspection if channel is invalid
-    if (isValid()) {
-        mPriv->introspectQueue.enqueue(&Private::introspectMain);
-        QTimer::singleShot(0, this, SLOT(continueIntrospection()));
-    }
 }
 
 /**
@@ -1109,10 +1110,12 @@ QSharedPointer<Contact> Channel::initiatorContact() const
  * \return \c true if the object has finished its initial setup for basic
  *         functionality plus the given features
  */
-bool Channel::isReady(Features features) const
+bool Channel::isReady(const Features &features) const
 {
-    return mPriv->ready
-        && ((mPriv->features & features) == features);
+    if (features.isEmpty()) {
+        return mPriv->readinessHelper->isReady(Features() << FeatureCore, true);
+    }
+    return mPriv->readinessHelper->isReady(features, features.contains(FeatureCore));
 }
 
 /**
@@ -1120,41 +1123,35 @@ bool Channel::isReady(Features features) const
  * its initial setup, or will fail if a fatal error occurs during this
  * initial setup.
  *
+ * If an empty set is used FeatureCore will be considered as the requested
+ * feature.
+ *
  * \param requestedFeatures The features which should be enabled
- * \return A PendingReadyChannel object which will emit finished
+ * \return A PendingReady object which will emit finished
  *         when this object has finished or failed initial setup for basic
  *         functionality plus the given features
  */
-PendingReadyChannel *Channel::becomeReady(Features requestedFeatures)
+PendingReady *Channel::becomeReady(const Features &requestedFeatures)
 {
-    if (!isValid()) {
-        PendingReadyChannel *operation =
-            new PendingReadyChannel(requestedFeatures, this);
-        operation->setFinishedWithError(TELEPATHY_ERROR_NOT_AVAILABLE,
-                "Channel is invalid");
-        return operation;
+    if (requestedFeatures.isEmpty()) {
+        return mPriv->readinessHelper->becomeReady(Features() << FeatureCore);
     }
+    return mPriv->readinessHelper->becomeReady(requestedFeatures);
+}
 
-    if (isReady(requestedFeatures)) {
-        PendingReadyChannel *operation =
-            new PendingReadyChannel(requestedFeatures, this);
-        operation->setFinished();
-        return operation;
-    }
+Features Channel::requestedFeatures() const
+{
+    return mPriv->readinessHelper->requestedFeatures();
+}
 
-    if (requestedFeatures != 0) {
-        PendingReadyChannel *operation =
-            new PendingReadyChannel(requestedFeatures, this);
-        operation->setFinishedWithError(TELEPATHY_ERROR_INVALID_ARGUMENT,
-                "Invalid features argument");
-        return operation;
-    }
+Features Channel::actualFeatures() const
+{
+    return mPriv->readinessHelper->actualFeatures();
+}
 
-    if (!mPriv->pendingReady) {
-        mPriv->pendingReady =
-            new PendingReadyChannel(requestedFeatures, this);
-    }
-    return mPriv->pendingReady;
+Features Channel::missingFeatures() const
+{
+    return mPriv->readinessHelper->missingFeatures();
 }
 
 /**
@@ -1839,6 +1836,11 @@ void Channel::gotMainProperties(QDBusPendingCallWatcher *watcher)
     continueIntrospection();
 }
 
+ReadinessHelper *Channel::readinessHelper() const
+{
+    return mPriv->readinessHelper;
+}
+
 void Channel::gotChannelType(QDBusPendingCallWatcher *watcher)
 {
     QDBusPendingReply<QString> reply = *watcher;
@@ -2216,7 +2218,8 @@ void Channel::onSelfHandleChanged(uint newSelfHandle)
 void Channel::continueIntrospection()
 {
     if (mPriv->introspectQueue.isEmpty()) {
-        if (!mPriv->ready) {
+        // this should always be true, but let's make sure
+        if (!isReady()) {
             if (mPriv->groupMembersChangedQueue.isEmpty() && !mPriv->buildingContacts) {
                 debug() << "Both the IS and the MCD queue empty for the first time. Ready.";
                 mPriv->setReady();
diff --git a/TelepathyQt4/Client/channel.h b/TelepathyQt4/Client/channel.h
index c7ef61f..ee3dc7a 100644
--- a/TelepathyQt4/Client/channel.h
+++ b/TelepathyQt4/Client/channel.h
@@ -33,6 +33,7 @@
 #include <TelepathyQt4/Client/DBus>
 #include <TelepathyQt4/Client/DBusProxy>
 #include <TelepathyQt4/Client/OptionalInterfaceFactory>
+#include <TelepathyQt4/Client/ReadinessHelper>
 
 #include <QSet>
 #include <QSharedPointer>
@@ -47,7 +48,7 @@ namespace Client
 
 class Connection;
 class PendingOperation;
-class PendingReadyChannel;
+class PendingReady;
 
 class Channel : public StatefulDBusProxy,
                 private OptionalInterfaceFactory<Channel>
@@ -56,10 +57,7 @@ class Channel : public StatefulDBusProxy,
     Q_DISABLE_COPY(Channel)
 
 public:
-    enum Feature {
-        _Paddding = 0xFFFFFFFF
-    };
-    Q_DECLARE_FLAGS(Features, Feature)
+    static const Feature FeatureCore;
 
     Channel(Connection *connection,
             const QString &objectPath,
@@ -78,8 +76,12 @@ public:
     bool isRequested() const;
     QSharedPointer<Contact> initiatorContact() const;
 
-    bool isReady(Features features = 0) const;
-    PendingReadyChannel *becomeReady(Features features = 0);
+    virtual bool isReady(const Features &features = Features()) const;
+    virtual PendingReady *becomeReady(const Features &requestedFeatures = Features());
+
+    virtual Features requestedFeatures() const;
+    virtual Features actualFeatures() const;
+    virtual Features missingFeatures() const;
 
     PendingOperation *requestClose();
 
@@ -269,6 +271,8 @@ protected:
         return optionalInterface<ChannelInterfaceGroupInterface>(check);
     }
 
+    ReadinessHelper *readinessHelper() const;
+
 private Q_SLOTS:
     void gotMainProperties(QDBusPendingCallWatcher *watcher);
     void gotChannelType(QDBusPendingCallWatcher *watcher);
diff --git a/TelepathyQt4/Client/connection.cpp b/TelepathyQt4/Client/connection.cpp
index 5215923..d99c462 100644
--- a/TelepathyQt4/Client/connection.cpp
+++ b/TelepathyQt4/Client/connection.cpp
@@ -36,7 +36,6 @@
 #include <TelepathyQt4/Client/PendingFailure>
 #include <TelepathyQt4/Client/PendingHandles>
 #include <TelepathyQt4/Client/PendingReady>
-#include <TelepathyQt4/Client/PendingReadyChannel>
 #include <TelepathyQt4/Client/PendingVoidMethodCall>
 #include <TelepathyQt4/Client/ReferencedHandles>
 
diff --git a/TelepathyQt4/Client/pending-ready-channel.cpp b/TelepathyQt4/Client/pending-ready-channel.cpp
deleted file mode 100644
index c4ec9d8..0000000
--- a/TelepathyQt4/Client/pending-ready-channel.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * This file is part of TelepathyQt4
- *
- * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright (C) 2009 Nokia Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <TelepathyQt4/Client/PendingReadyChannel>
-
-#include "TelepathyQt4/Client/_gen/pending-ready-channel.moc.hpp"
-
-#include "TelepathyQt4/debug-internal.h"
-
-#include <QDBusPendingCallWatcher>
-#include <QDBusPendingReply>
-
-/**
- * \addtogroup clientsideproxies Client-side proxies
- *
- * Proxy objects representing remote service objects accessed via D-Bus.
- *
- * In addition to providing direct access to methods, signals and properties
- * exported by the remote objects, some of these proxies offer features like
- * automatic inspection of remote object capabilities, property tracking,
- * backwards compatibility helpers for older services and other utilities.
- */
-
-namespace Telepathy
-{
-namespace Client
-{
-
-struct PendingReadyChannel::Private
-{
-    Private(Channel::Features requestedFeatures, Channel *channel) :
-        requestedFeatures(requestedFeatures),
-        channel(channel)
-    {
-    }
-
-    Channel::Features requestedFeatures;
-    Channel *channel;
-};
-
-/**
- * \class PendingReadyChannel
- * \ingroup clientchannel
- * \headerfile <TelepathyQt4/Client/pending-ready-channel.h> <TelepathyQt4/Client/PendingReadyChannel>
- *
- * Class containing the features requested and the reply to a request
- * for a channel to become ready. Instances of this class cannot be
- * constructed directly; the only way to get one is via Channel::becomeReady().
- */
-
-/**
- * Construct a PendingReadyChannel object.
- *
- * \param channel The Channel that will become ready.
- */
-PendingReadyChannel::PendingReadyChannel(Channel::Features requestedFeatures, Channel *channel)
-    : PendingOperation(channel),
-      mPriv(new Private(requestedFeatures, channel))
-{
-}
-
-/**
- * Class destructor.
- */
-PendingReadyChannel::~PendingReadyChannel()
-{
-    delete mPriv;
-}
-
-/**
- * Return the Channel object through which the request was made.
- *
- * \return Channel object.
- */
-Channel *PendingReadyChannel::channel() const
-{
-    return mPriv->channel;
-}
-
-/**
- * Return the Features that were requested to become ready on the
- * channel.
- *
- * \return Features.
- */
-Channel::Features PendingReadyChannel::requestedFeatures() const
-{
-    return mPriv->requestedFeatures;
-}
-
-} // Telepathy::Client
-} // Telepathy
diff --git a/TelepathyQt4/Client/pending-ready-channel.h b/TelepathyQt4/Client/pending-ready-channel.h
deleted file mode 100644
index 01e96e8..0000000
--- a/TelepathyQt4/Client/pending-ready-channel.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * This file is part of TelepathyQt4
- *
- * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright (C) 2009 Nokia Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef _TelepathyQt4_cli_pending_ready_channel_h_HEADER_GUARD_
-#define _TelepathyQt4_cli_pending_ready_channel_h_HEADER_GUARD_
-
-#ifndef IN_TELEPATHY_QT4_HEADER
-#error IN_TELEPATHY_QT4_HEADER
-#endif
-
-#include <TelepathyQt4/Client/Channel>
-#include <TelepathyQt4/Client/PendingOperation>
-
-class QDBusPendingCallWatcher;
-
-namespace Telepathy
-{
-namespace Client
-{
-
-class PendingReadyChannel : public PendingOperation
-{
-    Q_OBJECT
-
-public:
-    ~PendingReadyChannel();
-
-    Channel *channel() const;
-    Channel::Features requestedFeatures() const;
-
-private:
-    Q_DISABLE_COPY(PendingReadyChannel);
-    PendingReadyChannel(Channel::Features requestedFeatures, Channel *channel);
-
-    struct Private;
-    friend struct Private;
-    friend class Channel;
-    friend class TextChannel;
-    Private *mPriv;
-};
-
-} // Telepathy::Client
-} // Telepathy
-
-#endif
diff --git a/TelepathyQt4/Client/text-channel.cpp b/TelepathyQt4/Client/text-channel.cpp
index 28c5471..906258e 100644
--- a/TelepathyQt4/Client/text-channel.cpp
+++ b/TelepathyQt4/Client/text-channel.cpp
@@ -28,7 +28,7 @@
 #include <TelepathyQt4/Client/ContactManager>
 #include <TelepathyQt4/Client/Message>
 #include <TelepathyQt4/Client/PendingContacts>
-#include <TelepathyQt4/Client/PendingReadyChannel>
+#include <TelepathyQt4/Client/PendingReady>
 #include <TelepathyQt4/Client/ReceivedMessage>
 #include <TelepathyQt4/Client/ReferencedHandles>
 
@@ -98,15 +98,25 @@ void PendingSendMessage::onMessageSent(QDBusPendingCallWatcher *watcher)
 
 struct TextChannel::Private
 {
-    inline Private();
-    inline ~Private();
+    Private(TextChannel *parent);
+    ~Private();
 
-    TextChannel::Features features;
-    TextChannel::Features pendingFeatures;
-    QList<PendingReadyChannel *> pendingReady;
-    void continueReadying(TextChannel *channel);
-    void failReadying(TextChannel *channel, const QString &error,
-            const QString &message);
+    static void introspectMessageQueue(Private *self);
+    static void introspectMessageCapabilities(Private *self);
+    static void introspectMessageSentSignal(Private *self);
+
+    void updateInitialMessages();
+    void updateCapabilities();
+
+    // Public object
+    TextChannel *parent;
+
+    ReadinessHelper *readinessHelper;
+
+    // FeatureMessageCapabilities and FeatureMessageQueue
+    QVariantMap props;
+    bool getAllInFlight;
+    bool gotProperties;
 
     // requires FeatureMessageCapabilities
     QStringList supportedContentTypes;
@@ -114,9 +124,6 @@ struct TextChannel::Private
     DeliveryReportingSupportFlags deliveryReportingSupport;
 
     // FeatureMessageQueue
-    bool connectedMessageQueueSignals;
-    bool getAllMessagesInFlight;
-    bool listPendingMessagesCalled;
     bool initialMessagesReceived;
     struct QueuedEvent
     {
@@ -140,27 +147,177 @@ struct TextChannel::Private
     void contactFound(QSharedPointer<Contact> contact);
 };
 
-TextChannel::Private::Private()
-    : features(0),
-      pendingFeatures(0),
-      pendingReady(),
-      supportedContentTypes(),
+TextChannel::Private::Private(TextChannel *parent)
+    : parent(parent),
+      readinessHelper(parent->readinessHelper()),
+      getAllInFlight(false),
+      gotProperties(false),
       messagePartSupport(0),
       deliveryReportingSupport(0),
-      connectedMessageQueueSignals(false),
-      getAllMessagesInFlight(false),
-      listPendingMessagesCalled(false),
-      initialMessagesReceived(false),
-      messages(),
-      incompleteMessages(),
-      awaitingContacts()
+      initialMessagesReceived(false)
 {
+    ReadinessHelper::Introspectables introspectables;
+
+    ReadinessHelper::Introspectable introspectableMessageQueue(
+        QSet<uint>() << 0,                                                      // makesSenseForStatuses
+        Features() << Channel::FeatureCore,                                     // dependsOnFeatures (core)
+        QStringList(),                                                          // dependsOnInterfaces
+        (ReadinessHelper::IntrospectFunc) &Private::introspectMessageQueue,
+        this);
+    introspectables[FeatureMessageQueue] = introspectableMessageQueue;
+
+    ReadinessHelper::Introspectable introspectableMessageCapabilities(
+        QSet<uint>() << 0,                                                      // makesSenseForStatuses
+        Features() << Channel::FeatureCore,                                     // dependsOnFeatures (core)
+        QStringList(),                                                          // dependsOnInterfaces
+        (ReadinessHelper::IntrospectFunc) &Private::introspectMessageCapabilities,
+        this);
+    introspectables[FeatureMessageCapabilities] = introspectableMessageCapabilities;
+
+    ReadinessHelper::Introspectable introspectableMessageSentSignal(
+        QSet<uint>() << 0,                                                      // makesSenseForStatuses
+        Features() << Channel::FeatureCore,                                     // dependsOnFeatures (core)
+        QStringList(),                                                          // dependsOnInterfaces
+        (ReadinessHelper::IntrospectFunc) &Private::introspectMessageSentSignal,
+        this);
+    introspectables[FeatureMessageSentSignal] = introspectableMessageSentSignal;
+
+    readinessHelper->addIntrospectables(introspectables);
 }
 
 TextChannel::Private::~Private()
 {
 }
 
+void TextChannel::Private::introspectMessageQueue(
+        TextChannel::Private *self)
+{
+    TextChannel *parent = self->parent;
+
+    if (parent->hasMessagesInterface()) {
+        // FeatureMessageQueue needs signal connections + Get (but we
+        // might as well do GetAll and reduce the number of code paths)
+        parent->connect(parent->messagesInterface(),
+                SIGNAL(MessageReceived(const Telepathy::MessagePartList &)),
+                SLOT(onMessageReceived(const Telepathy::MessagePartList &)));
+        parent->connect(parent->messagesInterface(),
+                SIGNAL(PendingMessagesRemoved(const Telepathy::UIntList &)),
+                SLOT(onPendingMessagesRemoved(const Telepathy::UIntList &)));
+
+        if (!self->gotProperties && !self->getAllInFlight) {
+            self->getAllInFlight = true;
+            QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
+                    parent->propertiesInterface()->GetAll(
+                        QLatin1String(TELEPATHY_INTERFACE_CHANNEL_INTERFACE_MESSAGES)),
+                        parent);
+            parent->connect(watcher,
+                    SIGNAL(finished(QDBusPendingCallWatcher *)),
+                    SLOT(gotProperties(QDBusPendingCallWatcher *)));
+        } else if (self->gotProperties) {
+            self->updateInitialMessages();
+        }
+    } else {
+        // FeatureMessageQueue needs signal connections + ListPendingMessages
+        parent->connect(parent->textInterface(),
+                SIGNAL(Received(uint, uint, uint, uint, uint, const QString &)),
+                SLOT(onTextReceived(uint, uint, uint, uint, uint, const QString &)));
+
+        // we present SendError signals as if they were incoming
+        // messages, to be consistent with Messages
+        parent->connect(parent->textInterface(),
+                SIGNAL(SendError(uint, uint, uint, const QString &)),
+                SLOT(onTextSendError(uint, uint, uint, const QString &)));
+
+        QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
+                parent->textInterface()->ListPendingMessages(false), parent);
+        parent->connect(watcher,
+                SIGNAL(finished(QDBusPendingCallWatcher *)),
+                SLOT(gotPendingMessages(QDBusPendingCallWatcher *)));
+    }
+}
+
+void TextChannel::Private::introspectMessageCapabilities(
+        TextChannel::Private *self)
+{
+    TextChannel *parent = self->parent;
+
+    if (parent->hasMessagesInterface()) {
+        if (!self->gotProperties && !self->getAllInFlight) {
+            self->getAllInFlight = true;
+            QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
+                    parent->propertiesInterface()->GetAll(
+                        QLatin1String(TELEPATHY_INTERFACE_CHANNEL_INTERFACE_MESSAGES)),
+                        parent);
+            parent->connect(watcher,
+                    SIGNAL(finished(QDBusPendingCallWatcher *)),
+                    SLOT(gotProperties(QDBusPendingCallWatcher *)));
+        } else if (self->gotProperties) {
+            self->updateCapabilities();
+        }
+    } else {
+        self->supportedContentTypes =
+            (QStringList(QLatin1String("text/plain")));
+        parent->readinessHelper()->setIntrospectCompleted(
+                FeatureMessageCapabilities, true);
+    }
+}
+
+void TextChannel::Private::introspectMessageSentSignal(
+        TextChannel::Private *self)
+{
+    TextChannel *parent = self->parent;
+
+    if (parent->hasMessagesInterface()) {
+        parent->connect(parent->messagesInterface(),
+                SIGNAL(MessageSent(const Telepathy::MessagePartList &,
+                                   uint, const QString &)),
+                SLOT(onMessageSent(const Telepathy::MessagePartList &,
+                                   uint, const QString &)));
+    } else {
+        parent->connect(parent->textInterface(),
+                SIGNAL(Sent(uint, uint, const QString &)),
+                SLOT(onTextSent(uint, uint, const QString &)));
+    }
+
+    self->readinessHelper->setIntrospectCompleted(FeatureMessageSentSignal, true);
+}
+
+void TextChannel::Private::updateInitialMessages()
+{
+    if (!readinessHelper->requestedFeatures().contains(FeatureMessageQueue) ||
+        readinessHelper->isReady(Features() << FeatureMessageQueue, false)) {
+        return;
+    }
+
+    Q_ASSERT(!initialMessagesReceived);
+    initialMessagesReceived = true;
+
+    MessagePartListList messages = qdbus_cast<MessagePartListList>(
+            props["PendingMessages"]);
+    foreach (const MessagePartList &message, messages) {
+        parent->onMessageReceived(message);
+    }
+}
+
+void TextChannel::Private::updateCapabilities()
+{
+    if (!readinessHelper->requestedFeatures().contains(FeatureMessageCapabilities) ||
+        readinessHelper->isReady(Features() << FeatureMessageQueue, false)) {
+        return;
+    }
+
+    supportedContentTypes = qdbus_cast<QStringList>(
+            props["SupportedContentTypes"]);
+    if (supportedContentTypes.isEmpty()) {
+        supportedContentTypes << QLatin1String("text/plain");
+    }
+    messagePartSupport = MessagePartSupportFlags(qdbus_cast<uint>(
+            props["MessagePartSupportFlags"]));
+    deliveryReportingSupport = DeliveryReportingSupportFlags(
+            qdbus_cast<uint>(props["DeliveryReportingSupport"]));
+    readinessHelper->setIntrospectCompleted(FeatureMessageCapabilities, true);
+}
+
 /**
  * \class TextChannel
  * \ingroup clientchannel
@@ -174,25 +331,24 @@ TextChannel::Private::~Private()
  */
 
 /**
- * \enum TextChannel::Feature
- *
- * Features that can be enabled on a TextChannel using becomeReady().
- */
-/**
- * \var TextChannel::Feature TextChannel::FeatureMessageQueue
+ * \var Feature TextChannel::FeatureMessageQueue
  * The messageQueue method can be called, and the messageReceived and
  * pendingMessageRemoved methods can be called
  */
 /**
- * \var TextChannel::Feature TextChannel::FeatureMessageCapabilities
+ * \var Feature TextChannel::FeatureMessageCapabilities
  * The supportedContentTypes, messagePartSupport and deliveryReportingSupport
  * methods can be called
  */
 /**
- * \var TextChannel::Feature TextChannel::FeatureMessageSentSignal
+ * \var Feature TextChannel::FeatureMessageSentSignal
  * The messageSent signal will be emitted when a message is sent
  */
 
+const Feature TextChannel::FeatureMessageQueue = Feature(TextChannel::staticMetaObject.className(), 0);
+const Feature TextChannel::FeatureMessageCapabilities = Feature(TextChannel::staticMetaObject.className(), 1);
+const Feature TextChannel::FeatureMessageSentSignal = Feature(TextChannel::staticMetaObject.className(), 2);
+
 /**
  * \fn void TextChannel::messageSent(const Telepathy::Client::Message &message,
  *     Telepathy::MessageSendingFlags flags,
@@ -251,7 +407,7 @@ TextChannel::TextChannel(Connection *connection,
         const QVariantMap &immutableProperties,
         QObject *parent)
     : Channel(connection, objectPath, immutableProperties, parent),
-      mPriv(new Private())
+      mPriv(new Private(this))
 {
 }
 
@@ -508,228 +664,6 @@ PendingSendMessage *TextChannel::send(const MessagePartList &parts)
     return op;
 }
 
-/**
- * Return whether the desired features are ready for use.
- *
- * \param channelFeatures Features of the Channel class
- * \param textFeatures Features of the TextChannel class
- * \return true if basic Channel functionality, and all the requested features
- *         (if any), are ready for use
- */
-bool TextChannel::isReady(Channel::Features channelFeatures,
-        Features textFeatures) const
-{
-    debug() << "Checking whether ready:" << channelFeatures << textFeatures;
-    debug() << "Am I ready? mPriv->features =" << mPriv->features;
-    return Channel::isReady(channelFeatures) &&
-        ((mPriv->features & textFeatures) == textFeatures);
-}
-
-/**
- * Gather the necessary information to use the requested features.
- *
- * \param channelFeatures Features of the Channel class
- * \param textFeatures Features of the TextChannel class
- * \return A pending operation which will finish when basic Channel
- *         functionality, and all the requested features (if any), are ready
- *         for use
- */
-PendingReadyChannel *TextChannel::becomeReady(
-        Channel::Features channelFeatures,
-        Features textFeatures)
-{
-    PendingReadyChannel *textReady;
-
-    if (!isValid()) {
-        textReady = new PendingReadyChannel(channelFeatures, this);
-        textReady->setFinishedWithError(invalidationReason(),
-                invalidationMessage());
-        return textReady;
-    }
-
-    if (isReady(channelFeatures, textFeatures)) {
-        textReady = new PendingReadyChannel(channelFeatures, this);
-        textReady->setFinished();
-        return textReady;
-    }
-
-    if ((textFeatures & (FeatureMessageQueue |
-                    FeatureMessageCapabilities |
-                    FeatureMessageSentSignal))
-            != textFeatures) {
-        textReady = new PendingReadyChannel(channelFeatures, this);
-        textReady->setFinishedWithError(TELEPATHY_ERROR_INVALID_ARGUMENT,
-                "Invalid features argument");
-        return textReady;
-    }
-
-    PendingReadyChannel *channelReady = Channel::becomeReady(channelFeatures);
-
-    textReady = new PendingReadyChannel(channelFeatures, this);
-
-    connect(channelReady,
-            SIGNAL(finished(Telepathy::Client::PendingOperation *)),
-            this,
-            SLOT(onChannelReady(Telepathy::Client::PendingOperation *)));
-
-    mPriv->pendingReady.append(textReady);
-    mPriv->pendingFeatures |= (textFeatures & ~mPriv->features);
-    return textReady;
-}
-
-void TextChannel::onChannelReady(Telepathy::Client::PendingOperation *op)
-{
-    // Handle the error and insanity cases
-    if (op->isError()) {
-        mPriv->failReadying(this, op->errorName(), op->errorMessage());
-    }
-    if (channelType() != QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT)) {
-        mPriv->failReadying(this,
-                QLatin1String(TELEPATHY_ERROR_INVALID_ARGUMENT),
-                QLatin1String("TextChannel object with non-Text channel"));
-        return;
-    }
-
-    // Now that the basic Channel stuff is ready, we can know whether we have
-    // the Messages interface.
-
-    if (mPriv->pendingFeatures & FeatureMessageSentSignal) {
-        if (hasMessagesInterface()) {
-            connect(messagesInterface(),
-                    SIGNAL(MessageSent(const Telepathy::MessagePartList &,
-                            uint, const QString &)),
-                    this,
-                    SLOT(onMessageSent(const Telepathy::MessagePartList &,
-                            uint, const QString &)));
-        } else {
-            connect(textInterface(),
-                    SIGNAL(Sent(uint, uint, const QString &)),
-                    this,
-                    SLOT(onTextSent(uint, uint, const QString &)));
-        }
-
-        mPriv->features |= FeatureMessageSentSignal;
-        mPriv->pendingFeatures &= ~FeatureMessageSentSignal;
-    }
-
-    if (!hasMessagesInterface()) {
-        // For plain Text channels, FeatureMessageCapabilities is trivial to
-        // implement - we don't do anything special at all - so we might as
-        // well set it up even if the library user didn't actually care.
-        mPriv->supportedContentTypes =
-            (QStringList(QLatin1String("text/plain")));
-        mPriv->messagePartSupport = 0;
-        mPriv->deliveryReportingSupport = 0;
-        mPriv->features |= FeatureMessageCapabilities;
-        mPriv->pendingFeatures &= ~FeatureMessageCapabilities;
-    }
-
-    mPriv->continueReadying(this);
-}
-
-void TextChannel::Private::failReadying(TextChannel *channel,
-        const QString &error, const QString &message)
-{
-    QList<PendingReadyChannel *> ops = pendingReady;
-    pendingReady.clear();
-
-    foreach (PendingReadyChannel *op, ops) {
-        op->setFinishedWithError(error, message);
-    }
-    channel->invalidate(error, message);
-}
-
-void TextChannel::Private::continueReadying(TextChannel *channel)
-{
-    Q_ASSERT ((pendingFeatures & features) == 0);
-
-    if (pendingFeatures == 0) {
-        // everything we wanted is ready
-        QList<PendingReadyChannel *> ops = pendingReady;
-        pendingReady.clear();
-        foreach (PendingReadyChannel *op, ops) {
-            op->setFinished();
-        }
-        return;
-    }
-
-    // else there's more work to do yet
-
-    if (channel->hasMessagesInterface()) {
-        // FeatureMessageQueue needs signal connections + Get (but we
-        //  might as well do GetAll and reduce the number of code paths)
-        // FeatureMessageCapabilities needs GetAll
-        // FeatureMessageSentSignal already done
-
-        bool getAll = false;
-
-        if (pendingFeatures & TextChannel::FeatureMessageQueue) {
-            if (!connectedMessageQueueSignals) {
-                connectedMessageQueueSignals = true;
-                channel->connect(channel->messagesInterface(),
-                        SIGNAL(MessageReceived(const Telepathy::MessagePartList &)),
-                        SLOT(onMessageReceived(const Telepathy::MessagePartList &)));
-
-                channel->connect(channel->messagesInterface(),
-                        SIGNAL(PendingMessagesRemoved(const Telepathy::UIntList &)),
-                        SLOT(onPendingMessagesRemoved(const Telepathy::UIntList &)));
-            }
-
-            if (!initialMessagesReceived) {
-                getAll = true;
-            }
-        }
-
-        if (pendingFeatures & TextChannel::FeatureMessageCapabilities) {
-            getAll = true;
-        }
-
-        if (getAll && !getAllMessagesInFlight) {
-            getAllMessagesInFlight = true;
-            QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
-                    channel->propertiesInterface()->GetAll(
-                        QLatin1String(TELEPATHY_INTERFACE_CHANNEL_INTERFACE_MESSAGES)),
-                        channel);
-            channel->connect(watcher,
-                    SIGNAL(finished(QDBusPendingCallWatcher *)),
-                    SLOT(onGetAllMessagesReply(QDBusPendingCallWatcher *)));
-        }
-    } else {
-        // FeatureMessageQueue needs signal connections +
-        //  ListPendingMessages
-        // FeatureMessageCapabilities already done
-        // FeatureMessageSentSignal already done
-
-        if (pendingFeatures & TextChannel::FeatureMessageQueue) {
-            if (!connectedMessageQueueSignals) {
-                connectedMessageQueueSignals = true;
-
-                channel->connect(channel->textInterface(),
-                        SIGNAL(Received(uint, uint, uint, uint, uint,
-                                const QString &)),
-                        SLOT(onTextReceived(uint, uint, uint, uint, uint,
-                                const QString &)));
-
-                // we present SendError signals as if they were incoming
-                // messages, to be consistent with Messages
-                channel->connect(channel->textInterface(),
-                        SIGNAL(SendError(uint, uint, uint, const QString &)),
-                        SLOT(onTextSendError(uint, uint, uint, const QString &)));
-            }
-
-            if (!listPendingMessagesCalled) {
-                listPendingMessagesCalled = true;
-
-                QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
-                        channel->textInterface()->ListPendingMessages(false), channel);
-                channel->connect(watcher,
-                        SIGNAL(finished(QDBusPendingCallWatcher *)),
-                        SLOT(onListPendingMessagesReply(QDBusPendingCallWatcher *)));
-            }
-        }
-    }
-}
-
 void TextChannel::onMessageSent(const Telepathy::MessagePartList &parts,
         uint flags,
         const QString &sentMessageToken)
@@ -780,12 +714,11 @@ void TextChannel::processQueue()
     }
 
     if (mPriv->incompleteMessages.isEmpty()) {
-        if (mPriv->pendingFeatures & FeatureMessageQueue) {
+        if (mPriv->readinessHelper->requestedFeatures().contains(FeatureMessageQueue) &&
+            !mPriv->readinessHelper->isReady(Features() << FeatureMessageQueue, false)) {
             debug() << "incompleteMessages empty for the first time: "
                 "FeatureMessageQueue is now ready";
-            mPriv->features |= FeatureMessageQueue;
-            mPriv->pendingFeatures &= ~FeatureMessageQueue;
-            mPriv->continueReadying(this);
+            mPriv->readinessHelper->setIntrospectCompleted(FeatureMessageQueue, true);
         }
         return;
     }
@@ -1005,80 +938,61 @@ void TextChannel::onTextSendError(uint error, uint timestamp, uint type,
     parts << header;
 }
 
-void TextChannel::onGetAllMessagesReply(QDBusPendingCallWatcher *watcher)
+void TextChannel::gotProperties(QDBusPendingCallWatcher *watcher)
 {
-    Q_ASSERT(mPriv->getAllMessagesInFlight);
-    mPriv->getAllMessagesInFlight = false;
+    Q_ASSERT(mPriv->getAllInFlight);
+    mPriv->getAllInFlight = false;
+    mPriv->gotProperties = true;
 
     QDBusPendingReply<QVariantMap> reply = *watcher;
-    QVariantMap props;
-
-    if (!reply.isError()) {
-        debug() << "Properties::GetAll(Channel.Interface.Messages) returned";
-        props = reply.value();
-    } else {
+    if (reply.isError()) {
         warning().nospace() << "Properties::GetAll(Channel.Interface.Messages)"
             " failed with " << reply.error().name() << ": " <<
             reply.error().message();
-        // ... and act as though props had been empty
-    }
 
-    if (!mPriv->initialMessagesReceived &&
-        (mPriv->pendingFeatures & FeatureMessageQueue)) {
-        mPriv->initialMessagesReceived = true;
+        ReadinessHelper *readinessHelper = mPriv->readinessHelper;
+        if (readinessHelper->requestedFeatures().contains(FeatureMessageQueue) &&
+            !readinessHelper->isReady(Features() << FeatureMessageQueue, false)) {
+            readinessHelper->setIntrospectCompleted(FeatureMessageQueue, false);
+        }
 
-        MessagePartListList messages = qdbus_cast<MessagePartListList>(
-                props["PendingMessages"]);
-        foreach (const MessagePartList &message, messages) {
-            onMessageReceived(message);
+        if (readinessHelper->requestedFeatures().contains(FeatureMessageCapabilities) &&
+            !readinessHelper->isReady(Features() << FeatureMessageCapabilities, false)) {
+            readinessHelper->setIntrospectCompleted(FeatureMessageCapabilities, false);
         }
+        return;
     }
 
-    // Since we have the capabilities, we might as well set them - doing this
-    // multiple times is a no-op
-
-    mPriv->supportedContentTypes = qdbus_cast<QStringList>(
-            props["SupportedContentTypes"]);
-    if (mPriv->supportedContentTypes.isEmpty()) {
-        mPriv->supportedContentTypes << QLatin1String("text/plain");
-    }
-    mPriv->messagePartSupport = MessagePartSupportFlags(qdbus_cast<uint>(
-            props["MessagePartSupportFlags"]));
-    mPriv->deliveryReportingSupport = DeliveryReportingSupportFlags(
-            qdbus_cast<uint>(props["DeliveryReportingSupport"]));
+    debug() << "Properties::GetAll(Channel.Interface.Messages) returned";
+    mPriv->props = reply.value();
 
-    mPriv->features |= FeatureMessageCapabilities;
-    mPriv->pendingFeatures &= ~FeatureMessageCapabilities;
-    mPriv->continueReadying(this);
+    mPriv->updateInitialMessages();
+    mPriv->updateCapabilities();
 }
 
-void TextChannel::onListPendingMessagesReply(QDBusPendingCallWatcher *watcher)
+void TextChannel::gotPendingMessages(QDBusPendingCallWatcher *watcher)
 {
     Q_ASSERT(!mPriv->initialMessagesReceived);
-    Q_ASSERT(mPriv->listPendingMessagesCalled);
-
     mPriv->initialMessagesReceived = true;
 
     QDBusPendingReply<PendingTextMessageList> reply = *watcher;
-    PendingTextMessageList list;
-
-    if (!reply.isError()) {
-        debug() << "Text::ListPendingMessages returned";
-        list = reply.value();
-    } else {
+    if (reply.isError()) {
         warning().nospace() << "Properties::GetAll(Channel.Interface.Messages)"
             " failed with " << reply.error().name() << ": " <<
             reply.error().message();
-        // ... and act as though list was empty
+
+        // TODO should we fail here?
+        mPriv->readinessHelper->setIntrospectCompleted(FeatureMessageQueue, false);
+        return;
     }
 
+    debug() << "Text::ListPendingMessages returned";
+    PendingTextMessageList list = reply.value();
     foreach (const PendingTextMessage &message, list) {
         onTextReceived(message.identifier, message.unixTimestamp,
                 message.sender, message.messageType, message.flags,
                 message.text);
     }
-
-    mPriv->continueReadying(this);
 }
 
 } // Telepathy::Client
diff --git a/TelepathyQt4/Client/text-channel.h b/TelepathyQt4/Client/text-channel.h
index c66de61..297af62 100644
--- a/TelepathyQt4/Client/text-channel.h
+++ b/TelepathyQt4/Client/text-channel.h
@@ -68,30 +68,17 @@ class TextChannel : public Channel
     Q_DISABLE_COPY(TextChannel)
 
 public:
+    static const Feature FeatureMessageQueue;
+    static const Feature FeatureMessageCapabilities;
+    static const Feature FeatureMessageSentSignal;
+
     TextChannel(Connection *connection, const QString &objectPath,
             const QVariantMap &immutableProperties, QObject *parent = 0);
     ~TextChannel();
 
-    enum Feature {
-        // FeatureMessageQueue guarantees that incoming messages go in
-        // messageQueue when their corresponding contact objects have been
-        // created, and that messageReceived will be emitted. If not enabled,
-        // messageReceived will not be emitted.
-        FeatureMessageQueue = 1,
-        FeatureMessageCapabilities = 2,
-        FeatureMessageSentSignal = 4,
-        _Padding = 0xFFFFFFFF
-    };
-    Q_DECLARE_FLAGS(Features, Feature)
-
     bool hasMessagesInterface() const;
     bool canInviteContacts() const;
 
-    bool isReady(Channel::Features channelFeatures = 0,
-            Features textFeatures = 0) const;
-    PendingReadyChannel *becomeReady(Channel::Features channelFeatures = 0,
-            Features textFeatures = 0);
-
     // requires FeatureMessageCapabilities
     QStringList supportedContentTypes() const;
     MessagePartSupportFlags messagePartSupport() const;
@@ -101,7 +88,6 @@ public:
     QList<ReceivedMessage> messageQueue() const;
 
 public Q_SLOTS:
-
     void acknowledge(const QList<ReceivedMessage> &messages);
 
     void forget(const QList<ReceivedMessage> &messages);
@@ -119,7 +105,6 @@ public Q_SLOTS:
     }
 
 Q_SIGNALS:
-
     // FeatureMessageSentSignal
     void messageSent(const Telepathy::Client::Message &message,
             Telepathy::MessageSendingFlags flags,
@@ -131,7 +116,6 @@ Q_SIGNALS:
             const Telepathy::Client::ReceivedMessage &message);
 
 private Q_SLOTS:
-    void onChannelReady(Telepathy::Client::PendingOperation *);
     void onContactsFinished(Telepathy::Client::PendingOperation *);
     void onAcknowledgePendingMessagesReply(QDBusPendingCallWatcher *);
 
@@ -139,12 +123,13 @@ private Q_SLOTS:
             const QString &);
     void onMessageReceived(const Telepathy::MessagePartList &);
     void onPendingMessagesRemoved(const Telepathy::UIntList &);
-    void onGetAllMessagesReply(QDBusPendingCallWatcher *);
 
     void onTextSent(uint, uint, const QString &);
     void onTextReceived(uint, uint, uint, uint, uint, const QString &);
     void onTextSendError(uint, uint, uint, const QString &);
-    void onListPendingMessagesReply(QDBusPendingCallWatcher *);
+
+    void gotProperties(QDBusPendingCallWatcher *);
+    void gotPendingMessages(QDBusPendingCallWatcher *);
 
 private:
     void processQueue();
diff --git a/TelepathyQt4/Makefile.am b/TelepathyQt4/Makefile.am
index ea5bb6b..72197e6 100644
--- a/TelepathyQt4/Makefile.am
+++ b/TelepathyQt4/Makefile.am
@@ -60,7 +60,6 @@ libtelepathy_qt4_la_SOURCES = \
     Client/pending-handles.cpp \
     Client/pending-operation.cpp \
     Client/pending-ready.cpp \
-    Client/pending-ready-channel.cpp \
     Client/pending-string-list.cpp \
     Client/properties.cpp \
     Client/readiness-helper.cpp \
@@ -115,7 +114,6 @@ nodist_libtelepathy_qt4_la_SOURCES = \
     Client/_gen/pending-handles.moc.hpp \
     Client/_gen/pending-operation.moc.hpp \
     Client/_gen/pending-ready.moc.hpp \
-    Client/_gen/pending-ready-channel.moc.hpp \
     Client/_gen/pending-string-list.moc.hpp \
     Client/_gen/readiness-helper.moc.hpp \
     Client/_gen/room-list.moc.hpp \
@@ -160,7 +158,6 @@ tpqt4clientinclude_HEADERS = \
     Client/PendingHandles \
     Client/PendingOperation \
     Client/PendingReady \
-    Client/PendingReadyChannel \
     Client/PendingSuccess \
     Client/PendingStringList \
     Client/PendingVoidMethodCall \
@@ -228,7 +225,6 @@ tpqt4clientinclude_HEADERS = \
     Client/pending-handles.h \
     Client/pending-operation.h \
     Client/pending-ready.h \
-    Client/pending-ready-channel.h \
     Client/pending-string-list.h \
     Client/properties.h \
     Client/readiness-helper.h \
diff --git a/tests/dbus/chan-basics.cpp b/tests/dbus/chan-basics.cpp
index 670bbd0..5d8bbd4 100644
--- a/tests/dbus/chan-basics.cpp
+++ b/tests/dbus/chan-basics.cpp
@@ -10,7 +10,6 @@
 #include <TelepathyQt4/Client/PendingChannel>
 #include <TelepathyQt4/Client/PendingHandles>
 #include <TelepathyQt4/Client/PendingReady>
-#include <TelepathyQt4/Client/PendingReadyChannel>
 #include <TelepathyQt4/Client/ReferencedHandles>
 #include <TelepathyQt4/Debug>
 
diff --git a/tests/dbus/chan-group.cpp b/tests/dbus/chan-group.cpp
index f9c9d93..13fe232 100644
--- a/tests/dbus/chan-group.cpp
+++ b/tests/dbus/chan-group.cpp
@@ -12,7 +12,6 @@
 #include <TelepathyQt4/Client/PendingContacts>
 #include <TelepathyQt4/Client/PendingHandles>
 #include <TelepathyQt4/Client/PendingReady>
-#include <TelepathyQt4/Client/PendingReadyChannel>
 #include <TelepathyQt4/Client/ReferencedHandles>
 #include <TelepathyQt4/Debug>
 
diff --git a/tests/dbus/text-chan.cpp b/tests/dbus/text-chan.cpp
index 9bed1b9..f7e2d06 100644
--- a/tests/dbus/text-chan.cpp
+++ b/tests/dbus/text-chan.cpp
@@ -7,7 +7,7 @@
 
 #include <TelepathyQt4/Client/Connection>
 #include <TelepathyQt4/Client/Message>
-#include <TelepathyQt4/Client/PendingReadyChannel>
+#include <TelepathyQt4/Client/PendingReady>
 #include <TelepathyQt4/Client/ReceivedMessage>
 #include <TelepathyQt4/Client/TextChannel>
 #include <TelepathyQt4/Debug>
@@ -204,10 +204,12 @@ void TestTextChan::commonTest(bool withMessages)
 
     QVERIFY(asChannel->isReady());
     QVERIFY(mChan->isReady());
-    QVERIFY(!mChan->isReady(0, TextChannel::FeatureMessageQueue));
+
+    Features features = Features() << TextChannel::FeatureMessageQueue;
+    QVERIFY(!mChan->isReady(features));
     // Implementation detail: in legacy text channels, capabilities arrive
     // early, so don't assert about that
-    QVERIFY(!mChan->isReady(0, TextChannel::FeatureMessageSentSignal));
+    QVERIFY(!mChan->isReady(features));
 
     QVERIFY(connect(mChan,
                 SIGNAL(messageReceived(const Telepathy::Client::ReceivedMessage &)),
@@ -230,15 +232,18 @@ void TestTextChan::commonTest(bool withMessages)
     sendText("One");
 
     // Make the Sent signal become ready
-    QVERIFY(connect(mChan->becomeReady(0, TextChannel::FeatureMessageSentSignal),
+    features = Features() << TextChannel::FeatureMessageSentSignal;
+    QVERIFY(connect(mChan->becomeReady(features),
                 SIGNAL(finished(Telepathy::Client::PendingOperation *)),
                 SLOT(expectSuccessfulCall(Telepathy::Client::PendingOperation *))));
     QCOMPARE(mLoop->exec(), 0);
 
     QVERIFY(asChannel->isReady());
     QVERIFY(mChan->isReady());
-    QVERIFY(mChan->isReady(0, TextChannel::FeatureMessageSentSignal));
-    QVERIFY(!mChan->isReady(0, TextChannel::FeatureMessageQueue));
+    features = Features() << TextChannel::FeatureMessageSentSignal;
+    QVERIFY(mChan->isReady(features));
+    features = Features() << TextChannel::FeatureMessageQueue;
+    QVERIFY(!mChan->isReady(features));
 
     sendText("Two");
 
@@ -263,15 +268,18 @@ void TestTextChan::commonTest(bool withMessages)
     QCOMPARE(m.text(), QString::fromAscii("Two"));
 
     // Make capabilities become ready
-    QVERIFY(connect(mChan->becomeReady(0, TextChannel::FeatureMessageCapabilities),
+    features = Features() << TextChannel::FeatureMessageCapabilities;
+    QVERIFY(connect(mChan->becomeReady(features),
                 SIGNAL(finished(Telepathy::Client::PendingOperation *)),
                 SLOT(expectSuccessfulCall(Telepathy::Client::PendingOperation *))));
     QCOMPARE(mLoop->exec(), 0);
 
     QVERIFY(asChannel->isReady());
     QVERIFY(mChan->isReady());
-    QVERIFY(mChan->isReady(0, TextChannel::FeatureMessageCapabilities));
-    QVERIFY(!mChan->isReady(0, TextChannel::FeatureMessageQueue));
+    features = Features() << TextChannel::FeatureMessageCapabilities;
+    QVERIFY(mChan->isReady(features));
+    features = Features() << TextChannel::FeatureMessageQueue;
+    QVERIFY(!mChan->isReady(features));
 
     if (withMessages) {
         QCOMPARE(mChan->supportedContentTypes(), QStringList() << "*/*");
@@ -288,15 +296,16 @@ void TestTextChan::commonTest(bool withMessages)
     // Make the message queue become ready too
     QCOMPARE(received.size(), 0);
     QCOMPARE(mChan->messageQueue().size(), 0);
-    QVERIFY(connect(mChan->becomeReady(0, TextChannel::FeatureMessageQueue),
+    features = Features() << TextChannel::FeatureMessageQueue;
+    QVERIFY(connect(mChan->becomeReady(features),
                 SIGNAL(finished(Telepathy::Client::PendingOperation *)),
                 SLOT(expectSuccessfulCall(Telepathy::Client::PendingOperation *))));
     QCOMPARE(mLoop->exec(), 0);
 
     QVERIFY(asChannel->isReady());
     QVERIFY(mChan->isReady());
-    QVERIFY(mChan->isReady(0, TextChannel::FeatureMessageQueue));
-    QVERIFY(mChan->isReady(0, TextChannel::FeatureMessageCapabilities));
+    features = Features() << TextChannel::FeatureMessageQueue << TextChannel::FeatureMessageCapabilities;
+    QVERIFY(mChan->isReady(features));
 
     // Assert that both our sent messages were echoed by the remote contact
     QCOMPARE(received.size(), 2);
-- 
1.5.6.5




More information about the telepathy-commits mailing list