diff options
author | Remko Tronçon <git@el-tramo.be> | 2011-01-16 19:56:10 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2011-01-20 21:40:49 (GMT) |
commit | 004dfd8d4305b767b624be10072597ef3e311753 (patch) | |
tree | 7f9a70ce336e9eca3bc78397640530939e55fa20 /Swift/Controllers | |
parent | 03d69bfd11549e1c8dcbf3b5300029ba9892cf8a (diff) | |
download | swift-004dfd8d4305b767b624be10072597ef3e311753.zip swift-004dfd8d4305b767b624be10072597ef3e311753.tar.bz2 |
Use a dedicated Join MUC dialog.
Diffstat (limited to 'Swift/Controllers')
-rw-r--r-- | Swift/Controllers/Chat/ChatsManager.cpp | 79 | ||||
-rw-r--r-- | Swift/Controllers/Chat/ChatsManager.h | 14 | ||||
-rw-r--r-- | Swift/Controllers/Chat/MUCSearchController.cpp | 105 | ||||
-rw-r--r-- | Swift/Controllers/Chat/MUCSearchController.h | 34 | ||||
-rw-r--r-- | Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp | 12 | ||||
-rw-r--r-- | Swift/Controllers/DiscoServiceWalker.cpp | 4 | ||||
-rw-r--r-- | Swift/Controllers/DiscoServiceWalker.h | 4 | ||||
-rw-r--r-- | Swift/Controllers/MainController.cpp | 6 | ||||
-rw-r--r-- | Swift/Controllers/MainController.h | 1 | ||||
-rw-r--r-- | Swift/Controllers/UIEvents/JoinMUCUIEvent.h | 2 | ||||
-rw-r--r-- | Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h | 23 | ||||
-rw-r--r-- | Swift/Controllers/UIEvents/RequestMUCSearchUIEvent.h | 15 | ||||
-rw-r--r-- | Swift/Controllers/UIInterfaces/JoinMUCWindow.h | 27 | ||||
-rw-r--r-- | Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h | 18 | ||||
-rw-r--r-- | Swift/Controllers/UIInterfaces/MUCSearchWindow.h | 11 | ||||
-rw-r--r-- | Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h | 2 | ||||
-rw-r--r-- | Swift/Controllers/UIInterfaces/UIFactory.h | 12 |
17 files changed, 262 insertions, 107 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() {} }; |