diff options
Diffstat (limited to 'Swift')
31 files changed, 708 insertions, 424 deletions
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index 722b98f..b7e8432 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -9,15 +9,20 @@  #include <boost/bind.hpp>  #include "Swift/Controllers/Chat/ChatController.h" +#include "Swift/Controllers/Chat/MUCSearchController.h"  #include "Swift/Controllers/XMPPEvents/EventController.h"  #include "Swift/Controllers/Chat/MUCController.h"  #include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"  #include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h" +#include "Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h"  #include "Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h"  #include "Swift/Controllers/UIEvents/RemoveMUCBookmarkUIEvent.h"  #include "Swift/Controllers/UIEvents/EditMUCBookmarkUIEvent.h"  #include "Swift/Controllers/UIInterfaces/ChatListWindowFactory.h" +#include "Swift/Controllers/UIInterfaces/JoinMUCWindow.h" +#include "Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h"  #include "Swiften/Presence/PresenceSender.h" +#include "Swiften/Client/NickResolver.h"  #include "Swiften/MUC/MUCManager.h"  #include "Swiften/Elements/ChatState.h"  #include "Swiften/MUC/MUCBookmarkManager.h" @@ -27,7 +32,30 @@ namespace Swift {  typedef std::pair<JID, ChatController*> JIDChatControllerPair;  typedef std::pair<JID, MUCController*> JIDMUCControllerPair; -ChatsManager::ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager) : jid_(jid), useDelayForLatency_(useDelayForLatency), mucRegistry_(mucRegistry), entityCapsProvider_(entityCapsProvider), mucManager(mucManager) { +ChatsManager::ChatsManager( +		JID jid, StanzaChannel* stanzaChannel,  +		IQRouter* iqRouter,  +		EventController* eventController,  +		ChatWindowFactory* chatWindowFactory,  +		JoinMUCWindowFactory* joinMUCWindowFactory,  +		NickResolver* nickResolver,  +		PresenceOracle* presenceOracle,  +		PresenceSender* presenceSender,  +		UIEventStream* uiEventStream,  +		ChatListWindowFactory* chatListWindowFactory,  +		bool useDelayForLatency,  +		TimerFactory* timerFactory,  +		MUCRegistry* mucRegistry,  +		EntityCapsProvider* entityCapsProvider,  +		MUCManager* mucManager, +		MUCSearchWindowFactory* mucSearchWindowFactory, +		SettingsProvider* settings) :  +			jid_(jid),  +			joinMUCWindowFactory_(joinMUCWindowFactory),  +			useDelayForLatency_(useDelayForLatency),  +			mucRegistry_(mucRegistry),  +			entityCapsProvider_(entityCapsProvider),  +			mucManager(mucManager)  {  	timerFactory_ = timerFactory;  	eventController_ = eventController;  	stanzaChannel_ = stanzaChannel; @@ -43,10 +71,14 @@ ChatsManager::ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRo  	presenceOracle_->onPresenceChange.connect(boost::bind(&ChatsManager::handlePresenceChange, this, _1));  	uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&ChatsManager::handleUIEvent, this, _1));  	chatListWindow_ = chatListWindowFactory->createChatListWindow(uiEventStream_); +	joinMUCWindow_ = NULL; +	mucSearchController_ = new MUCSearchController(jid_, mucSearchWindowFactory, iqRouter, settings); +	mucSearchController_->onMUCSelected.connect(boost::bind(&ChatsManager::handleMUCSelectedAfterSearch, this, _1));  	setupBookmarks();  }  ChatsManager::~ChatsManager() { +	delete joinMUCWindow_;  	foreach (JIDChatControllerPair controllerPair, chatControllers_) {  		delete controllerPair.second;  	} @@ -54,6 +86,7 @@ ChatsManager::~ChatsManager() {  		delete controllerPair.second;  	}  	delete mucBookmarkManager_; +	delete mucSearchController_;  }  void ChatsManager::setupBookmarks() { @@ -80,7 +113,7 @@ void ChatsManager::handleMUCBookmarkAdded(const MUCBookmark& bookmark) {  	std::map<JID, MUCController*>::iterator it = mucControllers_.find(bookmark.getRoom());  	if (it == mucControllers_.end() && bookmark.getAutojoin()) {  		//FIXME: need vcard stuff here to get a nick -		handleJoinMUCRequest(bookmark.getRoom(), bookmark.getNick()); +		handleJoinMUCRequest(bookmark.getRoom(), bookmark.getNick(), false);  	}  	chatListWindow_->addMUCBookmark(bookmark);  } @@ -106,11 +139,6 @@ void ChatsManager::handleUIEvent(boost::shared_ptr<UIEvent> event) {  		handleChatRequest(chatEvent->getContact());  		return;  	} -	boost::shared_ptr<JoinMUCUIEvent> joinMUCEvent = boost::dynamic_pointer_cast<JoinMUCUIEvent>(event); -	if (joinMUCEvent) { -		handleJoinMUCRequest(joinMUCEvent->getJID(), joinMUCEvent->getNick()); -		return; -	}  	boost::shared_ptr<RemoveMUCBookmarkUIEvent> removeMUCBookmarkEvent = boost::dynamic_pointer_cast<RemoveMUCBookmarkUIEvent>(event);  	if (removeMUCBookmarkEvent) {  		mucBookmarkManager_->removeBookmark(removeMUCBookmarkEvent->getBookmark()); @@ -121,10 +149,23 @@ void ChatsManager::handleUIEvent(boost::shared_ptr<UIEvent> event) {  		mucBookmarkManager_->addBookmark(addMUCBookmarkEvent->getBookmark());  		return;  	} +  	boost::shared_ptr<EditMUCBookmarkUIEvent> editMUCBookmarkEvent = boost::dynamic_pointer_cast<EditMUCBookmarkUIEvent>(event);  	if (editMUCBookmarkEvent) {  		mucBookmarkManager_->replaceBookmark(editMUCBookmarkEvent->getOldBookmark(), editMUCBookmarkEvent->getNewBookmark()); -		return; +	} +	else if (JoinMUCUIEvent::ref joinEvent = boost::dynamic_pointer_cast<JoinMUCUIEvent>(event)) { +		handleJoinMUCRequest(joinEvent->getJID(), joinEvent->getNick(), false); +	} +	else if (boost::dynamic_pointer_cast<RequestJoinMUCUIEvent>(event)) { +		if (!joinMUCWindow_) { +			joinMUCWindow_ = joinMUCWindowFactory_->createJoinMUCWindow(); +			joinMUCWindow_->onJoinMUC.connect(boost::bind(&ChatsManager::handleJoinMUCRequest, this, _1, _2, _3)); +			joinMUCWindow_->onSearchMUC.connect(boost::bind(&ChatsManager::handleSearchMUCRequest, this)); +		} +		joinMUCWindow_->setMUC(""); +		joinMUCWindow_->setNick(nickResolver_->jidToNick(jid_)); +		joinMUCWindow_->show();  	}  } @@ -239,7 +280,16 @@ void ChatsManager::rebindControllerJID(const JID& from, const JID& to) {  	chatControllers_[to]->setToJID(to);  } -void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional<String>& nickMaybe) { +void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional<String>& nickMaybe, bool autoJoin) { +	if (autoJoin) { +		MUCBookmark bookmark(mucJID, mucJID.getNode()); +		bookmark.setAutojoin(true); +		if (nickMaybe) { +			bookmark.setNick(*nickMaybe); +		} +		mucBookmarkManager_->addBookmark(bookmark); +	} +  	std::map<JID, MUCController*>::iterator it = mucControllers_.find(mucJID);  	if (it != mucControllers_.end()) {  		it->second->rejoin(); @@ -254,6 +304,10 @@ void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional  	mucControllers_[mucJID]->activateChatWindow();  } +void ChatsManager::handleSearchMUCRequest() { +	mucSearchController_->openSearchWindow(); +} +  void ChatsManager::handleIncomingMessage(boost::shared_ptr<Message> message) {  	JID jid = message->getFrom();  	boost::shared_ptr<MessageEvent> event(new MessageEvent(message)); @@ -278,4 +332,11 @@ void ChatsManager::handleIncomingMessage(boost::shared_ptr<Message> message) {  	getChatControllerOrCreate(jid)->handleIncomingMessage(event);  } +void ChatsManager::handleMUCSelectedAfterSearch(const JID& muc) { +	if (joinMUCWindow_) { +		joinMUCWindow_->setMUC(muc.toString()); +	} +} + +  } diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h index 2b771eb..62b14d9 100644 --- a/Swift/Controllers/Chat/ChatsManager.h +++ b/Swift/Controllers/Chat/ChatsManager.h @@ -25,6 +25,8 @@ namespace Swift {  	class MUCController;  	class MUCManager;  	class ChatWindowFactory; +	class JoinMUCWindow; +	class JoinMUCWindowFactory;  	class NickResolver;  	class PresenceOracle;  	class AvatarManager; @@ -37,10 +39,13 @@ namespace Swift {  	class TimerFactory;  	class EntityCapsProvider;  	class DirectedPresenceSender; +	class MUCSearchWindowFactory; +	class SettingsProvider; +	class MUCSearchController;  	class ChatsManager {  		public: -			ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager); +			ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, JoinMUCWindowFactory* joinMUCWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager, MUCSearchWindowFactory* mucSearchWindowFactory, SettingsProvider* settings);  			virtual ~ChatsManager();  			void setAvatarManager(AvatarManager* avatarManager);  			void setOnline(bool enabled); @@ -48,7 +53,9 @@ namespace Swift {  			void handleIncomingMessage(boost::shared_ptr<Message> message);  		private:  			void handleChatRequest(const String& contact); -			void handleJoinMUCRequest(const JID& muc, const boost::optional<String>& nick); +			void handleJoinMUCRequest(const JID& muc, const boost::optional<String>& nick, bool autoJoin); +			void handleSearchMUCRequest(); +			void handleMUCSelectedAfterSearch(const JID&);  			void rebindControllerJID(const JID& from, const JID& to);  			void handlePresenceChange(boost::shared_ptr<Presence> newPresence);  			void handleUIEvent(boost::shared_ptr<UIEvent> event); @@ -68,6 +75,7 @@ namespace Swift {  			StanzaChannel* stanzaChannel_;  			IQRouter* iqRouter_;  			ChatWindowFactory* chatWindowFactory_; +			JoinMUCWindowFactory* joinMUCWindowFactory_;  			NickResolver* nickResolver_;  			PresenceOracle* presenceOracle_;  			AvatarManager* avatarManager_; @@ -76,11 +84,13 @@ namespace Swift {  			MUCBookmarkManager* mucBookmarkManager_;  			boost::shared_ptr<DiscoInfo> serverDiscoInfo_;  			ChatListWindow* chatListWindow_; +			JoinMUCWindow* joinMUCWindow_;  			boost::bsignals::scoped_connection uiEventConnection_;  			bool useDelayForLatency_;  			TimerFactory* timerFactory_;  			MUCRegistry* mucRegistry_;  			EntityCapsProvider* entityCapsProvider_;  			MUCManager* mucManager; +			MUCSearchController* mucSearchController_;  	};  } diff --git a/Swift/Controllers/Chat/MUCSearchController.cpp b/Swift/Controllers/Chat/MUCSearchController.cpp index c254e51..c85f793 100644 --- a/Swift/Controllers/Chat/MUCSearchController.cpp +++ b/Swift/Controllers/Chat/MUCSearchController.cpp @@ -11,12 +11,9 @@  #include <boost/bind.hpp>  #include <boost/shared_ptr.hpp> -#include <Swiften/Disco/GetDiscoInfoRequest.h>  #include <Swiften/Disco/GetDiscoItemsRequest.h> - +#include <Swiften/Base/Log.h>  #include <Swift/Controllers/UIEvents/UIEventStream.h> -#include <Swift/Controllers/UIEvents/RequestMUCSearchUIEvent.h> -#include <Swift/Controllers/UIInterfaces/MUCSearchWindow.h>  #include <Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h>  #include <Swift/Controllers/DiscoServiceWalker.h>  #include <Swiften/Client/NickResolver.h> @@ -25,57 +22,43 @@ namespace Swift {  static const String SEARCHED_SERVICES = "searchedServices"; -MUCSearchController::MUCSearchController(const JID& jid, UIEventStream* uiEventStream, MUCSearchWindowFactory* factory, IQRouter* iqRouter, SettingsProvider* settings, NickResolver *nickResolver) : jid_(jid) { -	iqRouter_ = iqRouter; -	settings_ = settings; -	uiEventStream_ = uiEventStream; -	nickResolver_ = nickResolver; +MUCSearchController::MUCSearchController(const JID& jid, MUCSearchWindowFactory* factory, IQRouter* iqRouter, SettingsProvider* settings) : jid_(jid), factory_(factory), iqRouter_(iqRouter), settings_(settings), window_(NULL), walker_(NULL) {  	itemsInProgress_ = 0; -	uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&MUCSearchController::handleUIEvent, this, _1)); -	window_ = NULL; -	factory_ = factory; -	loadServices(); +	loadSavedServices();  }  MUCSearchController::~MUCSearchController() { -	foreach (DiscoServiceWalker* walker, walksInProgress_) { -		delete walker; -	} +	delete walker_;  	delete window_;  } -void MUCSearchController::handleUIEvent(boost::shared_ptr<UIEvent> event) { -	boost::shared_ptr<RequestMUCSearchUIEvent> searchEvent = boost::dynamic_pointer_cast<RequestMUCSearchUIEvent>(event); -	if (searchEvent) { -		if (!window_) { -			window_ = factory_->createMUCSearchWindow(uiEventStream_); -			window_->onAddService.connect(boost::bind(&MUCSearchController::handleAddService, this, _1)); -			window_->addSavedServices(savedServices_); -			handleAddService(JID(jid_.getDomain())); -		} -		window_->setMUC(""); -		window_->setNick(nickResolver_->jidToNick(jid_)); -		window_->show(); -		return; +void MUCSearchController::openSearchWindow() { +	if (!window_) { +		window_ = factory_->createMUCSearchWindow(); +		window_->onSearchService.connect(boost::bind(&MUCSearchController::handleSearchService, this, _1)); +		window_->onFinished.connect(boost::bind(&MUCSearchController::handleMUCSearchFinished, this, _1)); +		window_->addSavedServices(savedServices_); +		handleSearchService(JID(jid_.getDomain()));  	} +	window_->show();  } -void MUCSearchController::loadServices() { +void MUCSearchController::loadSavedServices() {  	savedServices_.clear();  	foreach (String stringItem, settings_->getStringSetting(SEARCHED_SERVICES).split('\n')) {  		savedServices_.push_back(JID(stringItem));  	}  } -void MUCSearchController::addAndSaveServices(const JID& jid) { +void MUCSearchController::addToSavedServices(const JID& jid) {  	savedServices_.erase(std::remove(savedServices_.begin(), savedServices_.end(), jid), savedServices_.end()); -	savedServices_.push_back(jid); +	savedServices_.push_front(jid); +  	String collapsed; -	bool storeThis = savedServices_.size() < 15; +	int i = 0;  	foreach (JID jidItem, savedServices_) { -		if (!storeThis) { -			storeThis = true; -			continue; +		if (i >= 15) { +			break;  		}  		if (!collapsed.isEmpty()) {  			collapsed += "\n"; @@ -86,21 +69,32 @@ void MUCSearchController::addAndSaveServices(const JID& jid) {  	window_->addSavedServices(savedServices_);  } -void MUCSearchController::handleAddService(const JID& jid) { +void MUCSearchController::handleSearchService(const JID& jid) {  	if (!jid.isValid()) {  		//Set Window to say error this isn't valid  		return;  	} -	addAndSaveServices(jid); -	services_.push_back(jid); -	serviceDetails_[jid].setComplete(false); +	addToSavedServices(jid); + +	services_.clear(); +	serviceDetails_.clear(); +  	window_->setSearchInProgress(true);  	refreshView(); -	DiscoServiceWalker* walker = new DiscoServiceWalker(jid, iqRouter_); -	walker->onServiceFound.connect(boost::bind(&MUCSearchController::handleDiscoServiceFound, this, _1, _2)); -	walker->onWalkComplete.connect(boost::bind(&MUCSearchController::handleDiscoWalkFinished, this, walker)); -	walksInProgress_.push_back(walker); -	walker->beginWalk(); + +	if (walker_) { +		walker_->endWalk(); +		walker_->onServiceFound.disconnect(boost::bind(&MUCSearchController::handleDiscoServiceFound, this, _1, _2)); +		walker_->onWalkComplete.disconnect(boost::bind(&MUCSearchController::handleDiscoWalkFinished, this)); +		delete walker_; +	} + +	SWIFT_LOG(debug) << "Starting walking MUC services" << std::endl; +	itemsInProgress_ = 0; +	walker_ = new DiscoServiceWalker(jid, iqRouter_); +	walker_->onServiceFound.connect(boost::bind(&MUCSearchController::handleDiscoServiceFound, this, _1, _2)); +	walker_->onWalkComplete.connect(boost::bind(&MUCSearchController::handleDiscoWalkFinished, this)); +	walker_->beginWalk();  }  void MUCSearchController::handleDiscoServiceFound(const JID& jid, boost::shared_ptr<DiscoInfo> info) { @@ -116,25 +110,27 @@ void MUCSearchController::handleDiscoServiceFound(const JID& jid, boost::shared_  			}  	}  	if (isMUC) { -		services_.erase(std::remove(services_.begin(), services_.end(), jid), services_.end()); /* Bring it back to the end on a refresh */ +		SWIFT_LOG(debug) << "MUC Service found: " << jid << std::endl; +		services_.erase(std::remove(services_.begin(), services_.end(), jid), services_.end());  		services_.push_back(jid);  		serviceDetails_[jid].setName(name);  		serviceDetails_[jid].setJID(jid);  		serviceDetails_[jid].setComplete(false);  		itemsInProgress_++; +		SWIFT_LOG(debug) << "Requesting items of " << jid << " (" << itemsInProgress_ << " item requests in progress)" << std::endl;  		GetDiscoItemsRequest::ref discoItemsRequest = GetDiscoItemsRequest::create(jid, iqRouter_);  		discoItemsRequest->onResponse.connect(boost::bind(&MUCSearchController::handleRoomsItemsResponse, this, _1, _2, jid));  		discoItemsRequest->send(); -	} else { +	}  +	else {  		removeService(jid);  	}  	refreshView();  } -void MUCSearchController::handleDiscoWalkFinished(DiscoServiceWalker* walker) { -	walksInProgress_.erase(std::remove(walksInProgress_.begin(), walksInProgress_.end(), walker), walksInProgress_.end()); +void MUCSearchController::handleDiscoWalkFinished() { +	SWIFT_LOG(debug) << "MUC Walk finished" << std::endl;  	updateInProgressness(); -	delete walker;  }  void MUCSearchController::removeService(const JID& jid) { @@ -145,6 +141,7 @@ void MUCSearchController::removeService(const JID& jid) {  void MUCSearchController::handleRoomsItemsResponse(boost::shared_ptr<DiscoItems> items, ErrorPayload::ref error, const JID& jid) {  	itemsInProgress_--; +	SWIFT_LOG(debug) << "Items received for " << jid << " (" << itemsInProgress_ << " item requests in progress)" << std::endl;  	updateInProgressness();  	if (error) {  		handleDiscoError(jid, error); @@ -171,7 +168,13 @@ void MUCSearchController::refreshView() {  }  void MUCSearchController::updateInProgressness() { -	window_->setSearchInProgress(walksInProgress_.size() + itemsInProgress_ > 0); +	window_->setSearchInProgress((walker_ && walker_->isActive()) || itemsInProgress_ > 0); +} + +void MUCSearchController::handleMUCSearchFinished(const boost::optional<JID>& result) { +	if (result) { +		onMUCSelected(*result); +	}  }  } diff --git a/Swift/Controllers/Chat/MUCSearchController.h b/Swift/Controllers/Chat/MUCSearchController.h index 6caee54..6d3afd1 100644 --- a/Swift/Controllers/Chat/MUCSearchController.h +++ b/Swift/Controllers/Chat/MUCSearchController.h @@ -88,32 +88,38 @@ namespace Swift {  	class MUCSearchController {  		public: -			MUCSearchController(const JID& jid, UIEventStream* uiEventStream, MUCSearchWindowFactory* mucSearchWindowFactory, IQRouter* iqRouter, SettingsProvider* settings, NickResolver* nickResolver); +			MUCSearchController(const JID& jid, MUCSearchWindowFactory* mucSearchWindowFactory, IQRouter* iqRouter, SettingsProvider* settings);  			~MUCSearchController(); + +			void openSearchWindow(); + +		public: +			boost::signal<void (const JID&)> onMUCSelected; +  		private: -			void handleUIEvent(boost::shared_ptr<UIEvent> event); -			void handleAddService(const JID& jid); +			void handleSearchService(const JID& jid);  			void handleRoomsItemsResponse(boost::shared_ptr<DiscoItems> items, ErrorPayload::ref error, const JID& jid);  			void handleDiscoError(const JID& jid, ErrorPayload::ref error);  			void handleDiscoServiceFound(const JID&, boost::shared_ptr<DiscoInfo>); -			void handleDiscoWalkFinished(DiscoServiceWalker* walker); +			void handleDiscoWalkFinished(); +			void handleMUCSearchFinished(const boost::optional<JID>& result);  			void removeService(const JID& jid);  			void refreshView(); -			void loadServices(); -			void addAndSaveServices(const JID& jid); +			void loadSavedServices(); +			void addToSavedServices(const JID& jid);  			void updateInProgressness(); -			UIEventStream* uiEventStream_; -			MUCSearchWindow* window_; + +		private: +			JID jid_;  			MUCSearchWindowFactory* factory_; +			IQRouter* iqRouter_;  			SettingsProvider* settings_; -			NickResolver* nickResolver_; -			boost::bsignals::scoped_connection uiEventConnection_; -			std::vector<JID> services_; -			std::vector<JID> savedServices_; +			MUCSearchWindow* window_; +			DiscoServiceWalker* walker_; +			std::list<JID> services_; +			std::list<JID> savedServices_;  			std::map<JID, MUCService> serviceDetails_;  			std::vector<DiscoServiceWalker*> walksInProgress_; -			IQRouter* iqRouter_; -			JID jid_;  			int itemsInProgress_;  	};  } diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp index 6d20f70..be262bc 100644 --- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp @@ -11,8 +11,11 @@  #include "Swift/Controllers/Chat/ChatsManager.h"  #include "Swift/Controllers/UIInterfaces/ChatWindow.h" +#include "Swift/Controllers/Settings/DummySettingsProvider.h"  #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"  #include "Swift/Controllers/UIInterfaces/ChatListWindowFactory.h" +#include "Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h" +#include "Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h"  #include "Swiften/Client/Client.h"  #include "Swiften/Disco/EntityCapsManager.h"  #include "Swiften/Disco/CapsProvider.h" @@ -68,6 +71,7 @@ public:  		capsProvider_ = new DummyCapsProvider();  		eventController_ = new EventController();  		chatWindowFactory_ = mocks_->InterfaceMock<ChatWindowFactory>(); +		joinMUCWindowFactory_ = mocks_->InterfaceMock<JoinMUCWindowFactory>();  		xmppRoster_ = new XMPPRosterImpl();  		mucRegistry_ = new MUCRegistry();  		nickResolver_ = new NickResolver(jid_.toBare(), xmppRoster_, NULL, mucRegistry_); @@ -79,8 +83,10 @@ public:  		uiEventStream_ = new UIEventStream();  		entityCapsManager_ = new EntityCapsManager(capsProvider_, stanzaChannel_);  		chatListWindowFactory_ = mocks_->InterfaceMock<ChatListWindowFactory>(); +		mucSearchWindowFactory_ = mocks_->InterfaceMock<MUCSearchWindowFactory>(); +		settings_ = new DummySettingsProvider();  		mocks_->ExpectCall(chatListWindowFactory_, ChatListWindowFactory::createChatListWindow).With(uiEventStream_).Return(NULL); -		manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, NULL, mucRegistry_, entityCapsManager_, mucManager_); +		manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, NULL, mucRegistry_, entityCapsManager_, mucManager_, mucSearchWindowFactory_, settings_);  		avatarManager_ = new NullAvatarManager();  		manager_->setAvatarManager(avatarManager_); @@ -88,6 +94,7 @@ public:  	void tearDown() {  		//delete chatListWindowFactory_; +		delete settings_;  		delete mocks_;  		delete avatarManager_;  		delete manager_; @@ -325,6 +332,7 @@ private:  	IQRouter* iqRouter_;  	EventController* eventController_;  	ChatWindowFactory* chatWindowFactory_; +	JoinMUCWindowFactory* joinMUCWindowFactory_;  	NickResolver* nickResolver_;  	PresenceOracle* presenceOracle_;  	AvatarManager* avatarManager_; @@ -334,11 +342,13 @@ private:  	MockRepository* mocks_;  	UIEventStream* uiEventStream_;  	ChatListWindowFactory* chatListWindowFactory_; +	MUCSearchWindowFactory* mucSearchWindowFactory_;  	MUCRegistry* mucRegistry_;  	DirectedPresenceSender* directedPresenceSender_;  	EntityCapsManager* entityCapsManager_;  	CapsProvider* capsProvider_;  	MUCManager* mucManager_; +	DummySettingsProvider* settings_;  };  CPPUNIT_TEST_SUITE_REGISTRATION(ChatsManagerTest); diff --git a/Swift/Controllers/DiscoServiceWalker.cpp b/Swift/Controllers/DiscoServiceWalker.cpp index 505acb4..15d2aaa 100644 --- a/Swift/Controllers/DiscoServiceWalker.cpp +++ b/Swift/Controllers/DiscoServiceWalker.cpp @@ -141,10 +141,12 @@ void DiscoServiceWalker::markNodeCompleted(const JID& jid) {  	servicesBeingSearched_.erase(jid);  	/* All results are in */  	if (servicesBeingSearched_.size() == 0) { +		active_ = false;  		onWalkComplete();  	}  	/* Check if we're on a rampage */ -	if (searchedServices_.size() >= maxSteps_) { +	else if (searchedServices_.size() >= maxSteps_) { +		active_ = false;  		onWalkComplete();  	}  } diff --git a/Swift/Controllers/DiscoServiceWalker.h b/Swift/Controllers/DiscoServiceWalker.h index 167174a..00e2436 100644 --- a/Swift/Controllers/DiscoServiceWalker.h +++ b/Swift/Controllers/DiscoServiceWalker.h @@ -41,6 +41,10 @@ namespace Swift {  			 */  			void endWalk(); +			bool isActive() const { +				return active_; +			} +  			/** Emitted for each service found. */  			boost::signal<void(const JID&, boost::shared_ptr<DiscoInfo>)> onServiceFound; diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index bc40f95..f07a964 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -98,7 +98,6 @@ MainController::MainController(  	rosterController_ = NULL;  	chatsManager_ = NULL;  	eventWindowController_ = NULL; -	mucSearchController_ = NULL;  	userSearchControllerChat_ = NULL;  	userSearchControllerAdd_ = NULL;  	quitRequested_ = false; @@ -171,8 +170,6 @@ MainController::~MainController() {  void MainController::resetClient() {  	resetCurrentError();  	resetPendingReconnects(); -	delete mucSearchController_; -	mucSearchController_ = NULL;  	delete eventWindowController_;  	eventWindowController_ = NULL;  	delete chatsManager_; @@ -235,7 +232,7 @@ void MainController::handleConnected() {  		rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));  		rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this)); -		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager()); +		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, settings_);  		client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));  		chatsManager_->setAvatarManager(client_->getAvatarManager()); @@ -251,7 +248,6 @@ void MainController::handleConnected() {  		client_->getDiscoManager()->setDiscoInfo(discoInfo); -		mucSearchController_ = new MUCSearchController(jid_, uiEventStream_, uiFactory_, client_->getIQRouter(), settings_, client_->getNickResolver());  		userSearchControllerChat_ = new UserSearchController(UserSearchController::StartChat, jid_, uiEventStream_, uiFactory_, client_->getIQRouter());  		userSearchControllerAdd_ = new UserSearchController(UserSearchController::AddContact, jid_, uiEventStream_, uiFactory_, client_->getIQRouter());  	} diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h index 900319e..a933a5a 100644 --- a/Swift/Controllers/MainController.h +++ b/Swift/Controllers/MainController.h @@ -139,7 +139,6 @@ namespace Swift {  			String certificateFile_;  			boost::shared_ptr<ErrorEvent> lastDisconnectError_;  			bool useDelayForLatency_; -			MUCSearchController* mucSearchController_;  			UserSearchController* userSearchControllerChat_;  			UserSearchController* userSearchControllerAdd_;  			int timeBeforeNextReconnect_; diff --git a/Swift/Controllers/UIEvents/JoinMUCUIEvent.h b/Swift/Controllers/UIEvents/JoinMUCUIEvent.h index d294fe8..2a2cd96 100644 --- a/Swift/Controllers/UIEvents/JoinMUCUIEvent.h +++ b/Swift/Controllers/UIEvents/JoinMUCUIEvent.h @@ -7,6 +7,7 @@  #pragma once  #include <boost/optional.hpp> +#include <boost/shared_ptr.hpp>  #include "Swiften/Base/String.h"  #include "Swift/Controllers/UIEvents/UIEvent.h" @@ -14,6 +15,7 @@  namespace Swift {  	class JoinMUCUIEvent : public UIEvent {  		public: +			typedef boost::shared_ptr<JoinMUCUIEvent> ref;  			JoinMUCUIEvent(const JID& jid, const boost::optional<String>& nick = boost::optional<String>()) : jid_(jid), nick_(nick) {};  			boost::optional<String> getNick() {return nick_;};  			JID getJID() {return jid_;}; diff --git a/Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h b/Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h new file mode 100644 index 0000000..1415140 --- /dev/null +++ b/Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> + +#include <Swiften/Base/String.h> +#include <Swift/Controllers/UIEvents/UIEvent.h> + +namespace Swift { +	class RequestJoinMUCUIEvent : public UIEvent { +		public: +			typedef boost::shared_ptr<RequestJoinMUCUIEvent> ref; + +			RequestJoinMUCUIEvent() { +			} +	}; +} diff --git a/Swift/Controllers/UIEvents/RequestMUCSearchUIEvent.h b/Swift/Controllers/UIEvents/RequestMUCSearchUIEvent.h deleted file mode 100644 index 623cd00..0000000 --- a/Swift/Controllers/UIEvents/RequestMUCSearchUIEvent.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include "Swift/Controllers/UIEvents/UIEvent.h" - -namespace Swift { -	class RequestMUCSearchUIEvent : public UIEvent { - -	}; -} diff --git a/Swift/Controllers/UIInterfaces/JoinMUCWindow.h b/Swift/Controllers/UIInterfaces/JoinMUCWindow.h new file mode 100644 index 0000000..8cf712c --- /dev/null +++ b/Swift/Controllers/UIInterfaces/JoinMUCWindow.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <vector> + +#include <Swiften/Base/String.h> +#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/JID/JID.h> + +namespace Swift { +	class JoinMUCWindow { +		public: +			virtual ~JoinMUCWindow() {}; + +			virtual void setNick(const String& nick) = 0; +			virtual void setMUC(const String& nick) = 0; +			virtual void show() = 0; + +			boost::signal<void (const JID& /* muc */, const String& /* nick */, bool /* autoJoin */)> onJoinMUC; +			boost::signal<void ()> onSearchMUC; +	}; +} diff --git a/Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h b/Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h new file mode 100644 index 0000000..9c8bd77 --- /dev/null +++ b/Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swift/Controllers/UIInterfaces/JoinMUCWindow.h> + +namespace Swift { +	class JoinMUCWindowFactory { +		public: +			virtual ~JoinMUCWindowFactory() {}; + +			virtual JoinMUCWindow* createJoinMUCWindow() = 0; +	}; +} diff --git a/Swift/Controllers/UIInterfaces/MUCSearchWindow.h b/Swift/Controllers/UIInterfaces/MUCSearchWindow.h index 3c0ab12..ded2a0a 100644 --- a/Swift/Controllers/UIInterfaces/MUCSearchWindow.h +++ b/Swift/Controllers/UIInterfaces/MUCSearchWindow.h @@ -10,10 +10,10 @@  #include <vector> +#include <boost/optional.hpp>  #include "Swiften/Base/String.h"  #include "Swiften/JID/JID.h" - -#include "Swift/Controllers/Chat/MUCSearchController.h" +#include <Swift/Controllers/Chat/MUCSearchController.h>  namespace Swift { @@ -21,15 +21,14 @@ namespace Swift {  		public:  			virtual ~MUCSearchWindow() {}; -			virtual void setNick(const String& nick) = 0; -			virtual void setMUC(const String& nick) = 0;  			virtual void clearList() = 0;  			virtual void addService(const MUCService& service) = 0; -			virtual void addSavedServices(const std::vector<JID>& services) = 0; +			virtual void addSavedServices(const std::list<JID>& services) = 0;  			virtual void setSearchInProgress(bool searching) = 0;  			virtual void show() = 0; -			boost::signal<void (const JID&)> onAddService; +			boost::signal<void (const JID&)> onSearchService; +			boost::signal<void (const boost::optional<JID>&)> onFinished;  	};  } diff --git a/Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h b/Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h index 1f0bf90..d334dff 100644 --- a/Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h +++ b/Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h @@ -14,6 +14,6 @@ namespace Swift {  		public:  			virtual ~MUCSearchWindowFactory() {}; -			virtual MUCSearchWindow* createMUCSearchWindow(UIEventStream* eventStream) = 0; +			virtual MUCSearchWindow* createMUCSearchWindow() = 0;  	};  } diff --git a/Swift/Controllers/UIInterfaces/UIFactory.h b/Swift/Controllers/UIInterfaces/UIFactory.h index acb7638..4783dc8 100644 --- a/Swift/Controllers/UIInterfaces/UIFactory.h +++ b/Swift/Controllers/UIInterfaces/UIFactory.h @@ -12,11 +12,21 @@  #include <Swift/Controllers/UIInterfaces/LoginWindowFactory.h>  #include <Swift/Controllers/UIInterfaces/MainWindowFactory.h>  #include <Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h> +#include <Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h>  #include <Swift/Controllers/UIInterfaces/UserSearchWindowFactory.h>  #include <Swift/Controllers/UIInterfaces/XMLConsoleWidgetFactory.h>  namespace Swift { -	class UIFactory : public ChatListWindowFactory, public ChatWindowFactory, public EventWindowFactory, public LoginWindowFactory, public MainWindowFactory, public MUCSearchWindowFactory, public XMLConsoleWidgetFactory, public UserSearchWindowFactory { +	class UIFactory :  +			public ChatListWindowFactory,  +			public ChatWindowFactory,  +			public EventWindowFactory,  +			public LoginWindowFactory,  +			public MainWindowFactory,  +			public MUCSearchWindowFactory,  +			public XMLConsoleWidgetFactory,  +			public UserSearchWindowFactory,  +			public JoinMUCWindowFactory {  		public:  			virtual ~UIFactory() {}  	}; diff --git a/Swift/QtUI/MUCSearch/MUCSearchEmptyItem.cpp b/Swift/QtUI/MUCSearch/MUCSearchEmptyItem.cpp new file mode 100644 index 0000000..b1b4175 --- /dev/null +++ b/Swift/QtUI/MUCSearch/MUCSearchEmptyItem.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swift/QtUI/MUCSearch/MUCSearchEmptyItem.h> + +#include <Swift/QtUI/MUCSearch/MUCSearchServiceItem.h> +#include <QFont> +#include <QColor> + +namespace Swift { +MUCSearchEmptyItem::MUCSearchEmptyItem(MUCSearchServiceItem* parent) : parent(parent) { +	parent->addRoom(this); +} + +MUCSearchServiceItem* MUCSearchEmptyItem::getParent() { +	return parent; +} + +QVariant MUCSearchEmptyItem::data(int role) { +	switch (role) { +		case Qt::DisplayRole: +			return QVariant("No rooms found"); +		case Qt::FontRole: { +			QFont font; +			font.setItalic(true); +			return font; +		} +		case Qt::ForegroundRole: +			return QColor(Qt::gray); +		default: +			return QVariant(); +	} +} + +} diff --git a/Swift/QtUI/MUCSearch/MUCSearchEmptyItem.h b/Swift/QtUI/MUCSearch/MUCSearchEmptyItem.h new file mode 100644 index 0000000..d752ae3 --- /dev/null +++ b/Swift/QtUI/MUCSearch/MUCSearchEmptyItem.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swift/QtUI/MUCSearch/MUCSearchItem.h> + +namespace Swift { +	class MUCSearchServiceItem; + +	class MUCSearchEmptyItem : public MUCSearchItem { +		public: +			MUCSearchEmptyItem(MUCSearchServiceItem* parent); + +			MUCSearchServiceItem* getParent(); + +			QVariant data(int role); + +		private: +			MUCSearchServiceItem* parent; +	}; +} diff --git a/Swift/QtUI/MUCSearch/MUCSearchModel.cpp b/Swift/QtUI/MUCSearch/MUCSearchModel.cpp index 2526039..c657190 100644 --- a/Swift/QtUI/MUCSearch/MUCSearchModel.cpp +++ b/Swift/QtUI/MUCSearch/MUCSearchModel.cpp @@ -5,6 +5,7 @@   */  #include "Swift/QtUI/MUCSearch/MUCSearchModel.h" +#include "Swift/QtUI/MUCSearch/MUCSearchEmptyItem.h"  namespace Swift { @@ -39,7 +40,6 @@ QModelIndex MUCSearchModel::index(int row, int column, const QModelIndex & paren  	if (parent.isValid()) {  		MUCSearchServiceItem* parentItem = static_cast<MUCSearchServiceItem*>(parent.internalPointer());  		return row < parentItem->rowCount() ? createIndex(row, column, parentItem->getItem(row)) : QModelIndex(); -		  	} else {  		return row < services_.size() ? createIndex(row, column, services_[row]) : QModelIndex();  	} @@ -55,10 +55,17 @@ QModelIndex MUCSearchModel::parent(const QModelIndex& index) const {  	if (!item) {  		return QModelIndex();  	} -	if (dynamic_cast<MUCSearchServiceItem*>(item)) { +	else if (dynamic_cast<MUCSearchServiceItem*>(item)) {  		return QModelIndex();  	} -	MUCSearchServiceItem* parent = dynamic_cast<MUCSearchRoomItem*>(item)->getParent(); + +	MUCSearchServiceItem* parent = NULL; +	if (MUCSearchRoomItem* roomItem = dynamic_cast<MUCSearchRoomItem*>(item)) { +		parent = roomItem->getParent(); +	} +	else if (MUCSearchEmptyItem* emptyItem = dynamic_cast<MUCSearchEmptyItem*>(item)) { +		parent = emptyItem->getParent(); +	}  	if (parent) {  		int row = services_.indexOf(parent);  		return createIndex(row, 1, parent); @@ -74,7 +81,8 @@ int MUCSearchModel::rowCount(const QModelIndex& parentIndex) const {  	}   	if (dynamic_cast<MUCSearchServiceItem*>(static_cast<MUCSearchItem*>(parentIndex.internalPointer()))) {  		return services_[parentIndex.row()]->rowCount(); -	} else { +	} +	else {  		return 0;  	}  } diff --git a/Swift/QtUI/MUCSearch/MUCSearchServiceItem.h b/Swift/QtUI/MUCSearch/MUCSearchServiceItem.h index 860792f..411727d 100644 --- a/Swift/QtUI/MUCSearch/MUCSearchServiceItem.h +++ b/Swift/QtUI/MUCSearch/MUCSearchServiceItem.h @@ -15,9 +15,9 @@ namespace Swift {  	class MUCSearchServiceItem : public MUCSearchItem {  		public:  			MUCSearchServiceItem(const QString& jidString) : jidString_(jidString) {} -			void addRoom(MUCSearchRoomItem* room) {rooms_.push_back(room);} +			void addRoom(MUCSearchItem* room) {rooms_.push_back(room);}  			int rowCount() {return rooms_.count();} -			MUCSearchRoomItem* getItem(int i) {return rooms_[i];} +			MUCSearchItem* getItem(int i) {return rooms_[i];}  			QVariant data(int role) {  				switch (role) {  					case Qt::DisplayRole: return QVariant(jidString_);  @@ -26,7 +26,7 @@ namespace Swift {  			}  			QString getHost() {return jidString_;}  		private: -			QList<MUCSearchRoomItem*> rooms_; +			QList<MUCSearchItem*> rooms_;  			QString jidString_;  	};  } diff --git a/Swift/QtUI/MUCSearch/QtMUCSearchWindow.cpp b/Swift/QtUI/MUCSearch/QtMUCSearchWindow.cpp index 7d2caba..3bdc433 100644 --- a/Swift/QtUI/MUCSearch/QtMUCSearchWindow.cpp +++ b/Swift/QtUI/MUCSearch/QtMUCSearchWindow.cpp @@ -10,43 +10,42 @@  #include <QMovie>  #include <QScrollBar>  #include <QTimer> +#include <QPushButton> -#include "Swift/Controllers/UIEvents/UIEventStream.h"  #include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h"  #include "Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h"  #include "Swift/QtUI/MUCSearch/MUCSearchModel.h"  #include "Swift/QtUI/MUCSearch/MUCSearchDelegate.h" +#include "Swift/QtUI/MUCSearch/MUCSearchEmptyItem.h"  #include "Swift/QtUI/QtSwiftUtil.h"  namespace Swift { -QtMUCSearchWindow::QtMUCSearchWindow(UIEventStream* eventStream) { +QtMUCSearchWindow::QtMUCSearchWindow() { +	ui_.setupUi(this);  #ifndef Q_WS_MAC  	setWindowIcon(QIcon(":/logo-icon-16.png"));  #endif -	eventStream_ = eventStream; -	setupUi(this); -	showEmptyRooms_->hide(); -	filterLabel_->hide(); -	filter_->hide(); +	setModal(true); +	ui_.filter_->hide();  	model_ = new MUCSearchModel();  	delegate_ = new MUCSearchDelegate(); -	results_->setModel(model_); -	results_->setItemDelegate(delegate_); -	results_->setHeaderHidden(true); -#ifdef SWIFT_PLATFORM_MACOSX -	results_->setAlternatingRowColors(true); -#endif -	connect(service_, SIGNAL(activated(const QString&)), this, SLOT(handleSearch(const QString&))); -	connect(room_, SIGNAL(returnPressed()), this, SLOT(handleJoin())); -	connect(nickName_, SIGNAL(returnPressed()), room_, SLOT(setFocus())); -	connect(searchButton_, SIGNAL(clicked()), this, SLOT(handleSearch())); -	connect(joinButton_, SIGNAL(clicked()), this, SLOT(handleJoin())); -	connect(results_, SIGNAL(clicked(const QModelIndex&)), this, SLOT(handleSelected(const QModelIndex&))); -	connect(results_, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleActivated(const QModelIndex&))); -	throbber_ = new QLabel("Searching", results_); +	ui_.results_->setModel(model_); +	ui_.results_->setItemDelegate(delegate_); +	ui_.results_->setHeaderHidden(true); +	ui_.results_->setRootIsDecorated(true); +	ui_.results_->setAnimated(true); +	ui_.results_->setAlternatingRowColors(true); +	connect(ui_.service_, SIGNAL(activated(const QString&)), this, SLOT(handleSearch(const QString&))); +	connect(ui_.results_, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleActivated(const QModelIndex&))); +	// Not using a button box, because i can't seem to be able to make the ok button non-default (on mac) +	connect(ui_.okButton, SIGNAL(clicked()), this, SLOT(accept())); +	connect(ui_.cancelButton, SIGNAL(clicked()), this, SLOT(reject())); + +	throbber_ = new QLabel("Searching", ui_.results_);  	throbber_->setMovie(new QMovie(":/icons/throbber.gif", QByteArray(), throbber_));  	throbber_->setToolTip("Searching"); +  	hasHadScrollBars_ = false;  	updateThrobberPosition();  	setSearchInProgress(false); @@ -62,8 +61,8 @@ void QtMUCSearchWindow::resizeEvent(QResizeEvent* /*event*/) {  void QtMUCSearchWindow::updateThrobberPosition() {  	bool isShown = throbber_->isVisible(); -	int resultWidth = results_->width(); -	int resultHeight = results_->height(); +	int resultWidth = ui_.results_->width(); +	int resultHeight = ui_.results_->height();  	//throbberWidth = throbber_->movie()->scaledSize().width();  	//throbberHeight = throbber_->movie()->scaledSize().height();  	int throbberWidth = 16; /* This is nasty, but the above doesn't work! */ @@ -72,99 +71,43 @@ void QtMUCSearchWindow::updateThrobberPosition() {  	 * because if you listen for the expanded/collapsed signals, you seem to get them before the scrollbars are updated.  	 * This seems an acceptable workaround.  	 */ -	hasHadScrollBars_ |= results_->verticalScrollBar()->isVisible(); -	int hMargin = hasHadScrollBars_ ? results_->verticalScrollBar()->width() + 2 : 2; +	hasHadScrollBars_ |= ui_.results_->verticalScrollBar()->isVisible(); +	int hMargin = hasHadScrollBars_ ? ui_.results_->verticalScrollBar()->width() + 2 : 2;  	int vMargin = 2; /* We don't get horizontal scrollbars */  	throbber_->setGeometry(QRect(resultWidth - throbberWidth - hMargin, resultHeight - throbberHeight - vMargin, throbberWidth, throbberHeight)); /* include margins */  	throbber_->setVisible(isShown);  } -void QtMUCSearchWindow::addSavedServices(const std::vector<JID>& services) { -	service_->clear(); -	foreach (JID jid, services) { -		service_->addItem(P2QSTRING(jid.toString())); +void QtMUCSearchWindow::addSavedServices(const std::list<JID>& services) { +	ui_.service_->clear(); +	foreach (const JID& jid, services) { +		ui_.service_->addItem(P2QSTRING(jid.toString()));  	} -	service_->clearEditText(); -} - -void QtMUCSearchWindow::handleActivated(const QModelIndex& index) { -	if (!index.isValid()) { -		return; +	if (!services.empty()) { +		ui_.service_->setEditText(P2QSTRING(services.begin()->toString()));  	} -	MUCSearchRoomItem* roomItem = dynamic_cast<MUCSearchRoomItem*>(static_cast<MUCSearchItem*>(index.internalPointer())); -	if (roomItem) { -		handleSelected(index); -		handleJoin(); +	else { +		ui_.service_->clearEditText();  	}  } -void QtMUCSearchWindow::handleSelected(const QModelIndex& current) { -	if (!current.isValid()) { +void QtMUCSearchWindow::handleActivated(const QModelIndex& index) { +	if (!index.isValid()) {  		return; -	}	 -	MUCSearchRoomItem* roomItem = dynamic_cast<MUCSearchRoomItem*>(static_cast<MUCSearchItem*>(current.internalPointer())); -	if (roomItem) { -		room_->setText(roomItem->getNode() + "@" + roomItem->getParent()->getHost());  	} - -} - -void QtMUCSearchWindow::handleSearch(const QString& text) { -	if (text.isEmpty()) { -		return; +	if (dynamic_cast<MUCSearchRoomItem*>(static_cast<MUCSearchItem*>(index.internalPointer()))) { +		accept();  	} -	onAddService(JID(Q2PSTRING(text)));  }  void QtMUCSearchWindow::handleSearch() { -	handleSearch(service_->currentText()); -} - - -void QtMUCSearchWindow::handleJoin() { -	if (room_->text().isEmpty()) { -		handleSelected(results_->currentIndex()); -	} -	if (room_->text().isEmpty()) { -		return; -	} -	boost::optional<String> maybeNick; -	if (!nickName_->text().isEmpty()) { -		lastSetNick_ = Q2PSTRING(nickName_->text()); -		maybeNick = lastSetNick_; -	} - -	JID room(Q2PSTRING(room_->text())); -	if (joinAutomatically_->isChecked()) { -		createAutoJoin(room, maybeNick); -	} -	eventStream_->send(boost::shared_ptr<UIEvent>(new JoinMUCUIEvent(room, maybeNick))); -	hide(); +	handleSearch(ui_.service_->currentText());  } -void QtMUCSearchWindow::createAutoJoin(const JID& room, boost::optional<String> passedNick) { -	String nick = lastSetNick_; -	if (passedNick) { -		nick = passedNick.get(); +void QtMUCSearchWindow::handleSearch(const QString& service) { +	if (!service.isEmpty()) { +		onSearchService(JID(Q2PSTRING(service)));  	} -	MUCBookmark bookmark(room, room.getNode()); -	bookmark.setAutojoin(true); -	if (!nick.isEmpty()) { -		bookmark.setNick(nick); -	} -	//if (!password.isEmpty()) { -	//	bookmark.setPassword(password); -	//} -	eventStream_->send(boost::shared_ptr<UIEvent>(new AddMUCBookmarkUIEvent(bookmark))); -}  - -void QtMUCSearchWindow::setNick(const String& nick) { -	nickName_->setText(P2QSTRING(nick)); -	lastSetNick_ = nick; -} - -void QtMUCSearchWindow::setMUC(const String& nick) { -	room_->setText(P2QSTRING(nick));  }  void QtMUCSearchWindow::show() { @@ -179,11 +122,16 @@ void QtMUCSearchWindow::clearList() {  void QtMUCSearchWindow::addService(const MUCService& service) {  	updateThrobberPosition();  	MUCSearchServiceItem* serviceItem = new MUCSearchServiceItem(P2QSTRING(service.getJID().toString())); -	foreach (MUCService::MUCRoom room, service.getRooms()) { -		new MUCSearchRoomItem(P2QSTRING(room.getNode()), serviceItem); +	if (service.getRooms().size() > 0) { +		foreach (MUCService::MUCRoom room, service.getRooms()) { +			new MUCSearchRoomItem(P2QSTRING(room.getNode()), serviceItem); +		} +	} +	else { +		new MUCSearchEmptyItem(serviceItem);  	}  	model_->addService(serviceItem); -	results_->expandAll(); +	ui_.results_->expandAll();  }  void QtMUCSearchWindow::setSearchInProgress(bool searching) { @@ -195,4 +143,24 @@ void QtMUCSearchWindow::setSearchInProgress(bool searching) {  	throbber_->setVisible(searching);  } +void QtMUCSearchWindow::accept() { +	QModelIndexList selection = ui_.results_->selectionModel()->selectedIndexes(); +	if (selection.isEmpty()) { +		onFinished(boost::optional<JID>()); +	} +	else { +		QModelIndex selectedItem = selection[0]; +		MUCSearchRoomItem* item = dynamic_cast<MUCSearchRoomItem*>(static_cast<MUCSearchItem*>(selectedItem.internalPointer())); +		if (item) { +			onFinished(JID(Q2PSTRING(item->getNode()), Q2PSTRING(item->getParent()->getHost()))); +		} +	} +	QDialog::accept(); +} + +void QtMUCSearchWindow::reject() { +	onFinished(boost::optional<JID>()); +	QDialog::reject(); +} +  } diff --git a/Swift/QtUI/MUCSearch/QtMUCSearchWindow.h b/Swift/QtUI/MUCSearch/QtMUCSearchWindow.h index b8cf953..cb4585d 100644 --- a/Swift/QtUI/MUCSearch/QtMUCSearchWindow.h +++ b/Swift/QtUI/MUCSearch/QtMUCSearchWindow.h @@ -13,37 +13,36 @@  namespace Swift {  	class MUCSearchModel;  	class MUCSearchDelegate; -	class UIEventStream; -	class QtMUCSearchWindow : public QWidget, public MUCSearchWindow, private Ui::QtMUCSearchWindow { + +	class QtMUCSearchWindow : public QDialog, public MUCSearchWindow {  		Q_OBJECT  		public: -			QtMUCSearchWindow(UIEventStream* eventStream); +			QtMUCSearchWindow();  			virtual ~QtMUCSearchWindow(); -			virtual void setNick(const String& nick); -			virtual void setMUC(const String& nick);  			virtual void clearList();  			virtual void addService(const MUCService& service); -			virtual void addSavedServices(const std::vector<JID>& services); +			virtual void addSavedServices(const std::list<JID>& services);  			virtual void setSearchInProgress(bool searching);  			virtual void show(); +			virtual void accept(); +			virtual void reject(); +  		protected:  			virtual void resizeEvent(QResizeEvent* event); +  		private slots: -			void handleSearch(const QString& text);  			void handleSearch(); -			void handleJoin(); -			void handleSelected(const QModelIndex& current); +			void handleSearch(const QString&);  			void handleActivated(const QModelIndex& index);  			void updateThrobberPosition(); +  		private: -			void createAutoJoin(const JID& room, boost::optional<String> passedNick); +			Ui::QtMUCSearchWindow ui_;  			MUCSearchModel* model_;  			MUCSearchDelegate* delegate_; -			UIEventStream* eventStream_;  			QLabel* throbber_; -			String lastSetNick_;  			bool hasHadScrollBars_;  	};  } diff --git a/Swift/QtUI/MUCSearch/QtMUCSearchWindow.ui b/Swift/QtUI/MUCSearch/QtMUCSearchWindow.ui index ef2524b..f1a1fd5 100644 --- a/Swift/QtUI/MUCSearch/QtMUCSearchWindow.ui +++ b/Swift/QtUI/MUCSearch/QtMUCSearchWindow.ui @@ -1,212 +1,92 @@  <?xml version="1.0" encoding="UTF-8"?>  <ui version="4.0">   <class>QtMUCSearchWindow</class> - <widget class="QWidget" name="QtMUCSearchWindow"> + <widget class="QDialog" name="QtMUCSearchWindow">    <property name="geometry">     <rect>      <x>0</x>      <y>0</y>      <width>523</width> -    <height>531</height> +    <height>368</height>     </rect>    </property> -  <property name="sizePolicy"> -   <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> -    <horstretch>0</horstretch> -    <verstretch>0</verstretch> -   </sizepolicy> -  </property>    <property name="windowTitle"> -   <string>Find Room</string> +   <string>Dialog</string>    </property> -  <layout class="QVBoxLayout" name="verticalLayout_4"> -   <item> -    <layout class="QVBoxLayout" name="verticalLayout_3"> -     <property name="sizeConstraint"> -      <enum>QLayout::SetDefaultConstraint</enum> +  <layout class="QGridLayout" name="gridLayout"> +   <item row="0" column="0"> +    <widget class="QLabel" name="label_2"> +     <property name="text"> +      <string>Service:</string> +     </property> +    </widget> +   </item> +   <item row="0" column="1"> +    <widget class="QComboBox" name="service_"> +     <property name="sizePolicy"> +      <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> +       <horstretch>2</horstretch> +       <verstretch>0</verstretch> +      </sizepolicy> +     </property> +     <property name="editable"> +      <bool>true</bool> +     </property> +    </widget> +   </item> +   <item row="0" column="2"> +    <widget class="QLineEdit" name="filter_"> +     <property name="sizePolicy"> +      <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> +       <horstretch>1</horstretch> +       <verstretch>0</verstretch> +      </sizepolicy>       </property> +     <property name="text"> +      <string/> +     </property> +     <property name="frame"> +      <bool>true</bool> +     </property> +    </widget> +   </item> +   <item row="1" column="0" colspan="3"> +    <widget class="QTreeView" name="results_"/> +   </item> +   <item row="2" column="0" colspan="3"> +    <layout class="QHBoxLayout" name="horizontalLayout"> +     <item> +      <spacer name="horizontalSpacer"> +       <property name="orientation"> +        <enum>Qt::Horizontal</enum> +       </property> +       <property name="sizeHint" stdset="0"> +        <size> +         <width>40</width> +         <height>20</height> +        </size> +       </property> +      </spacer> +     </item>       <item> -      <layout class="QHBoxLayout" name="horizontalLayout_2"> -       <item> -        <layout class="QVBoxLayout" name="verticalLayout"> -         <item> -          <widget class="QLabel" name="label"> -           <property name="text"> -            <string>Available Rooms</string> -           </property> -          </widget> -         </item> -         <item> -          <widget class="QTreeView" name="results_"/> -         </item> -        </layout> -       </item> -       <item> -        <layout class="QVBoxLayout" name="verticalLayout_2"> -         <item> -          <widget class="QLabel" name="label_5"> -           <property name="text"> -            <string>Your nickname:</string> -           </property> -          </widget> -         </item> -         <item> -          <widget class="QLineEdit" name="nickName_"/> -         </item> -         <item> -          <spacer name="verticalSpacer"> -           <property name="orientation"> -            <enum>Qt::Vertical</enum> -           </property> -           <property name="sizeHint" stdset="0"> -            <size> -             <width>20</width> -             <height>40</height> -            </size> -           </property> -          </spacer> -         </item> -         <item> -          <widget class="QLabel" name="label_2"> -           <property name="text"> -            <string>Search another service:</string> -           </property> -          </widget> -         </item> -         <item> -          <widget class="QComboBox" name="service_"> -           <property name="editable"> -            <bool>true</bool> -           </property> -          </widget> -         </item> -         <item> -          <layout class="QHBoxLayout" name="horizontalLayout"> -           <item> -            <spacer name="horizontalSpacer"> -             <property name="orientation"> -              <enum>Qt::Horizontal</enum> -             </property> -             <property name="sizeHint" stdset="0"> -              <size> -               <width>40</width> -               <height>20</height> -              </size> -             </property> -            </spacer> -           </item> -           <item> -            <widget class="QPushButton" name="searchButton_"> -             <property name="text"> -              <string>Search</string> -             </property> -            </widget> -           </item> -          </layout> -         </item> -         <item> -          <spacer name="verticalSpacer_2"> -           <property name="orientation"> -            <enum>Qt::Vertical</enum> -           </property> -           <property name="sizeHint" stdset="0"> -            <size> -             <width>20</width> -             <height>40</height> -            </size> -           </property> -          </spacer> -         </item> -         <item> -          <widget class="QLabel" name="filterLabel_"> -           <property name="text"> -            <string>Only show rooms matching:</string> -           </property> -          </widget> -         </item> -         <item> -          <widget class="QLineEdit" name="filter_"/> -         </item> -         <item> -          <widget class="QCheckBox" name="showEmptyRooms_"> -           <property name="enabled"> -            <bool>true</bool> -           </property> -           <property name="text"> -            <string>Show Empty Rooms</string> -           </property> -          </widget> -         </item> -         <item> -          <spacer name="verticalSpacer_3"> -           <property name="orientation"> -            <enum>Qt::Vertical</enum> -           </property> -           <property name="sizeHint" stdset="0"> -            <size> -             <width>20</width> -             <height>18</height> -            </size> -           </property> -          </spacer> -         </item> -         <item> -          <widget class="QLabel" name="label_4"> -           <property name="text"> -            <string>Join Room Directly:</string> -           </property> -          </widget> -         </item> -         <item> -          <widget class="QLineEdit" name="room_"/> -         </item> -         <item> -          <widget class="QCheckBox" name="joinAutomatically_"> -           <property name="text"> -            <string>Join automatically in future</string> -           </property> -          </widget> -         </item> -        </layout> -       </item> -      </layout> +      <widget class="QPushButton" name="cancelButton"> +       <property name="text"> +        <string>Cancel</string> +       </property> +       <property name="autoDefault"> +        <bool>false</bool> +       </property> +      </widget>       </item>       <item> -      <layout class="QHBoxLayout" name="horizontalLayout_3"> -       <item> -        <spacer name="horizontalSpacer_2"> -         <property name="orientation"> -          <enum>Qt::Horizontal</enum> -         </property> -         <property name="sizeHint" stdset="0"> -          <size> -           <width>40</width> -           <height>20</height> -          </size> -         </property> -        </spacer> -       </item> -       <item> -        <widget class="QPushButton" name="joinButton_"> -         <property name="text"> -          <string>Join Room</string> -         </property> -        </widget> -       </item> -       <item> -        <spacer name="horizontalSpacer_3"> -         <property name="orientation"> -          <enum>Qt::Horizontal</enum> -         </property> -         <property name="sizeHint" stdset="0"> -          <size> -           <width>40</width> -           <height>20</height> -          </size> -         </property> -        </spacer> -       </item> -      </layout> +      <widget class="QPushButton" name="okButton"> +       <property name="text"> +        <string>Ok</string> +       </property> +       <property name="autoDefault"> +        <bool>false</bool> +       </property> +      </widget>       </item>      </layout>     </item> diff --git a/Swift/QtUI/QtJoinMUCWindow.cpp b/Swift/QtUI/QtJoinMUCWindow.cpp new file mode 100644 index 0000000..55b285b --- /dev/null +++ b/Swift/QtUI/QtJoinMUCWindow.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "QtJoinMUCWindow.h" +#include "QtSwiftUtil.h" + +namespace Swift { + +QtJoinMUCWindow::QtJoinMUCWindow() { +	ui.setupUi(this); +	connect(ui.room, SIGNAL(returnPressed()), this, SLOT(handleJoin())); +	connect(ui.searchButton, SIGNAL(clicked()), this, SLOT(handleSearch())); +	connect(ui.joinButton, SIGNAL(clicked()), this, SLOT(handleJoin())); +} + +void QtJoinMUCWindow::handleJoin() { +	if (ui.room->text().isEmpty()) { +		// TODO: Error +		return; +	} +	if (ui.nickName->text().isEmpty()) { +		// TODO: Error +		return; +	} + +	lastSetNick = Q2PSTRING(ui.nickName->text()); +	JID room(Q2PSTRING(ui.room->text())); +	onJoinMUC(room, lastSetNick, ui.joinAutomatically->isChecked());  +	hide(); +} + +void QtJoinMUCWindow::handleSearch() { +	onSearchMUC(); +} + +void QtJoinMUCWindow::setNick(const String& nick) { +	ui.nickName->setText(P2QSTRING(nick)); +	lastSetNick = nick; +} + +void QtJoinMUCWindow::setMUC(const String& nick) { +	ui.room->setText(P2QSTRING(nick)); +} + +void QtJoinMUCWindow::show() { +	QWidget::show(); +	QWidget::activateWindow(); +} + +} diff --git a/Swift/QtUI/QtJoinMUCWindow.h b/Swift/QtUI/QtJoinMUCWindow.h new file mode 100644 index 0000000..2d12319 --- /dev/null +++ b/Swift/QtUI/QtJoinMUCWindow.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/String.h> +#include <Swift/Controllers/UIInterfaces/JoinMUCWindow.h> +#include <Swift/QtUI/ui_QtJoinMUCWindow.h> + +namespace Swift { +	class QtJoinMUCWindow : public QWidget, public JoinMUCWindow { +			Q_OBJECT +		public: +			QtJoinMUCWindow(); + +			virtual void setNick(const String& nick); +			virtual void setMUC(const String& nick); + +			virtual void show(); + +		private slots: +			void handleJoin(); +			void handleSearch(); + +		private: +			Ui::QtJoinMUCWindow ui; +			String lastSetNick; +	}; +} diff --git a/Swift/QtUI/QtJoinMUCWindow.ui b/Swift/QtUI/QtJoinMUCWindow.ui new file mode 100644 index 0000000..2f3608a --- /dev/null +++ b/Swift/QtUI/QtJoinMUCWindow.ui @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtJoinMUCWindow</class> + <widget class="QWidget" name="QtJoinMUCWindow"> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>398</width> +    <height>172</height> +   </rect> +  </property> +  <property name="sizePolicy"> +   <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> +    <horstretch>0</horstretch> +    <verstretch>0</verstretch> +   </sizepolicy> +  </property> +  <property name="windowTitle"> +   <string>Join Room</string> +  </property> +  <layout class="QVBoxLayout" name="verticalLayout"> +   <item> +    <layout class="QGridLayout" name="gridLayout"> +     <item row="0" column="0"> +      <widget class="QLabel" name="label_4"> +       <property name="text"> +        <string>Room:</string> +       </property> +      </widget> +     </item> +     <item row="0" column="2"> +      <widget class="QToolButton" name="searchButton"> +       <property name="text"> +        <string>Search ...</string> +       </property> +      </widget> +     </item> +     <item row="1" column="0"> +      <widget class="QLabel" name="label_5"> +       <property name="text"> +        <string>Nickname:</string> +       </property> +      </widget> +     </item> +     <item row="1" column="1" colspan="2"> +      <widget class="QLineEdit" name="nickName"/> +     </item> +     <item row="0" column="1"> +      <widget class="QLineEdit" name="room"> +       <property name="text"> +        <string/> +       </property> +       <property name="placeholderText"> +        <string>swift@rooms.swift.im</string> +       </property> +      </widget> +     </item> +    </layout> +   </item> +   <item> +    <spacer name="verticalSpacer"> +     <property name="orientation"> +      <enum>Qt::Vertical</enum> +     </property> +     <property name="sizeHint" stdset="0"> +      <size> +       <width>20</width> +       <height>36</height> +      </size> +     </property> +    </spacer> +   </item> +   <item> +    <layout class="QHBoxLayout" name="horizontalLayout"> +     <item> +      <spacer name="horizontalSpacer"> +       <property name="orientation"> +        <enum>Qt::Horizontal</enum> +       </property> +       <property name="sizeHint" stdset="0"> +        <size> +         <width>40</width> +         <height>20</height> +        </size> +       </property> +      </spacer> +     </item> +     <item> +      <widget class="QCheckBox" name="joinAutomatically"> +       <property name="text"> +        <string>Join automatically in future</string> +       </property> +      </widget> +     </item> +     <item> +      <widget class="QPushButton" name="joinButton"> +       <property name="text"> +        <string>Join Room</string> +       </property> +      </widget> +     </item> +    </layout> +   </item> +  </layout> + </widget> + <tabstops> +  <tabstop>room</tabstop> +  <tabstop>nickName</tabstop> +  <tabstop>joinAutomatically</tabstop> +  <tabstop>joinButton</tabstop> +  <tabstop>searchButton</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp index 21d1474..0411c0b 100644 --- a/Swift/QtUI/QtMainWindow.cpp +++ b/Swift/QtUI/QtMainWindow.cpp @@ -8,6 +8,7 @@  #include <boost/optional.hpp>  #include <boost/bind.hpp> +#include <boost/smart_ptr/make_shared.hpp>  #include <QBoxLayout>  #include <QComboBox> @@ -24,9 +25,9 @@  #include "QtSwiftUtil.h"  #include "QtTabWidget.h"  #include "Roster/QtTreeWidget.h" +#include "Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h"  #include "Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h"  #include "Swift/Controllers/UIEvents/RequestChatWithUserDialogUIEvent.h" -#include "Swift/Controllers/UIEvents/RequestMUCSearchUIEvent.h"  #include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h"  #include "Swift/Controllers/UIEvents/ToggleShowOfflineUIEvent.h" @@ -143,7 +144,7 @@ void QtMainWindow::handleSignOutAction() {  }  void QtMainWindow::handleJoinMUCAction() { -	uiEventStream_->send(boost::shared_ptr<UIEvent>(new RequestMUCSearchUIEvent())); +	uiEventStream_->send(boost::make_shared<RequestJoinMUCUIEvent>());  }  void QtMainWindow::handleStatusChanged(StatusShow::Type showType, const QString &statusMessage) { diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp index 25a508e..8cb9863 100644 --- a/Swift/QtUI/QtUIFactory.cpp +++ b/Swift/QtUI/QtUIFactory.cpp @@ -16,6 +16,7 @@  #include "QtSettingsProvider.h"  #include "QtMainWindow.h"  #include "QtChatWindow.h" +#include "QtJoinMUCWindow.h"  #include "QtChatWindowFactory.h"  #include "QtSwiftUtil.h"  #include "MUCSearch/QtMUCSearchWindow.h" @@ -70,8 +71,8 @@ ChatListWindow* QtUIFactory::createChatListWindow(UIEventStream*) {  	return lastMainWindow->getChatListWindow();  } -MUCSearchWindow* QtUIFactory::createMUCSearchWindow(UIEventStream* eventStream) { -		return new QtMUCSearchWindow(eventStream); +MUCSearchWindow* QtUIFactory::createMUCSearchWindow() { +		return new QtMUCSearchWindow();  }  ChatWindow* QtUIFactory::createChatWindow(const JID& contact, UIEventStream* eventStream) { @@ -82,4 +83,8 @@ UserSearchWindow* QtUIFactory::createUserSearchWindow(UserSearchWindow::Type typ  	return new QtUserSearchWindow(eventStream, type);  }; +JoinMUCWindow* QtUIFactory::createJoinMUCWindow() { +	return new QtJoinMUCWindow(); +} +  } diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h index 6ddc316..4d80338 100644 --- a/Swift/QtUI/QtUIFactory.h +++ b/Swift/QtUI/QtUIFactory.h @@ -31,9 +31,10 @@ namespace Swift {  			virtual LoginWindow* createLoginWindow(UIEventStream* eventStream);  			virtual EventWindow* createEventWindow();  			virtual ChatListWindow* createChatListWindow(UIEventStream*); -			virtual MUCSearchWindow* createMUCSearchWindow(UIEventStream* eventStream); +			virtual MUCSearchWindow* createMUCSearchWindow();  			virtual ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream);  			virtual UserSearchWindow* createUserSearchWindow(UserSearchWindow::Type type, UIEventStream* eventStream); +			virtual JoinMUCWindow* createJoinMUCWindow();  		private slots:  			void handleLoginWindowGeometryChanged(); diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index c0730dc..b0072a6 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -92,6 +92,7 @@ sources = [      "SystemMessageSnippet.cpp",      "QtElidingLabel.cpp",      "QtLineEdit.cpp", +    "QtJoinMUCWindow.cpp",      "Roster/RosterModel.cpp",      "Roster/QtTreeWidget.cpp",  #    "Roster/QtTreeWidgetItem.cpp", @@ -110,6 +111,7 @@ sources = [      "MUCSearch/QtMUCSearchWindow.cpp",      "MUCSearch/MUCSearchModel.cpp",      "MUCSearch/MUCSearchRoomItem.cpp", +    "MUCSearch/MUCSearchEmptyItem.cpp",      "MUCSearch/MUCSearchDelegate.cpp",      "UserSearch/QtUserSearchWindow.cpp",      "UserSearch/UserSearchModel.cpp", @@ -147,6 +149,7 @@ myenv.Uic4("UserSearch/QtUserSearchFieldsPage.ui")  myenv.Uic4("UserSearch/QtUserSearchResultsPage.ui")  myenv.Uic4("QtAddContactDialog.ui")  myenv.Uic4("QtBookmarkDetailWindow.ui") +myenv.Uic4("QtJoinMUCWindow.ui")  myenv.Qrc("DefaultTheme.qrc")  myenv.Qrc("Swift.qrc")  | 
 Swift