[Telepathy-commits] [telepathy-qt4/master] Connection: Implement getSelfPresence.
Andre Moreira Magalhaes (andrunko)
andre.magalhaes at collabora.co.uk
Mon Jan 26 08:53:26 PST 2009
---
TelepathyQt4/Client/connection.cpp | 172 +++++++++++++++++++++++++++++++++++-
TelepathyQt4/Client/connection.h | 8 ++
2 files changed, 179 insertions(+), 1 deletions(-)
diff --git a/TelepathyQt4/Client/connection.cpp b/TelepathyQt4/Client/connection.cpp
index 91b5535..864b350 100644
--- a/TelepathyQt4/Client/connection.cpp
+++ b/TelepathyQt4/Client/connection.cpp
@@ -111,11 +111,15 @@ struct Connection::Private
void startIntrospection();
void introspectMain();
void introspectSimplePresence();
+ void introspectSelfPresence();
+ void introspectSelfHandle();
void changeReadiness(Readiness newReadiness);
void updatePendingOperations();
+ void changeSelfPresence(const Telepathy::SimplePresence &presence);
+
struct HandleContext;
class PendingReady;
@@ -127,6 +131,7 @@ struct Connection::Private
// Optional interface proxies
DBus::PropertiesInterface *properties;
+ ConnectionInterfaceSimplePresenceInterface *simplePresence;
bool ready;
QList<PendingReady *> pendingOperations;
@@ -150,6 +155,9 @@ struct Connection::Private
uint statusReason;
bool haveInitialStatus;
SimpleStatusSpecMap simplePresenceStatuses;
+ SimplePresence selfPresence;
+
+ uint selfHandle;
// (Bus connection name, service name) -> HandleContext
static QMap<QPair<QString, QString>, HandleContext *> handleContexts;
@@ -206,6 +214,7 @@ Connection::Private::Private(Connection *parent)
baseInterface(new ConnectionInterface(parent->dbusConnection(),
parent->busName(), parent->objectPath(), parent)),
properties(0),
+ simplePresence(0),
initialIntrospection(false),
readiness(ReadinessJustCreated),
pendingStatus(ConnectionStatusDisconnected),
@@ -213,8 +222,10 @@ Connection::Private::Private(Connection *parent)
status(ConnectionStatusDisconnected),
statusReason(ConnectionStatusReasonNoneSpecified),
haveInitialStatus(false),
+ selfHandle(0),
handleContext(0)
{
+ selfPresence.type = Telepathy::ConnectionPresenceTypeUnknown;
}
Connection::Private::~Private()
@@ -320,6 +331,43 @@ void Connection::Private::introspectSimplePresence()
SLOT(gotSimpleStatuses(QDBusPendingCallWatcher *)));
}
+void Connection::Private::introspectSelfPresence()
+{
+ if (!simplePresence) {
+ simplePresence = parent->simplePresenceInterface();
+ Q_ASSERT(simplePresence != 0);
+ }
+
+ parent->connect(simplePresence,
+ SIGNAL(PresencesChanged(const Telepathy::SimpleContactPresences&)),
+ SLOT(onPresenceChanged(const Telepathy::SimpleContactPresences&)));
+
+ debug() << "Getting self presence status";
+ UIntList handles;
+ handles << selfHandle;
+ QDBusPendingCall call = simplePresence->GetPresences(handles);
+ QDBusPendingCallWatcher *watcher =
+ new QDBusPendingCallWatcher(call, parent);
+ parent->connect(watcher,
+ SIGNAL(finished(QDBusPendingCallWatcher *)),
+ SLOT(gotSelfPresence(QDBusPendingCallWatcher *)));
+}
+
+void Connection::Private::introspectSelfHandle()
+{
+ parent->connect(baseInterface,
+ SIGNAL(SelfHandleChanged(uint)),
+ SLOT(onSelfHandleChanged(uint)));
+
+ debug() << "Getting self handle";
+ QDBusPendingCall call = baseInterface->GetSelfHandle();
+ QDBusPendingCallWatcher *watcher =
+ new QDBusPendingCallWatcher(call, parent);
+ parent->connect(watcher,
+ SIGNAL(finished(QDBusPendingCallWatcher *)),
+ SLOT(gotSelfHandle(QDBusPendingCallWatcher *)));
+}
+
void Connection::Private::changeReadiness(Readiness newReadiness)
{
debug() << "changing readiness from" << readiness <<
@@ -370,6 +418,17 @@ void Connection::Private::updatePendingOperations()
}
}
+void Connection::Private::changeSelfPresence(const Telepathy::SimplePresence &presence)
+{
+ if (presence.type == selfPresence.type &&
+ presence.status == selfPresence.status &&
+ presence.statusMessage == selfPresence.statusMessage) {
+ return;
+ }
+ selfPresence = presence;
+ parent->emit selfPresenceChanged(presence);
+}
+
QMap<QPair<QString, QString>, Connection::Private::HandleContext*> Connection::Private::handleContexts;
QMutex Connection::Private::handleContextsLock;
@@ -558,6 +617,36 @@ PendingOperation *Connection::setSelfPresence(const QString &status,
}
/**
+ * Get the self presence status.
+ *
+ * Note that in order for this method to work properly,
+ * Connection::becomeReady(FeatureSelfPresence) needs to be called, otherwise
+ * ConnectionPresenceTypeUnknown will be returned.
+ *
+ * \param status The desired status.
+ * \param statusMessage The desired status message.
+ * \return A PendingOperation which will emit PendingOperation::finished
+ * when the call has finished.
+ */
+Telepathy::SimplePresence Connection::selfPresence() const
+{
+ if (mPriv->missingFeatures & FeatureSelfPresence) {
+ warning() << "Trying to retrieve self simple presence from connection, but "
+ "simple presence is not supported";
+ }
+ else if (!(mPriv->features & FeatureSelfPresence)) {
+ warning() << "Trying to retrieve self simple presence from connection without "
+ "calling Connection::becomeReady(FeatureSelfPresence)";
+ }
+ else if (mPriv->pendingFeatures & FeatureSelfPresence) {
+ warning() << "Trying to retrieve self simple presence from connection, but "
+ "simple presence is still being retrieved";
+ }
+
+ return mPriv->selfPresence;
+}
+
+/**
* \fn Connection::optionalInterface(InterfaceSupportedChecking check) const
*
* Get a pointer to a valid instance of a given %Connection optional
@@ -844,6 +933,42 @@ void Connection::gotSimpleStatuses(QDBusPendingCallWatcher *watcher)
watcher->deleteLater();
}
+void Connection::gotSelfPresence(QDBusPendingCallWatcher *watcher)
+{
+ QDBusPendingReply<Telepathy::SimpleContactPresences> reply = *watcher;
+
+ if (!reply.isError()) {
+ mPriv->changeSelfPresence(reply.value()[mPriv->selfHandle]);
+ debug() << "Got self presence";
+ }
+ else {
+ warning().nospace() << "Getting self presence status failed with" <<
+ reply.error().name() << ":" << reply.error().message();
+ }
+
+ continueIntrospection();
+
+ watcher->deleteLater();
+}
+
+void Connection::gotSelfHandle(QDBusPendingCallWatcher *watcher)
+{
+ QDBusPendingReply<uint> reply = *watcher;
+
+ if (!reply.isError()) {
+ mPriv->selfHandle = reply.value();
+ debug() << "Got self handle";
+ }
+ else {
+ warning().nospace() << "Getting self handle failed with" <<
+ reply.error().name() << ":" << reply.error().message();
+ }
+
+ continueIntrospection();
+
+ watcher->deleteLater();
+}
+
/**
* Get the ConnectionInterface for this Connection. This
* method is protected since the convenience methods provided by this
@@ -1183,10 +1308,28 @@ PendingOperation *Connection::becomeReady(Features requestedFeatures)
!(mPriv->missingFeatures & FeatureSelfPresence) &&
mPriv->interfaces.contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE)) {
mPriv->introspectQueue.enqueue(&Private::introspectSimplePresence);
+
+ // we still don't have our own presence but as the user
+ // requested for FeatureSelfPresence, change our presence to
+ // offline
+ SimplePresence presence = { Telepathy::ConnectionPresenceTypeOffline, };
+ mPriv->changeSelfPresence(presence);
+
+ // we are already connected, so we at least enqueued the call to
+ // getSelfHandle and we can enqueue the call to getSelfPresence
+ if (mPriv->readiness == Private::ReadinessFull) {
+ mPriv->introspectQueue.enqueue(&Private::introspectSelfPresence);
+ }
+
QTimer::singleShot(0, this, SLOT(continueIntrospection()));
}
else {
if (mPriv->readiness == Private::ReadinessFull) {
+ // we don't support simple presence but we are online, so
+ // set selfPresence to available as we are connected
+ SimplePresence presence = { Telepathy::ConnectionPresenceTypeAvailable, };
+ mPriv->changeSelfPresence(presence);
+
// we should have all interfaces now, so if simple presence is not
// present, add it to missing features.
mPriv->missingFeatures |= FeatureSelfPresence;
@@ -1324,15 +1467,30 @@ void Connection::continueIntrospection()
}
}
else {
- if (mPriv->readiness != Private::ReadinessDead) {
+ if (mPriv->readiness != Private::ReadinessDead &&
+ 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.
if (!mPriv->interfaces.contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE)) {
+ debug() << "removing FeatureSelfPresence from pending features";
+ mPriv->pendingFeatures &= ~FeatureSelfPresence;
debug() << "adding FeatureSelfPresence to missing features";
mPriv->missingFeatures |= FeatureSelfPresence;
}
+ else {
+ // the user requested for FeatureSelfPresence so, now we are
+ // able to get it
+ if (mPriv->pendingFeatures == FeatureSelfPresence) {
+ mPriv->introspectQueue.enqueue(&Private::introspectSelfPresence);
+ }
+ }
+
+ (mPriv->*(mPriv->introspectQueue.dequeue()))();
}
}
}
@@ -1343,5 +1501,17 @@ void Connection::continueIntrospection()
mPriv->updatePendingOperations();
}
+void Connection::onPresenceChanged(const Telepathy::SimpleContactPresences &presences)
+{
+ if (presences.contains(mPriv->selfHandle)) {
+ mPriv->changeSelfPresence(presences.value(mPriv->selfHandle));
+ }
+}
+
+void Connection::onSelfHandleChanged(uint handle)
+{
+ mPriv->selfHandle = handle;
+}
+
}
}
diff --git a/TelepathyQt4/Client/connection.h b/TelepathyQt4/Client/connection.h
index a8bcd13..6a98c85 100644
--- a/TelepathyQt4/Client/connection.h
+++ b/TelepathyQt4/Client/connection.h
@@ -80,6 +80,7 @@ public:
SimpleStatusSpecMap allowedPresenceStatuses() const;
PendingOperation *setSelfPresence(const QString &status, const QString &statusMessage);
+ Telepathy::SimplePresence selfPresence() const;
template <class Interface>
inline Interface *optionalInterface(
@@ -157,6 +158,7 @@ public:
Q_SIGNALS:
void statusChanged(uint newStatus, uint newStatusReason);
+ void selfPresenceChanged(const Telepathy::SimplePresence &newPresence);
protected:
ConnectionInterface *baseInterface() const;
@@ -166,11 +168,17 @@ private Q_SLOTS:
void gotStatus(QDBusPendingCallWatcher *watcher);
void gotInterfaces(QDBusPendingCallWatcher *watcher);
void gotSimpleStatuses(QDBusPendingCallWatcher *watcher);
+ void gotSelfPresence(QDBusPendingCallWatcher *watcher);
+ void gotSelfHandle(QDBusPendingCallWatcher *watcher);
void doReleaseSweep(uint type);
void continueIntrospection();
+ void onPresenceChanged(const Telepathy::SimpleContactPresences &);
+
+ void onSelfHandleChanged(uint);
+
private:
void refHandle(uint type, uint handle);
void unrefHandle(uint type, uint handle);
--
1.5.6.5
More information about the Telepathy-commits
mailing list