From 42cf17e614f0c490ea214e36ac4e7ded2d0495b7 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Fri, 26 Mar 2010 13:42:19 +0000
Subject: Remove MUCs from the ChatsManager's list once you leave them.

Resolves: #292

diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index ac03f8a..104df22 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -56,6 +56,17 @@ void ChatsManager::handleMUCBookmarksChanged() {
 	}
 }
 
+void ChatsManager::handleUserLeftMUC(MUCController* mucController) {
+	std::map<JID, MUCController*>::iterator it;
+	for (it = mucControllers_.begin(); it != mucControllers_.end(); it++) {
+		if ((*it).second == mucController) {
+			mucControllers_.erase(it);
+			delete mucController;
+			return;
+		}
+	}
+}
+
 void ChatsManager::handleUIEvent(boost::shared_ptr<UIEvent> event) {
 	boost::shared_ptr<RequestChatUIEvent> chatEvent = boost::dynamic_pointer_cast<RequestChatUIEvent>(event);
 	if (chatEvent) {
@@ -150,8 +161,10 @@ void ChatsManager::handleJoinMUCRequest(const JID &muc, const String &nick) {
 	if (it != mucControllers_.end()) {
 		//FIXME: What's correct behaviour here?
 	} else {
-		mucControllers_[muc] = new MUCController(jid_, muc, nick, stanzaChannel_, presenceSender_, iqRouter_, chatWindowFactory_, treeWidgetFactory_, presenceOracle_, avatarManager_);
-		mucControllers_[muc]->setAvailableServerFeatures(serverDiscoInfo_);
+		MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, presenceSender_, iqRouter_, chatWindowFactory_, treeWidgetFactory_, presenceOracle_, avatarManager_);
+		mucControllers_[muc] = controller;
+		controller->setAvailableServerFeatures(serverDiscoInfo_);
+		controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller));
 	}
 	mucControllers_[muc]->activateChatWindow();
 }
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index bef766b..a1614f8 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -41,6 +41,7 @@ namespace Swift {
 			void handlePresenceChange(boost::shared_ptr<Presence> newPresence, boost::shared_ptr<Presence> lastPresence);
 			void handleUIEvent(boost::shared_ptr<UIEvent> event);
 			void handleMUCBookmarksChanged();
+			void handleUserLeftMUC(MUCController* mucController);
 			ChatController* getChatController(const JID &contact);
 			virtual bool isMUC(const JID& muc) const;
 
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 7736aec..0ec8c28 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -33,6 +33,7 @@ MUCController::MUCController (
 			muc_(new MUC(stanzaChannel, presenceSender, muc)), 
 			nick_(nick), 
 			treeWidgetFactory_(treeWidgetFactory) { 
+	parting_ = false;
 	roster_ = new Roster(chatWindow_->getTreeWidget(), treeWidgetFactory_);
 	chatWindow_->onClosed.connect(boost::bind(&MUCController::handleWindowClosed, this));
 	muc_->joinAs(nick);
@@ -42,7 +43,7 @@ MUCController::MUCController (
 	chatWindow_->convertToMUC();
 	chatWindow_->show();
 	if (avatarManager_ != NULL) {
-		avatarManager_->onAvatarChanged.connect(boost::bind(&MUCController::handleAvatarChanged, this, _1, _2));
+		avatarChangedConnection_ = (avatarManager_->onAvatarChanged.connect(boost::bind(&MUCController::handleAvatarChanged, this, _1, _2)));
 	} 
 }
 
@@ -52,12 +53,17 @@ MUCController::~MUCController() {
 }
 
 void MUCController::handleAvatarChanged(const JID& jid, const String&) {
+	if (parting_) {
+		return;
+	}
 	String path = avatarManager_->getAvatarPath(jid).string();
 	roster_->applyOnItems(SetAvatar(jid, path, JID::WithResource));
 }
 
 void MUCController::handleWindowClosed() {
+	parting_ = true;
 	muc_->part();
+	onUserLeft();
 }
 
 void MUCController::handleOccupantJoined(const MUCOccupant& occupant) {
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index bafe3db..aae2150 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -2,6 +2,8 @@
 #define SWIFTEN_MUCController_H
 
 #include <boost/shared_ptr.hpp>
+#include <boost/signals.hpp>
+#include <boost/signals/connection.hpp>
 
 #include "Swiften/Base/String.h"
 #include "Swift/Controllers/Chat/ChatControllerBase.h"
@@ -24,6 +26,7 @@ namespace Swift {
 		public:
 			MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory *treeWidgetFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager);
 			~MUCController();
+			boost::signal<void ()> onUserLeft;
 		
 		protected:
 			void preSendMessageRequest(boost::shared_ptr<Message> message);
@@ -42,6 +45,8 @@ namespace Swift {
 			String nick_;
 			TreeWidgetFactory *treeWidgetFactory_;
 			Roster *roster_;
+			bool parting_;
+			boost::bsignals::scoped_connection avatarChangedConnection_;
 	};
 }
 #endif
diff --git a/Swift/QtUI/QtChatTabs.cpp b/Swift/QtUI/QtChatTabs.cpp
index 53fa5ce..67cd8ae 100644
--- a/Swift/QtUI/QtChatTabs.cpp
+++ b/Swift/QtUI/QtChatTabs.cpp
@@ -31,7 +31,7 @@ void QtChatTabs::closeEvent(QCloseEvent* event) {
 	//Hide first to prevent flickering as each tab is removed.
 	hide();
 	for (int i = tabs_->count() - 1; i >= 0; i--) {
-		tabs_->removeTab(i);
+		tabs_->widget(i)->close();
 	}
 	event->accept();
 }
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index fe97573..e627960 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -106,9 +106,9 @@ SecurityLabel QtChatWindow::getSelectedSecurityLabel() {
 }
 
 void QtChatWindow::closeEvent(QCloseEvent* event) {
-	onClosed();
-	emit windowClosing();
 	event->accept();
+	emit windowClosing();
+	onClosed();
 }
 
 void QtChatWindow::convertToMUC() {
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp
index a6fbcbd..3c06c7a 100644
--- a/Swiften/MUC/MUC.cpp
+++ b/Swiften/MUC/MUC.cpp
@@ -13,7 +13,7 @@ namespace Swift {
 typedef std::pair<String, MUCOccupant> StringMUCOccupantPair;
 
 MUC::MUC(StanzaChannel* stanzaChannel, PresenceSender* presenceSender, const JID &muc) : ownMUCJID(muc), stanzaChannel(stanzaChannel), presenceSender(presenceSender) {
-	stanzaChannel->onPresenceReceived.connect(boost::bind(&MUC::handleIncomingPresence, this, _1));
+	scopedConnection_ = stanzaChannel->onPresenceReceived.connect(boost::bind(&MUC::handleIncomingPresence, this, _1));
 }
 
 void MUC::joinAs(const String &nick) {
diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h
index c31f9ac..1ef974f 100644
--- a/Swiften/MUC/MUC.h
+++ b/Swiften/MUC/MUC.h
@@ -6,8 +6,9 @@
 #include "Swiften/Elements/Presence.h"
 #include "Swiften/MUC/MUCOccupant.h"
 
-#include <boost/signals.hpp>
 #include <boost/shared_ptr.hpp>
+#include <boost/signals.hpp>
+#include <boost/signals/connection.hpp>
 
 #include <map>
 
@@ -53,5 +54,6 @@ namespace Swift {
 			PresenceSender* presenceSender;
 			std::map<String, MUCOccupant> occupants;
 			bool firstPresenceSeen;
+			boost::bsignals::scoped_connection scopedConnection_;
 	};
 }
-- 
cgit v0.10.2-6-g49f6