summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlli Salli <ollisal@gmail.com>2011-01-03 14:59:12 +0200
committerOlli Salli <ollisal@gmail.com>2011-01-03 14:59:12 +0200
commita053aea1072f1b241cd06af3c598d29830519069 (patch)
treef341ca2c972fac20968624b87d403120522708a4
parenta1594809eb4afddf97453e16c06969cbb3b91041 (diff)
Order removePresenceSubscription finishes consistently with other roster events
-rw-r--r--TelepathyQt4/contact-manager-internal.h15
-rw-r--r--TelepathyQt4/contact-manager.cpp74
-rw-r--r--TelepathyQt4/contact-manager.h3
3 files changed, 91 insertions, 1 deletions
diff --git a/TelepathyQt4/contact-manager-internal.h b/TelepathyQt4/contact-manager-internal.h
index 9a9281e9..0205bf05 100644
--- a/TelepathyQt4/contact-manager-internal.h
+++ b/TelepathyQt4/contact-manager-internal.h
@@ -41,6 +41,21 @@ private Q_SLOTS:
void onChannelClosed(Tp::PendingOperation *);
};
+class TELEPATHY_QT4_NO_EXPORT RosterModifyFinishOp : public PendingOperation
+{
+ Q_OBJECT
+
+public:
+ RosterModifyFinishOp(const ConnectionPtr &conn);
+ ~RosterModifyFinishOp() {};
+
+ void setError(const QString &errorName, const QString &errorMessage);
+ void finish();
+
+private:
+ QString errorName, errorMessage;
+};
+
} // Tp
#endif
diff --git a/TelepathyQt4/contact-manager.cpp b/TelepathyQt4/contact-manager.cpp
index fb5c4b62..588550da 100644
--- a/TelepathyQt4/contact-manager.cpp
+++ b/TelepathyQt4/contact-manager.cpp
@@ -65,6 +65,7 @@ struct TELEPATHY_QT4_NO_EXPORT ContactManager::Private
void processContactListGroupsCreated();
void processContactListGroupRenamed();
void processContactListGroupsRemoved();
+ void processFinishedModify();
Contacts allKnownContactsFallback() const;
void computeKnownContactsChangesFallback(const Contacts &added,
@@ -125,6 +126,9 @@ struct TELEPATHY_QT4_NO_EXPORT ContactManager::Private
QQueue<QStringList> contactListGroupsRemovedQueue;
bool processingContactListChanges;
+ QMap<Tp::PendingOperation * /* actual */, Tp::RosterModifyFinishOp *> returnedModifyOps;
+ QQueue<RosterModifyFinishOp *> modifyFinishQueue;
+
// old roster API
QMap<uint, ContactListChannel> contactListChannels;
ChannelPtr subscribeChannel;
@@ -376,6 +380,24 @@ void ContactManager::Private::processContactListGroupsRemoved()
processContactListChanges();
}
+void ContactManager::Private::processFinishedModify()
+{
+ RosterModifyFinishOp *op = modifyFinishQueue.dequeue();
+ // Only continue processing changes (and thus, emitting change signals) when the op has signaled
+ // finish (it'll only do this after we've returned to the mainloop)
+ connect(op,
+ SIGNAL(finished(Tp::PendingOperation*)),
+ parent,
+ SLOT(onModifyFinishSignaled()));
+ op->finish();
+}
+
+void ContactManager::onModifyFinishSignaled()
+{
+ mPriv->processingContactListChanges = false;
+ mPriv->processContactListChanges();
+}
+
Contacts ContactManager::Private::allKnownContactsFallback() const
{
Contacts contacts;
@@ -1226,7 +1248,16 @@ PendingOperation *ContactManager::removePresenceSubscription(
Client::ConnectionInterfaceContactListInterface *iface =
connection()->interface<Client::ConnectionInterfaceContactListInterface>();
Q_ASSERT(iface);
- return new PendingVoid(iface->Unsubscribe(handles), connection());
+
+ // TODO: generalize and make other modify ops use this mechanism too
+ PendingOperation *actual = new PendingVoid(iface->Unsubscribe(handles), connection());
+ connect(actual,
+ SIGNAL(finished(Tp::PendingOperation*)),
+ this,
+ SLOT(onModifyFinished(Tp::PendingOperation*)));
+ RosterModifyFinishOp *toReturn = new RosterModifyFinishOp(connection());
+ mPriv->returnedModifyOps.insert(actual, toReturn);
+ return toReturn;
}
/**
@@ -1935,6 +1966,22 @@ void ContactManager::onContactListGroupsRemoved(const QStringList &names)
mPriv->processContactListChanges();
}
+void ContactManager::onModifyFinished(Tp::PendingOperation *op)
+{
+ RosterModifyFinishOp *returned = mPriv->returnedModifyOps.take(op);
+
+ // Finished twice, or we didn't add the returned op at all?
+ Q_ASSERT(returned);
+
+ if (op->isError()) {
+ returned->setError(op->errorName(), op->errorMessage());
+ }
+
+ mPriv->modifyFinishQueue.enqueue(returned);
+ mPriv->contactListChangesQueue.enqueue(&Private::processFinishedModify);
+ mPriv->processContactListChanges();
+}
+
void ContactManager::onStoredChannelMembersChangedFallback(
const Contacts &groupMembersAdded,
const Contacts &groupLocalPendingMembersAdded,
@@ -2432,6 +2479,31 @@ void PendingContactManagerRemoveContactListGroup::onChannelClosed(PendingOperati
}
}
+RosterModifyFinishOp::RosterModifyFinishOp(const ConnectionPtr &conn)
+ : PendingOperation(conn)
+{
+}
+
+void RosterModifyFinishOp::setError(const QString &errorName, const QString &errorMessage)
+{
+ Q_ASSERT(this->errorName.isEmpty());
+ Q_ASSERT(this->errorMessage.isEmpty());
+
+ Q_ASSERT(!errorName.isEmpty());
+
+ this->errorName = errorName;
+ this->errorMessage = errorMessage;
+}
+
+void RosterModifyFinishOp::finish()
+{
+ if (errorName.isEmpty()) {
+ setFinished();
+ } else {
+ setFinishedWithError(errorName, errorMessage);
+ }
+}
+
void ContactManager::connectNotify(const char *signalName)
{
if (qstrcmp(signalName, SIGNAL(presencePublicationRequested(Tp::Contacts,Tp::Channel::GroupMemberChangeDetails))) == 0) {
diff --git a/TelepathyQt4/contact-manager.h b/TelepathyQt4/contact-manager.h
index 75d3cb63..2ec05257 100644
--- a/TelepathyQt4/contact-manager.h
+++ b/TelepathyQt4/contact-manager.h
@@ -156,6 +156,9 @@ private Q_SLOTS:
void onContactListGroupRenamed(const QString &oldName, const QString &newName);
void onContactListGroupsRemoved(const QStringList &names);
+ void onModifyFinished(Tp::PendingOperation *op);
+ void onModifyFinishSignaled();
+
void onStoredChannelMembersChangedFallback(
const Tp::Contacts &groupMembersAdded,
const Tp::Contacts &groupLocalPendingMembersAdded,