From b54aa689ffc6bec7987c193e28c641d2f0f73236 Mon Sep 17 00:00:00 2001
From: Tobias Markmann <tm@ayena.de>
Date: Wed, 17 Jun 2015 22:40:41 +0200
Subject: Implement logic behind 'Clear all' button

The 'Clear all' button in the file transfer overview window
was only present in the UI, without any logic behind. That's fixed now.

Test-Information:

Send a file in between two Swift instances. Verified that the button is
enabled/disabled at appropriate times and works as expected if pressed.

Change-Id: Ib92621cba479683ade8d815ce5ace9768449a499

diff --git a/Swift/Controllers/FileTransfer/FileTransferController.cpp b/Swift/Controllers/FileTransfer/FileTransferController.cpp
index f7ce8e6..c21c364 100644
--- a/Swift/Controllers/FileTransfer/FileTransferController.cpp
+++ b/Swift/Controllers/FileTransfer/FileTransferController.cpp
@@ -121,7 +121,7 @@ void FileTransferController::cancel() {
 
 void FileTransferController::handleFileTransferStateChange(FileTransfer::State state) {
 	currentState = state;
-	onStateChage();
+	onStateChanged();
 	switch(state.type) {
 		case FileTransfer::State::Initial:
 			assert(false);
diff --git a/Swift/Controllers/FileTransfer/FileTransferController.h b/Swift/Controllers/FileTransfer/FileTransferController.h
index 3d6f7d5..490773d 100644
--- a/Swift/Controllers/FileTransfer/FileTransferController.h
+++ b/Swift/Controllers/FileTransfer/FileTransferController.h
@@ -4,18 +4,25 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
 #pragma once
 
 #include <string>
 
-#include <boost/shared_ptr.hpp>
 #include <boost/cstdint.hpp>
+#include <boost/shared_ptr.hpp>
 
-#include <Swiften/JID/JID.h>
-#include <Swiften/FileTransfer/FileTransfer.h>
-#include <Swiften/FileTransfer/IncomingFileTransfer.h>
 #include <Swiften/FileTransfer/FileReadBytestream.h>
+#include <Swiften/FileTransfer/FileTransfer.h>
 #include <Swiften/FileTransfer/FileWriteBytestream.h>
+#include <Swiften/FileTransfer/IncomingFileTransfer.h>
+#include <Swiften/JID/JID.h>
+
 #include <Swift/Controllers/FileTransfer/FileTransferProgressInfo.h>
 
 namespace Swift {
@@ -49,14 +56,14 @@ public:
 	int getProgress() const;
 	boost::uintmax_t getSize() const;
 
-	boost::signal<void ()> onStateChage;
+	boost::signal<void ()> onStateChanged;
 	boost::signal<void ()> onProgressChange;
 
 private:
 	void handleFileTransferStateChange(FileTransfer::State);
 	void handleProgressPercentageChange(int percentage);
 
-private:	
+private:
 	bool sending;
 	JID otherParty;
 	std::string filename;
diff --git a/Swift/Controllers/FileTransfer/FileTransferOverview.cpp b/Swift/Controllers/FileTransfer/FileTransferOverview.cpp
index 2a8c319..b2afea9 100644
--- a/Swift/Controllers/FileTransfer/FileTransferOverview.cpp
+++ b/Swift/Controllers/FileTransfer/FileTransferOverview.cpp
@@ -4,41 +4,89 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
 #include "FileTransferOverview.h"
 
 #include <boost/bind.hpp>
 #include <boost/filesystem.hpp>
-#include <Swiften/Base/boost_bsignals.h>
 
+#include <Swiften/Base/Log.h>
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Base/foreach.h>
 #include <Swiften/FileTransfer/FileTransferManager.h>
 
 namespace Swift {
 
 FileTransferOverview::FileTransferOverview(FileTransferManager* ftm) : fileTransferManager(ftm) {
 	fileTransferManager->onIncomingFileTransfer.connect(boost::bind(&FileTransferOverview::handleIncomingFileTransfer, this, _1));
+	onNewFileTransferController.connect(boost::bind(&FileTransferOverview::handleNewFileTransferController, this, _1));
 }
 
 FileTransferOverview::~FileTransferOverview() {
-	
+	onNewFileTransferController.disconnect(boost::bind(&FileTransferOverview::handleNewFileTransferController, this, _1));
+	fileTransferManager->onIncomingFileTransfer.disconnect(boost::bind(&FileTransferOverview::handleIncomingFileTransfer, this, _1));
+	foreach(FileTransferController* controller, fileTransfers) {
+		controller->onStateChanged.disconnect(boost::bind(&FileTransferOverview::handleFileTransferStateChanged, this));
+	}
 }
 	
 void FileTransferOverview::sendFile(const JID& jid, const std::string& filename) {
 	if (boost::filesystem::exists(filename) && boost::filesystem::file_size(filename) > 0) {
 		FileTransferController* controller = new FileTransferController(jid, filename, fileTransferManager);
-		fileTransfers.push_back(controller);
-
 		onNewFileTransferController(controller);
 	}
 }
 
 void FileTransferOverview::handleIncomingFileTransfer(IncomingFileTransfer::ref transfer) {
 	FileTransferController* controller = new FileTransferController(transfer);
-	fileTransfers.push_back(controller);
 	onNewFileTransferController(controller);
 }
 
+void FileTransferOverview::handleNewFileTransferController(FileTransferController* controller) {
+	fileTransfers.push_back(controller);
+	controller->onStateChanged.connect(boost::bind(&FileTransferOverview::handleFileTransferStateChanged, this));
+}
+
+void FileTransferOverview::handleFileTransferStateChanged() {
+	onFileTransferListChanged();
+}
+
 const std::vector<FileTransferController*>& FileTransferOverview::getFileTransfers() const {
 	return fileTransfers;
 }
 
+void FileTransferOverview::clearFinished() {
+	for (std::vector<FileTransferController*>::iterator it = fileTransfers.begin(); it != fileTransfers.end(); ) {
+		if((*it)->getState().type == FileTransfer::State::Finished
+			|| (*it)->getState().type == FileTransfer::State::Failed
+			|| (*it)->getState().type == FileTransfer::State::Canceled) {
+			FileTransferController* controller = *it;
+			it = fileTransfers.erase(it);
+			controller->onStateChanged.disconnect(boost::bind(&FileTransferOverview::handleFileTransferStateChanged, this));
+			delete controller;
+		} else {
+			++it;
+		}
+	}
+	onFileTransferListChanged();
+}
+
+bool FileTransferOverview::isClearable() const {
+	bool isClearable = false;
+	foreach (FileTransferController* controller, fileTransfers) {
+		if(controller->getState().type == FileTransfer::State::Finished
+			|| controller->getState().type == FileTransfer::State::Failed
+			|| controller->getState().type == FileTransfer::State::Canceled) {
+			isClearable = true;
+			break;
+		}
+	}
+	return isClearable;
+}
+
 }
diff --git a/Swift/Controllers/FileTransfer/FileTransferOverview.h b/Swift/Controllers/FileTransfer/FileTransferOverview.h
index 716666a..e3cbf81 100644
--- a/Swift/Controllers/FileTransfer/FileTransferOverview.h
+++ b/Swift/Controllers/FileTransfer/FileTransferOverview.h
@@ -4,14 +4,20 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
 #pragma once
 
 #include <vector>
 
-#include "Swift/Controllers/FileTransfer/FileTransferController.h"
-
 #include <Swiften/Base/boost_bsignals.h>
 
+#include <Swift/Controllers/FileTransfer/FileTransferController.h>
+
 namespace Swift {
 
 class ChatsManager;
@@ -24,11 +30,16 @@ public:
 	
 	void sendFile(const JID&, const std::string&);
 	const std::vector<FileTransferController*>& getFileTransfers() const;
+	void clearFinished();
+	bool isClearable() const;
 
 	boost::signal<void (FileTransferController*)> onNewFileTransferController;
+	boost::signal<void ()> onFileTransferListChanged;
 
 private:
 	void handleIncomingFileTransfer(IncomingFileTransfer::ref transfer);
+	void handleNewFileTransferController(FileTransferController* controller);
+	void handleFileTransferStateChanged();
 
 private:
 	std::vector<FileTransferController*> fileTransfers;
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index a65a18a..cdaa207 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -13,84 +13,84 @@
 #include <boost/shared_ptr.hpp>
 #include <boost/smart_ptr/make_shared.hpp>
 
-#include <Swiften/Base/format.h>
 #include <Swiften/Base/Algorithm.h>
 #include <Swiften/Base/String.h>
-#include <Swiften/StringCodecs/Base64.h>
-#include <Swiften/Network/TimerFactory.h>
-#include <Swiften/Client/Storages.h>
-#include <Swiften/VCards/VCardManager.h>
-#include <Swiften/Client/NickResolver.h>
 #include <Swiften/Base/foreach.h>
+#include <Swiften/Base/format.h>
 #include <Swiften/Client/Client.h>
-#include <Swiften/Presence/PresenceSender.h>
+#include <Swiften/Client/ClientBlockListManager.h>
+#include <Swiften/Client/ClientXMLTracer.h>
+#include <Swiften/Client/NickResolver.h>
+#include <Swiften/Client/StanzaChannel.h>
+#include <Swiften/Client/Storages.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Disco/CapsInfoGenerator.h>
+#include <Swiften/Disco/ClientDiscoManager.h>
+#include <Swiften/Disco/GetDiscoInfoRequest.h>
 #include <Swiften/Elements/ChatState.h>
+#include <Swiften/Elements/DiscoInfo.h>
 #include <Swiften/Elements/Presence.h>
 #include <Swiften/Elements/VCardUpdate.h>
-#include <Swiften/Elements/DiscoInfo.h>
-#include <Swiften/Disco/CapsInfoGenerator.h>
-#include <Swiften/Disco/GetDiscoInfoRequest.h>
-#include <Swiften/Disco/ClientDiscoManager.h>
-#include <Swiften/VCards/GetVCardRequest.h>
-#include <Swiften/StringCodecs/Hexify.h>
-#include <Swiften/Network/NetworkFactories.h>
 #include <Swiften/FileTransfer/FileTransferManager.h>
-#include <Swiften/Client/ClientXMLTracer.h>
-#include <Swiften/Client/StanzaChannel.h>
-#include <Swiften/Client/ClientBlockListManager.h>
-#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Network/NetworkFactories.h>
+#include <Swiften/Network/TimerFactory.h>
+#include <Swiften/Presence/PresenceSender.h>
+#include <Swiften/StringCodecs/Base64.h>
+#include <Swiften/StringCodecs/Hexify.h>
+#include <Swiften/VCards/GetVCardRequest.h>
+#include <Swiften/VCards/VCardManager.h>
 
 #ifdef SWIFTEN_PLATFORM_WIN32
 #include <Swiften/SASL/WindowsAuthentication.h>
 #endif
 
-#include <SwifTools/Dock/Dock.h>
-#include <SwifTools/Notifier/TogglableNotifier.h>
-#include <SwifTools/Idle/IdleDetector.h>
-
-#include <Swift/Controllers/Intl.h>
-#include <Swift/Controllers/UIInterfaces/UIFactory.h>
+#include <Swift/Controllers/AdHocManager.h>
+#include <Swift/Controllers/BlockListController.h>
 #include <Swift/Controllers/BuildVersion.h>
-#include <Swift/Controllers/Chat/UserSearchController.h>
 #include <Swift/Controllers/Chat/ChatsManager.h>
-#include <Swift/Controllers/XMPPEvents/EventController.h>
-#include <Swift/Controllers/EventWindowController.h>
-#include <Swift/Controllers/UIInterfaces/LoginWindow.h>
-#include <Swift/Controllers/UIInterfaces/LoginWindowFactory.h>
-#include <Swift/Controllers/UIInterfaces/MainWindow.h>
 #include <Swift/Controllers/Chat/MUCController.h>
+#include <Swift/Controllers/Chat/UserSearchController.h>
+#include <Swift/Controllers/ContactEditController.h>
+#include <Swift/Controllers/ContactSuggester.h>
+#include <Swift/Controllers/ContactsFromXMPPRoster.h>
+#include <Swift/Controllers/EventNotifier.h>
+#include <Swift/Controllers/EventWindowController.h>
+#include <Swift/Controllers/FileTransfer/FileTransferOverview.h>
+#include <Swift/Controllers/FileTransferListController.h>
+#include <Swift/Controllers/HighlightEditorController.h>
+#include <Swift/Controllers/HighlightManager.h>
+#include <Swift/Controllers/HistoryController.h>
+#include <Swift/Controllers/HistoryViewController.h>
+#include <Swift/Controllers/Intl.h>
+#include <Swift/Controllers/PresenceNotifier.h>
+#include <Swift/Controllers/ProfileController.h>
 #include <Swift/Controllers/Roster/RosterController.h>
+#include <Swift/Controllers/SettingConstants.h>
+#include <Swift/Controllers/Settings/SettingsProvider.h>
+#include <Swift/Controllers/ShowProfileController.h>
 #include <Swift/Controllers/SoundEventController.h>
 #include <Swift/Controllers/SoundPlayer.h>
 #include <Swift/Controllers/StatusTracker.h>
+#include <Swift/Controllers/Storages/CertificateStorageFactory.h>
+#include <Swift/Controllers/Storages/CertificateStorageTrustChecker.h>
+#include <Swift/Controllers/Storages/StoragesFactory.h>
 #include <Swift/Controllers/SystemTray.h>
 #include <Swift/Controllers/SystemTrayController.h>
-#include <Swift/Controllers/XMLConsoleController.h>
-#include <Swift/Controllers/HistoryController.h>
-#include <Swift/Controllers/HistoryViewController.h>
-#include <Swift/Controllers/FileTransferListController.h>
+#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
+#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
 #include <Swift/Controllers/UIEvents/UIEventStream.h>
-#include <Swift/Controllers/PresenceNotifier.h>
-#include <Swift/Controllers/EventNotifier.h>
-#include <Swift/Controllers/Storages/StoragesFactory.h>
+#include <Swift/Controllers/UIInterfaces/LoginWindow.h>
+#include <Swift/Controllers/UIInterfaces/LoginWindowFactory.h>
+#include <Swift/Controllers/UIInterfaces/MainWindow.h>
+#include <Swift/Controllers/UIInterfaces/UIFactory.h>
 #include <Swift/Controllers/WhiteboardManager.h>
-#include <Swift/Controllers/Settings/SettingsProvider.h>
-#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
-#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
-#include <Swift/Controllers/Storages/CertificateStorageFactory.h>
-#include <Swift/Controllers/Storages/CertificateStorageTrustChecker.h>
-#include <Swift/Controllers/ProfileController.h>
-#include <Swift/Controllers/ShowProfileController.h>
-#include <Swift/Controllers/ContactEditController.h>
+#include <Swift/Controllers/XMLConsoleController.h>
+#include <Swift/Controllers/XMPPEvents/EventController.h>
 #include <Swift/Controllers/XMPPURIController.h>
-#include <Swift/Controllers/AdHocManager.h>
-#include <Swift/Controllers/FileTransfer/FileTransferOverview.h>
-#include <Swift/Controllers/SettingConstants.h>
-#include <Swift/Controllers/HighlightManager.h>
-#include <Swift/Controllers/HighlightEditorController.h>
-#include <Swift/Controllers/BlockListController.h>
-#include <Swift/Controllers/ContactSuggester.h>
-#include <Swift/Controllers/ContactsFromXMPPRoster.h>
+
+#include <SwifTools/Dock/Dock.h>
+#include <SwifTools/Idle/IdleDetector.h>
+#include <SwifTools/Notifier/TogglableNotifier.h>
 
 namespace Swift {
 
@@ -270,6 +270,7 @@ void MainController::resetClient() {
 	delete historyController_;
 	historyController_ = NULL;
 #endif
+	fileTransferListController_->setFileTransferOverview(NULL);
 	delete ftOverview_;
 	ftOverview_ = NULL;
 	delete blockListController_;
diff --git a/Swift/QtUI/QtFileTransferListItemModel.cpp b/Swift/QtUI/QtFileTransferListItemModel.cpp
index b9b9fd1..ef73f4f 100644
--- a/Swift/QtUI/QtFileTransferListItemModel.cpp
+++ b/Swift/QtUI/QtFileTransferListItemModel.cpp
@@ -4,35 +4,64 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
-#include "QtFileTransferListItemModel.h"
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtFileTransferListItemModel.h>
 
 #include <boost/bind.hpp>
 #include <boost/cstdint.hpp>
 
-#include <Swiften/Base/boost_bsignals.h>
 #include <Swiften/Base/FileSize.h>
+#include <Swiften/Base/boost_bsignals.h>
+
 #include <Swift/Controllers/FileTransfer/FileTransferController.h>
 #include <Swift/Controllers/FileTransfer/FileTransferOverview.h>
-#include "QtSwiftUtil.h"
+
+#include <Swift/QtUI/QtSwiftUtil.h>
 
 namespace Swift {
 
 QtFileTransferListItemModel::QtFileTransferListItemModel(QObject *parent) : QAbstractItemModel(parent), fileTransferOverview(0) {
 }
 
+QtFileTransferListItemModel::~QtFileTransferListItemModel() {
+	if (fileTransferOverview) {
+		fileTransferOverview->onNewFileTransferController.disconnect(boost::bind(&QtFileTransferListItemModel::handleNewFileTransferController, this, _1));
+		fileTransferOverview->onFileTransferListChanged.disconnect(boost::bind(&QtFileTransferListItemModel::handleFileTransferListChanged, this));
+	}
+}
+
 void QtFileTransferListItemModel::setFileTransferOverview(FileTransferOverview *overview) {
+	if (fileTransferOverview) {
+		fileTransferOverview->onNewFileTransferController.disconnect(boost::bind(&QtFileTransferListItemModel::handleNewFileTransferController, this, _1));
+		fileTransferOverview->onFileTransferListChanged.disconnect(boost::bind(&QtFileTransferListItemModel::handleFileTransferListChanged, this));
+	}
 	fileTransferOverview = overview;
-	fileTransferOverview->onNewFileTransferController.connect(boost::bind(&QtFileTransferListItemModel::handleNewFileTransferController, this, _1));
+	if (fileTransferOverview) {
+		fileTransferOverview->onNewFileTransferController.connect(boost::bind(&QtFileTransferListItemModel::handleNewFileTransferController, this, _1));
+		fileTransferOverview->onFileTransferListChanged.connect(boost::bind(&QtFileTransferListItemModel::handleFileTransferListChanged, this));
+	}
+	emit layoutAboutToBeChanged();
+	emit layoutChanged();
 }
 
 void QtFileTransferListItemModel::handleNewFileTransferController(FileTransferController* newController) {
 	emit layoutAboutToBeChanged();
 	emit layoutChanged();
 	dataChanged(createIndex(0,0), createIndex(fileTransferOverview->getFileTransfers().size(),4));
-	newController->onStateChage.connect(boost::bind(&QtFileTransferListItemModel::handleStateChange, this, fileTransferOverview->getFileTransfers().size() - 1));
+	newController->onStateChanged.connect(boost::bind(&QtFileTransferListItemModel::handleStateChange, this, fileTransferOverview->getFileTransfers().size() - 1));
 	newController->onProgressChange.connect(boost::bind(&QtFileTransferListItemModel::handleProgressChange, this, fileTransferOverview->getFileTransfers().size() - 1));
 }
 
+void QtFileTransferListItemModel::handleFileTransferListChanged() {
+	emit layoutAboutToBeChanged();
+	emit layoutChanged();
+}
+
 void QtFileTransferListItemModel::handleStateChange(int index) {
 	emit dataChanged(createIndex(index, 2), createIndex(index, 2));
 }
diff --git a/Swift/QtUI/QtFileTransferListItemModel.h b/Swift/QtUI/QtFileTransferListItemModel.h
index 28f13f8..64cdca4 100644
--- a/Swift/QtUI/QtFileTransferListItemModel.h
+++ b/Swift/QtUI/QtFileTransferListItemModel.h
@@ -4,6 +4,12 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
 #pragma once
 
 #include <QAbstractItemModel>
@@ -17,6 +23,7 @@ class QtFileTransferListItemModel : public QAbstractItemModel {
 	Q_OBJECT
 public:
 	explicit QtFileTransferListItemModel(QObject *parent = 0);
+	virtual ~QtFileTransferListItemModel();
 
 	void setFileTransferOverview(FileTransferOverview*);
 
@@ -39,6 +46,7 @@ private:
 
 private:
 	void handleNewFileTransferController(FileTransferController*);
+	void handleFileTransferListChanged();
 	void handleStateChange(int index);
 	void handleProgressChange(int index);
 
diff --git a/Swift/QtUI/QtFileTransferListWidget.cpp b/Swift/QtUI/QtFileTransferListWidget.cpp
index fb2b4de..729c95f 100644
--- a/Swift/QtUI/QtFileTransferListWidget.cpp
+++ b/Swift/QtUI/QtFileTransferListWidget.cpp
@@ -4,14 +4,24 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
-#include "QtFileTransferListWidget.h"
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
 
-#include <Swift/QtUI/QtFileTransferListItemModel.h>
+#include <Swift/QtUI/QtFileTransferListWidget.h>
+
+#include <boost/bind.hpp>
 
-#include <QVBoxLayout>
 #include <QHBoxLayout>
-#include <QWidget>
 #include <QPushButton>
+#include <QVBoxLayout>
+#include <QWidget>
+
+#include <Swift/Controllers/FileTransfer/FileTransferOverview.h>
+
+#include <Swift/QtUI/QtFileTransferListItemModel.h>
 
 namespace Swift {
 
@@ -36,9 +46,9 @@ QtFileTransferListWidget::QtFileTransferListWidget() : fileTransferOverview(0) {
 	buttonLayout->setContentsMargins(10,0,20,0);
 	buttonLayout->setSpacing(0);
 
-	QPushButton* clearFinished = new QPushButton(tr("Clear Finished Transfers"), bottom);
+	clearFinished = new QPushButton(tr("Clear Inactive Transfers"), bottom);
 	clearFinished->setEnabled(false);
-	//connect(clearButton, SIGNAL(clicked()), textEdit, SLOT(clear()));
+	connect(clearFinished, SIGNAL(clicked()), this, SLOT(clearInactiveTransfers()));
 	buttonLayout->addWidget(clearFinished);
 
 	setWindowTitle(tr("File Transfer List"));
@@ -46,6 +56,10 @@ QtFileTransferListWidget::QtFileTransferListWidget() : fileTransferOverview(0) {
 }
 
 QtFileTransferListWidget::~QtFileTransferListWidget() {
+	if (fileTransferOverview) {
+		fileTransferOverview->onFileTransferListChanged.disconnect(boost::bind(&QtFileTransferListWidget::handleFileTransferListChanged, this));
+		fileTransferOverview = NULL;
+	}
 	delete itemModel;
 }
 
@@ -55,6 +69,14 @@ void QtFileTransferListWidget::showEvent(QShowEvent* event) {
 	QWidget::showEvent(event);
 }
 
+void QtFileTransferListWidget::handleFileTransferListChanged() {
+	clearFinished->setEnabled(fileTransferOverview->isClearable());
+}
+
+void QtFileTransferListWidget::clearInactiveTransfers() {
+	fileTransferOverview->clearFinished();
+}
+
 void QtFileTransferListWidget::show() {
 	QWidget::show();
 	emit windowOpening();
@@ -65,7 +87,15 @@ void QtFileTransferListWidget::activate() {
 }
 
 void QtFileTransferListWidget::setFileTransferOverview(FileTransferOverview *overview) {
-	fileTransferOverview = overview;
+	if (fileTransferOverview) {
+		fileTransferOverview->onFileTransferListChanged.disconnect(boost::bind(&QtFileTransferListWidget::handleFileTransferListChanged, this));
+		fileTransferOverview = NULL;
+	}
+	if (overview) {
+		fileTransferOverview = overview;
+		fileTransferOverview->onFileTransferListChanged.connect(boost::bind(&QtFileTransferListWidget::handleFileTransferListChanged, this));
+		clearFinished->setEnabled(fileTransferOverview->isClearable());
+	}
 	itemModel->setFileTransferOverview(overview);
 }
 
diff --git a/Swift/QtUI/QtFileTransferListWidget.h b/Swift/QtUI/QtFileTransferListWidget.h
index 8adc009..740eb15 100644
--- a/Swift/QtUI/QtFileTransferListWidget.h
+++ b/Swift/QtUI/QtFileTransferListWidget.h
@@ -4,16 +4,23 @@
  * See Documentation/Licenses/BSD-simplified.txt for more information.
  */
 
-#pragma once
-
-#include "Swift/Controllers/UIInterfaces/FileTransferListWidget.h"
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
 
-#include "QtTabbable.h"
+#pragma once
 
 #include <QCloseEvent>
+#include <QPushButton>
 #include <QShowEvent>
 #include <QTreeView>
 
+#include <Swift/Controllers/UIInterfaces/FileTransferListWidget.h>
+
+#include <Swift/QtUI/QtTabbable.h>
+
 namespace Swift {
 
 class FileTransferOverview;
@@ -36,12 +43,17 @@ public:
 private:
 	virtual void closeEvent(QCloseEvent* event);
 	virtual void showEvent(QShowEvent* event);
+	void handleFileTransferListChanged();
+
+private slots:
+	void clearInactiveTransfers();
 
 private:
 	QTreeView* treeView;
 
 	QtFileTransferListItemModel* itemModel;
 	FileTransferOverview* fileTransferOverview;
+	QPushButton* clearFinished;
 };
 
 }
-- 
cgit v0.10.2-6-g49f6