summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlli Salli <ollisal@gmail.com>2010-12-31 13:35:31 +0200
committerOlli Salli <ollisal@gmail.com>2010-12-31 16:35:01 +0200
commit8ed37c6b0da009155aeb740dc03f1363ea47f3a2 (patch)
tree24ee2c3f16fced9fbd90d60b6a6539a85fe13ad3
parentb8cd97e01ef22990c731dd7df4cda2a4ce28e90d (diff)
Implement falling back to Close in Channel::requestLeave
-rw-r--r--TelepathyQt4/CMakeLists.txt6
-rw-r--r--TelepathyQt4/channel-internal.h47
-rw-r--r--TelepathyQt4/channel.cpp87
-rw-r--r--TelepathyQt4/channel.h3
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;