diff options
author | Olli Salli <ollisal@gmail.com> | 2011-01-03 14:59:12 +0200 |
---|---|---|
committer | Olli Salli <ollisal@gmail.com> | 2011-01-03 14:59:12 +0200 |
commit | a053aea1072f1b241cd06af3c598d29830519069 (patch) | |
tree | f341ca2c972fac20968624b87d403120522708a4 | |
parent | a1594809eb4afddf97453e16c06969cbb3b91041 (diff) |
Order removePresenceSubscription finishes consistently with other roster events
-rw-r--r-- | TelepathyQt4/contact-manager-internal.h | 15 | ||||
-rw-r--r-- | TelepathyQt4/contact-manager.cpp | 74 | ||||
-rw-r--r-- | TelepathyQt4/contact-manager.h | 3 |
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, |