From c557a9771c99012624e104e5bc71aeb93f38a8bf Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Tue, 15 Sep 2009 08:36:24 +0100
Subject: Logout without signout, but without UI notification that you're
 logged out.


diff --git a/Swift/Controllers/ChatControllerBase.cpp b/Swift/Controllers/ChatControllerBase.cpp
index 92b77b5..519b019 100644
--- a/Swift/Controllers/ChatControllerBase.cpp
+++ b/Swift/Controllers/ChatControllerBase.cpp
@@ -21,7 +21,12 @@ ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaCha
 ChatControllerBase::~ChatControllerBase() {
 	delete chatWindow_;
 }
-	
+
+void ChatControllerBase::setEnabled(bool enabled) {
+	//FIXME: implement
+	h
+}
+
 void ChatControllerBase::setAvailableServerFeatures(boost::shared_ptr<DiscoInfo> info) {
 	if (info->hasFeature(DiscoInfo::SecurityLabels)) {
 		chatWindow_->setSecurityLabelsEnabled(true);
diff --git a/Swift/Controllers/ChatControllerBase.h b/Swift/Controllers/ChatControllerBase.h
index 3eadcc5..a977f8c 100644
--- a/Swift/Controllers/ChatControllerBase.h
+++ b/Swift/Controllers/ChatControllerBase.h
@@ -29,7 +29,7 @@ namespace Swift {
 			void activateChatWindow();
 			void setAvailableServerFeatures(boost::shared_ptr<DiscoInfo> info);
 			void handleIncomingMessage(boost::shared_ptr<MessageEvent> message);
-
+			void setEnabled(bool enabled);
 		protected:
 			ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager);
 
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 1de4011..cf85c18 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -28,7 +28,6 @@
 #include "Swiften/Client/Client.h"
 #include "Swiften/Elements/Presence.h"
 #include "Swiften/Elements/VCardUpdate.h"
-#include "Swiften/Roster/XMPPRoster.h"
 #include "Swiften/Queries/Responders/SoftwareVersionResponder.h"
 #include "Swiften/Roster/TreeWidgetFactory.h"
 #include "Swiften/Settings/SettingsProvider.h"
@@ -63,8 +62,10 @@ typedef std::pair<JID, MUCController*> JIDMUCControllerPair;
 MainController::MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory *treeWidgetFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer)
 		: client_(NULL), chatWindowFactory_(chatWindowFactory), mainWindowFactory_(mainWindowFactory), loginWindowFactory_(loginWindowFactory), treeWidgetFactory_(treeWidgetFactory), settings_(settings),
 		xmppRosterController_(NULL), rosterController_(NULL), loginWindow_(NULL), clientVersionResponder_(NULL), nickResolver_(NULL), discoResponder_(NULL), 
-		serverDiscoInfo_(new DiscoInfo()), presenceOracle_(NULL), avatarManager_(NULL) {
+		serverDiscoInfo_(new DiscoInfo()),  xmppRoster_(new XMPPRoster()) {
 	application_ = application;
+	presenceOracle_ = NULL;
+	avatarManager_ = NULL;
 
 	avatarStorage_ = new AvatarFileStorage(application_->getAvatarDir());
 
@@ -102,8 +103,12 @@ void MainController::resetClient() {
 	nickResolver_ = NULL;
 	delete avatarManager_;
 	avatarManager_ = NULL;
-	delete rosterController_;
-	rosterController_ = NULL;
+	//delete rosterController_;
+	//rosterController_ = NULL;
+	if (rosterController_) {
+		rosterController_->setAvatarManager(NULL);
+		rosterController_->setNickResolver(NULL);
+	}
 	delete xmppRosterController_;
 	xmppRosterController_ = NULL;
 	delete clientVersionResponder_;
@@ -115,28 +120,36 @@ void MainController::resetClient() {
 }
 
 void MainController::handleConnected() {
+	//FIXME: this freshLogin thing is temporary so I can see what's what before I split into a seperate method.
+	bool freshLogin = rosterController_ == NULL;
+	
 	presenceOracle_ = new PresenceOracle(client_);
-
-	lastSentPresence_ = boost::shared_ptr<Presence>();
+	if (freshLogin) {
+		lastSentPresence_ = boost::shared_ptr<Presence>();
+	}
 
 	client_->onPresenceReceived.connect(boost::bind(&MainController::handleIncomingPresence, this, _1));
 
-	boost::shared_ptr<XMPPRoster> xmppRoster(new XMPPRoster());
-
-	nickResolver_ = new NickResolver(xmppRoster);
+	nickResolver_ = new NickResolver(xmppRoster_);
 
 	avatarManager_ = new AvatarManager(client_, client_, avatarStorage_, this);
-	
-	rosterController_ = new RosterController(jid_, xmppRoster, avatarManager_, mainWindowFactory_, treeWidgetFactory_, nickResolver_);
-	rosterController_->onStartChatRequest.connect(boost::bind(&MainController::handleChatRequest, this, _1));
-	rosterController_->onJoinMUCRequest.connect(boost::bind(&MainController::handleJoinMUCRequest, this, _1, _2));
-	rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
+	if (freshLogin) {
+		rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, treeWidgetFactory_, nickResolver_);
+		rosterController_->onStartChatRequest.connect(boost::bind(&MainController::handleChatRequest, this, _1));
+		rosterController_->onJoinMUCRequest.connect(boost::bind(&MainController::handleJoinMUCRequest, this, _1, _2));
+		rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
+	} else {
+		rosterController_->setAvatarManager(avatarManager_);
+		rosterController_->setNickResolver(nickResolver_);
+	}
 
-	xmppRosterController_ = new XMPPRosterController(client_, xmppRoster);
+	xmppRosterController_ = new XMPPRosterController(client_, xmppRoster_);
 	xmppRosterController_->requestRoster();
 
 	clientVersionResponder_ = new SoftwareVersionResponder(CLIENT_NAME, CLIENT_VERSION, client_);
-	loginWindow_->morphInto(rosterController_->getWindow());
+	if (freshLogin) {
+		loginWindow_->morphInto(rosterController_->getWindow());
+	}
 
 	DiscoInfo discoInfo;
 	discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc"));
@@ -156,9 +169,15 @@ void MainController::handleConnected() {
 	vCardRequest->send();
 	
 	//Send presence last to catch all the incoming presences.
-	boost::shared_ptr<Presence> initialPresence(new Presence());
+	boost::shared_ptr<Presence> initialPresence;
+	if (queuedPresence_.get() != NULL) {
+		initialPresence = queuedPresence_;
+	} else {
+		initialPresence = boost::shared_ptr<Presence>(new Presence());
+	}
 	initialPresence->addPayload(capsInfo_);
 	sendPresence(initialPresence);
+	enableManagers();
 }
 
 void MainController::handleEventQueueLengthChange(int count) {
@@ -176,7 +195,12 @@ void MainController::handleChangeStatusRequest(StatusShow::Type show, const Stri
 		presence->setShow(show);
 	}
 	presence->setStatus(statusText);
-	sendPresence(presence);
+	if (presence->getType() != Presence::Unavailable && !client_) {
+		performLoginFromCachedCredentials();
+		queuedPresence_ = presence;
+	} else {
+		sendPresence(presence);
+	}
 }
 
 void MainController::sendPresence(boost::shared_ptr<Presence> presence) {
@@ -191,6 +215,7 @@ void MainController::sendPresence(boost::shared_ptr<Presence> presence) {
 }
 
 void MainController::handleIncomingPresence(boost::shared_ptr<Presence> presence) {
+	//FIXME: subscribe, subscribed
 	rosterController_->handleIncomingPresence(presence);
 }
 
@@ -202,15 +227,20 @@ void MainController::handleLoginRequest(const String &username, const String &pa
 	profileSettings->storeString("pass", remember ? password : "");
 	loginWindow_->addAvailableAccount(profileSettings->getStringSetting("jid"), profileSettings->getStringSetting("pass"), profileSettings->getStringSetting("certificate"));
 	delete profileSettings;
+	jid_ = JID(username);
+	password_ = password;
+	certificateFile_ = certificateFile;
+	performLoginFromCachedCredentials();
+}
 
+void MainController::performLoginFromCachedCredentials() {
 	resetClient();
 
-	jid_ = JID(username);
-	client_ = new Swift::Client(jid_, password);
+	client_ = new Swift::Client(jid_, password_);
 	//client_->onDataRead.connect(&printIncomingData);
 	//client_->onDataWritten.connect(&printOutgoingData);
-	if (!certificateFile.isEmpty()) {
-		client_->setCertificate(certificateFile);
+	if (!certificateFile_.isEmpty()) {
+		client_->setCertificate(certificateFile_);
 	}
 	client_->onError.connect(boost::bind(&MainController::handleError, this, _1));
 	client_->onConnected.connect(boost::bind(&MainController::handleConnected, this));
@@ -240,22 +270,45 @@ void MainController::handleError(const ClientError& error) {
 	logout();
 }
 
-void MainController::logout() {
+void MainController::signout() {
 	loginWindow_->loggedOut();
+	foreach (JIDChatControllerPair controllerPair, chatControllers_) {
+		delete controllerPair.second;
+	}
+	chatControllers_.clear();
+	foreach (JIDMUCControllerPair controllerPair, mucControllers_) {
+		delete controllerPair.second;
+	}
+	mucControllers_.clear();
+}
 
+void MainController::logout() {
 	delete discoResponder_;
 	discoResponder_ = NULL;
 	delete clientVersionResponder_;
 	clientVersionResponder_ = NULL;
+	disableManagers();
+	resetClient();
+}
+
+void MainController::disableManagers() {
 	foreach (JIDChatControllerPair controllerPair, chatControllers_) {
-		delete controllerPair.second;
+		controllerPair.second->setEnabled(false);
 	}
-	client_->disconnect();
-	chatControllers_.clear();
 	foreach (JIDMUCControllerPair controllerPair, mucControllers_) {
-		delete controllerPair.second;
+		controllerPair.second->setEnabled(false);
 	}
-	mucControllers_.clear();
+	rosterController_->setEnabled(false);
+}
+
+void MainController::enableManagers() {
+	foreach (JIDChatControllerPair controllerPair, chatControllers_) {
+		controllerPair.second->setEnabled(true);
+	}
+	foreach (JIDMUCControllerPair controllerPair, mucControllers_) {
+		controllerPair.second->setEnabled(true);
+	}
+	rosterController_->setEnabled(true);
 }
 
 
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index a36351e..3fbe9b4 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -16,6 +16,7 @@
 #include "Swiften/Settings/SettingsProvider.h"
 #include "Swiften/Elements/CapsInfo.h"
 #include "Swiften/MUC/MUCRegistry.h"
+#include "Swiften/Roster/XMPPRoster.h"
 
 namespace Swift {
 	class AvatarStorage;
@@ -67,10 +68,14 @@ namespace Swift {
 			ChatController* getChatController(const JID &contact);
 			void sendPresence(boost::shared_ptr<Presence> presence);
 			void logout();
+			void signout();
 
 			virtual bool isMUC(const JID& muc) const;
 	
 		private:	
+			void performLoginFromCachedCredentials();
+			void enableManagers();
+			void disableManagers();
 			Client* client_;
 			ChatWindowFactory* chatWindowFactory_;
 			MainWindowFactory* mainWindowFactory_;
@@ -91,6 +96,7 @@ namespace Swift {
 			std::map<JID, MUCController*> mucControllers_;
 			std::map<JID, ChatController*> chatControllers_;
 			boost::shared_ptr<DiscoInfo> serverDiscoInfo_;
+			boost::shared_ptr<XMPPRoster> xmppRoster_;;
 			JID jid_;
 			PresenceOracle* presenceOracle_;
 			SystemTrayController* systemTrayController_;
@@ -98,6 +104,9 @@ namespace Swift {
 			AvatarManager* avatarManager_;
 			boost::shared_ptr<Presence> lastSentPresence_;
 			String vCardPhotoHash_;
+			boost::shared_ptr<Presence> queuedPresence_;
+			String password_;
+			String certificateFile_;
 	};
 }
 #endif
diff --git a/Swift/Controllers/RosterController.cpp b/Swift/Controllers/RosterController.cpp
index 322d704..e27335b 100644
--- a/Swift/Controllers/RosterController.cpp
+++ b/Swift/Controllers/RosterController.cpp
@@ -24,19 +24,19 @@ namespace Swift {
  */
 RosterController::RosterController(const JID& jid, boost::shared_ptr<XMPPRoster> xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, TreeWidgetFactory* treeWidgetFactory, NickResolver* nickResolver)
  : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), treeWidgetFactory_(treeWidgetFactory), mainWindow_(mainWindowFactory_->createMainWindow()), roster_(new Roster(mainWindow_->getTreeWidget(), treeWidgetFactory_)), offlineFilter_(new OfflineRosterFilter()) {
-	nickResolver_ = nickResolver;
+	
 	roster_->addFilter(offlineFilter_);
-	avatarManager_ = avatarManager;
-	avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1, _2));
+	
 	mainWindow_->onStartChatRequest.connect(boost::bind(&RosterController::handleStartChatRequest, this, _1));
 	mainWindow_->onJoinMUCRequest.connect(boost::bind(&RosterController::handleJoinMUCRequest, this, _1, _2));
 	mainWindow_->onChangeStatusRequest.connect(boost::bind(&RosterController::handleChangeStatusRequest, this, _1, _2));
 	mainWindow_->onShowOfflineToggled.connect(boost::bind(&RosterController::handleShowOfflineToggled, this, _1));
 	roster_->onUserAction.connect(boost::bind(&RosterController::handleUserAction, this, _1));
 	xmppRoster_->onJIDAdded.connect(boost::bind(&RosterController::handleOnJIDAdded, this, _1));
+	avatarManager_ = NULL;
+	setAvatarManager(avatarManager);
+	setNickResolver(nickResolver);
 	
-	mainWindow_->setMyAvatarPath(avatarManager_->getAvatarPath(myJID_).string());
-	mainWindow_->setMyName(nickResolver_->jidToNick(myJID_));
 }
 
 RosterController::~RosterController() {
@@ -44,6 +44,29 @@ RosterController::~RosterController() {
 
 }
 
+void RosterController::setNickResolver(NickResolver* nickResolver) {
+	nickResolver_ = nickResolver;
+	if (nickResolver_ != NULL) {
+		mainWindow_->setMyName(nickResolver_->jidToNick(myJID_));
+	}
+}
+
+void RosterController::setAvatarManager(AvatarManager* avatarManager) {
+	if (avatarManager_ != NULL) {
+		//FIXME: disconnect old signal;
+	}
+	avatarManager_ = avatarManager;
+	if (avatarManager != NULL) {
+		avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1, _2));
+		mainWindow_->setMyAvatarPath(avatarManager_->getAvatarPath(myJID_).string());
+	}
+}
+
+void RosterController::setEnabled(bool enabled) {
+	//FIXME: implement;
+	h
+}
+
 void RosterController::handleShowOfflineToggled(bool state) {
 	if (state) {
 		roster_->removeFilter(offlineFilter_);
diff --git a/Swift/Controllers/RosterController.h b/Swift/Controllers/RosterController.h
index 2eddaf6..50aff49 100644
--- a/Swift/Controllers/RosterController.h
+++ b/Swift/Controllers/RosterController.h
@@ -26,12 +26,14 @@ namespace Swift {
 			~RosterController();
 			void showRosterWindow();
 			MainWindow* getWindow() {return mainWindow_;};
+			void setAvatarManager(AvatarManager* avatarManager);
+			void setNickResolver(NickResolver* nickResolver);
 			boost::signal<void (const JID&)> onStartChatRequest;
 			boost::signal<void (const JID&, const String&)> onJoinMUCRequest;
 			boost::signal<void (StatusShow::Type, const String&)> onChangeStatusRequest;
 			void handleIncomingPresence(boost::shared_ptr<Presence> presence);
 			void handleAvatarChanged(const JID& jid, const String& hash);
-
+			void setEnabled(bool enabled);
 		private:
 			void handleOnJIDAdded(const JID &jid);
 			void handleStartChatRequest(const JID& contact);
-- 
cgit v0.10.2-6-g49f6