diff options
author | Olli Salli <ollisal@gmail.com> | 2010-12-31 13:35:31 +0200 |
---|---|---|
committer | Olli Salli <ollisal@gmail.com> | 2010-12-31 16:35:01 +0200 |
commit | 8ed37c6b0da009155aeb740dc03f1363ea47f3a2 (patch) | |
tree | 24ee2c3f16fced9fbd90d60b6a6539a85fe13ad3 | |
parent | b8cd97e01ef22990c731dd7df4cda2a4ce28e90d (diff) |
Implement falling back to Close in Channel::requestLeave
-rw-r--r-- | TelepathyQt4/CMakeLists.txt | 6 | ||||
-rw-r--r-- | TelepathyQt4/channel-internal.h | 47 | ||||
-rw-r--r-- | TelepathyQt4/channel.cpp | 87 | ||||
-rw-r--r-- | TelepathyQt4/channel.h | 3 |
4 files changed, 136 insertions, 7 deletions
diff --git a/TelepathyQt4/CMakeLists.txt b/TelepathyQt4/CMakeLists.txt index 87b51f28..d00c428a 100644 --- a/TelepathyQt4/CMakeLists.txt +++ b/TelepathyQt4/CMakeLists.txt @@ -20,10 +20,11 @@ set(telepathy_qt4_SRCS capabilities-base.cpp channel.cpp channel-class-spec.cpp - channel-factory.cpp - channel-request.cpp channel-dispatcher.cpp channel-dispatch-operation.cpp + channel-factory.cpp + channel-internal.h + channel-request.cpp client.cpp client-registrar.cpp client-registrar-internal.h @@ -367,6 +368,7 @@ set(telepathy_qt4_MOC_SRCS account-set-internal.h channel.h channel-dispatch-operation.h + channel-internal.h channel-request.h client-registrar.h client-registrar-internal.h diff --git a/TelepathyQt4/channel-internal.h b/TelepathyQt4/channel-internal.h new file mode 100644 index 00000000..ec1ccb38 --- /dev/null +++ b/TelepathyQt4/channel-internal.h @@ -0,0 +1,47 @@ +/* + * This file is part of TelepathyQt4 + * + * Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> + * Copyright (C) 2010 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_channel_internal_h_HEADER_GUARD_ +#define _TelepathyQt4_channel_internal_h_HEADER_GUARD_ + +#include <TelepathyQt4/Channel> +#include <TelepathyQt4/PendingOperation> + +namespace Tp +{ + +class TELEPATHY_QT4_NO_EXPORT Channel::PendingLeave : public PendingOperation +{ + Q_OBJECT + +public: + PendingLeave(const ChannelPtr &channel, const QString &message, + ChannelGroupChangeReason reason); + +private Q_SLOTS: + void onChanInvalidated(Tp::DBusProxy *proxy); + void onRemoveFinished(Tp::PendingOperation *); + void onCloseFinished(Tp::PendingOperation *); +}; + +} // Tp + +#endif diff --git a/TelepathyQt4/channel.cpp b/TelepathyQt4/channel.cpp index 3f75987c..268be324 100644 --- a/TelepathyQt4/channel.cpp +++ b/TelepathyQt4/channel.cpp @@ -20,10 +20,13 @@ */ #include <TelepathyQt4/Channel> +#include "TelepathyQt4/channel-internal.h" #include "TelepathyQt4/_gen/cli-channel-body.hpp" #include "TelepathyQt4/_gen/cli-channel.moc.hpp" #include "TelepathyQt4/_gen/channel.moc.hpp" +#include "TelepathyQt4/_gen/channel-internal.moc.hpp" + #include "TelepathyQt4/debug-internal.h" #include "TelepathyQt4/future-internal.h" @@ -1555,6 +1558,84 @@ PendingOperation *Channel::requestClose() return new PendingVoid(mPriv->baseInterface->Close(), ChannelPtr(this)); } +Channel::PendingLeave::PendingLeave(const ChannelPtr &chan, const QString &message, + ChannelGroupChangeReason reason) + : PendingOperation(chan) +{ + Q_ASSERT(chan->mPriv->group != NULL); + + QDBusPendingCall call = + chan->mPriv->group->RemoveMembersWithReason( + UIntList() << chan->mPriv->groupSelfHandle, + message, + reason); + + connect(chan.data(), + SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)), + this, + SLOT(onChanInvalidated(Tp::DBusProxy*))); + + connect(new PendingVoid(call, chan), + SIGNAL(finished(Tp::PendingOperation*)), + this, + SLOT(onRemoveFinished(Tp::PendingOperation*))); +} + +void Channel::PendingLeave::onChanInvalidated(Tp::DBusProxy *proxy) +{ + if (isFinished()) { + return; + } + + debug() << "Finishing PendingLeave successfully as the channel was invalidated"; + + setFinished(); +} + +void Channel::PendingLeave::onRemoveFinished(Tp::PendingOperation *op) +{ + if (isFinished()) { + return; + } + + ChannelPtr chan = ChannelPtr::staticCast(object()); + + if (op->isValid()) { + debug() << "We left the channel" << chan->objectPath(); + setFinished(); + return; + } + + debug() << "Leave RemoveMembersWithReason failed with " << op->errorName() << op->errorMessage() + << "- falling back to Close"; + + // If the channel has been closed or otherwise invalidated already in this mainloop iteration, + // the requestClose() operation will early-succeed + connect(chan->requestClose(), + SIGNAL(finished(Tp::PendingOperation*)), + this, + SLOT(onCloseFinished(Tp::PendingOperation*))); +} + +void Channel::PendingLeave::onCloseFinished(Tp::PendingOperation *op) +{ + if (isFinished()) { + return; + } + + ChannelPtr chan = ChannelPtr::staticCast(object()); + + if (op->isError()) { + warning() << "Closing the channel" << chan->objectPath() + << "as a fallback for leaving it failed with" + << op->errorName() << op->errorMessage() << "- so didn't leave"; + setFinishedWithError(op->errorName(), op->errorMessage()); + } else { + debug() << "We left (by closing) the channel" << chan->objectPath(); + setFinished(); + } +} + /** * Start an asynchronous request to leave this channel as gracefully as possible. * @@ -1603,11 +1684,7 @@ PendingOperation *Channel::requestLeave(const QString &message, ChannelGroupChan } // TODO: use PendingLeave which handles errors correctly by falling back to Close - return new PendingVoid(mPriv->group->RemoveMembersWithReason( - UIntList() << mPriv->groupSelfHandle, - message, - reason), - ChannelPtr(this)); + return new PendingLeave(ChannelPtr(this), message, reason); } /** diff --git a/TelepathyQt4/channel.h b/TelepathyQt4/channel.h index f638b025..4d2019e0 100644 --- a/TelepathyQt4/channel.h +++ b/TelepathyQt4/channel.h @@ -238,6 +238,9 @@ private Q_SLOTS: void gotConferenceChannelRemovedActorContact(Tp::PendingOperation *op); private: + class PendingLeave; + friend class PendingLeave; + struct Private; friend struct Private; Private *mPriv; |