summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2010-05-08 12:14:01 (GMT)
committerKevin Smith <git@kismith.co.uk>2010-05-13 12:29:20 (GMT)
commit705bd7256fa4812045677743fc1e939ccfd66d05 (patch)
tree84502c2c6bd6bda1bc38e7fce59cc451e05b21c4 /Swift/Controllers
parent61078c4e4fd553bf952bae5c9d44da6cb96a3a70 (diff)
downloadswift-705bd7256fa4812045677743fc1e939ccfd66d05.zip
swift-705bd7256fa4812045677743fc1e939ccfd66d05.tar.bz2
List MUCs available on services.
Resolves: #276
Diffstat (limited to 'Swift/Controllers')
-rw-r--r--Swift/Controllers/Chat/MUCSearchController.cpp156
-rw-r--r--Swift/Controllers/Chat/MUCSearchController.h108
-rw-r--r--Swift/Controllers/MainController.cpp16
-rw-r--r--Swift/Controllers/MainController.h6
-rw-r--r--Swift/Controllers/SConscript3
-rw-r--r--Swift/Controllers/UIEvents/RequestMUCSearchUIEvent.h15
-rw-r--r--Swift/Controllers/UIInterfaces/MUCSearchWindow.h31
-rw-r--r--Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h19
8 files changed, 347 insertions, 7 deletions
diff --git a/Swift/Controllers/Chat/MUCSearchController.cpp b/Swift/Controllers/Chat/MUCSearchController.cpp
new file mode 100644
index 0000000..93d2087
--- /dev/null
+++ b/Swift/Controllers/Chat/MUCSearchController.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swift/Controllers/Chat/MUCSearchController.h"
+
+#include <iostream>
+
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Queries/Requests/GetDiscoInfoRequest.h"
+#include "Swiften/Queries/Requests/GetDiscoItemsRequest.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"
+
+namespace Swift {
+
+MUCSearchController::MUCSearchController(const JID& jid, UIEventStream* uiEventStream, MUCSearchWindowFactory* factory, IQRouter* iqRouter) : jid_(jid) {
+ iqRouter_ = iqRouter;
+ uiEventStream_ = uiEventStream;
+ uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&MUCSearchController::handleUIEvent, this, _1));
+ window_ = NULL;
+ factory_ = factory;
+}
+
+MUCSearchController::~MUCSearchController() {
+ 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, true));
+ handleAddService(JID(jid_.getDomain()), true);
+ }
+ window_->setMUC("");
+ window_->setNick(jid_.getNode());
+ window_->show();
+ return;
+ }
+}
+
+void MUCSearchController::handleAddService(const JID& jid, bool userTriggered) {
+ if (std::find(services_.begin(), services_.end(), jid) != services_.end()) {
+ if (!userTriggered) {
+ /* No infinite recursion. (Some buggy servers do infinitely deep disco of themselves)*/
+ return;
+ }
+ } else if (userTriggered) {
+ services_.push_back(jid);
+ serviceDetails_[jid].setComplete(false);
+ refreshView();
+ }
+ if (!jid.isValid()) {
+ //Set Window to say error this isn't valid
+ return;
+ }
+ boost::shared_ptr<GetDiscoInfoRequest> discoInfoRequest(new GetDiscoInfoRequest(jid, iqRouter_));
+ discoInfoRequest->onResponse.connect(boost::bind(&MUCSearchController::handleDiscoInfoResponse, this, _1, _2, jid));
+ discoInfoRequest->send();
+}
+
+void MUCSearchController::removeService(const JID& jid) {
+ serviceDetails_.erase(jid);
+ services_.erase(std::remove(services_.begin(), services_.end(), jid), services_.end());
+ refreshView();
+}
+
+void MUCSearchController::handleDiscoInfoResponse(boost::shared_ptr<DiscoInfo> info, const boost::optional<ErrorPayload>& error, const JID& jid) {
+ if (error) {
+ handleDiscoError(jid, error.get());
+ return;
+ }
+ boost::shared_ptr<GetDiscoItemsRequest> discoItemsRequest(new GetDiscoItemsRequest(jid, iqRouter_));
+ bool mucService = false;
+ bool couldContainServices = false;
+ String name;
+ foreach (DiscoInfo::Identity identity, info->getIdentities()) {
+ if ((identity.getCategory() == "directory"
+ && identity.getType() == "chatroom")
+ || (identity.getCategory() == "conference"
+ && identity.getType() == "text")) {
+ mucService = true;
+ name = identity.getName();
+ }
+ if (identity.getCategory() == "server") {
+ couldContainServices = true;
+ name = identity.getName();
+ }
+ }
+ services_.erase(std::remove(services_.begin(), services_.end(), jid), services_.end()); /* Bring it back to the end on a refresh */
+ services_.push_back(jid);
+ serviceDetails_[jid].setName(name);
+ serviceDetails_[jid].setJID(jid);
+ serviceDetails_[jid].setComplete(false);
+
+ if (mucService) {
+ discoItemsRequest->onResponse.connect(boost::bind(&MUCSearchController::handleRoomsItemsResponse, this, _1, _2, jid));
+ } else if (couldContainServices) {
+ discoItemsRequest->onResponse.connect(boost::bind(&MUCSearchController::handleServerItemsResponse, this, _1, _2, jid));
+ } else {
+ removeService(jid);
+ return;
+ }
+ discoItemsRequest->send();
+ refreshView();
+}
+
+void MUCSearchController::handleRoomsItemsResponse(boost::shared_ptr<DiscoItems> items, const boost::optional<ErrorPayload>& error, const JID& jid) {
+ if (error) {
+ handleDiscoError(jid, error.get());
+ return;
+ }
+ serviceDetails_[jid].clearRooms();
+ foreach (DiscoItems::Item item, items->getItems()) {
+ serviceDetails_[jid].addRoom(MUCService::MUCRoom(item.getJID().getNode(), item.getName(), -1));
+ }
+ serviceDetails_[jid].setComplete(true);
+ refreshView();
+}
+
+void MUCSearchController::handleServerItemsResponse(boost::shared_ptr<DiscoItems> items, const boost::optional<ErrorPayload>& error, const JID& jid) {
+ if (error) {
+ handleDiscoError(jid, error.get());
+ return;
+ }
+ if (jid.isValid()) {
+ removeService(jid);
+ }
+ foreach (DiscoItems::Item item, items->getItems()) {
+ handleAddService(item.getJID());
+ }
+ refreshView();
+}
+
+void MUCSearchController::handleDiscoError(const JID& jid, const ErrorPayload& error) {
+ serviceDetails_[jid].setComplete(true);
+ serviceDetails_[jid].setError(error.getText());
+}
+
+void MUCSearchController::refreshView() {
+ window_->clearList();
+ foreach (JID jid, services_) {
+ window_->addService(serviceDetails_[jid]);
+ }
+}
+
+}
diff --git a/Swift/Controllers/Chat/MUCSearchController.h b/Swift/Controllers/Chat/MUCSearchController.h
new file mode 100644
index 0000000..6eba2a5
--- /dev/null
+++ b/Swift/Controllers/Chat/MUCSearchController.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <vector>
+#include <map>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/signals.hpp>
+
+#include "Swiften/Base/String.h"
+#include "Swiften/JID/JID.h"
+
+#include "Swift/Controllers/UIEvents/UIEvent.h"
+#include "Swift/Controllers/Chat/MUCSearchController.h"
+#include "Swiften/Elements/DiscoInfo.h"
+#include "Swiften/Elements/DiscoItems.h"
+#include "Swiften/Elements/ErrorPayload.h"
+
+namespace Swift {
+ class UIEventStream;
+ class MUCSearchWindow;
+ class MUCSearchWindowFactory;
+ class IQRouter;
+
+ class MUCService {
+ public:
+ class MUCRoom {
+ public:
+ MUCRoom(const String& node, const String& name, int occupants) : node_(node), name_(name), occupants_(occupants) {}
+ String getNode() {return node_;}
+ String getName() {return name_;}
+ int getOccupantCount() {return occupants_;}
+ private:
+ String node_;
+ String name_;
+ int occupants_;
+ };
+
+ MUCService() {error_ = false; complete_ = false;}
+
+ void setComplete(bool complete) {
+ complete_ = complete;
+ }
+
+ void setName(const String& name) {
+ name_ = name;
+ }
+
+ void setJID(const JID& jid) {
+ jid_ = jid;
+ }
+
+ bool getComplete() const {
+ return complete_;
+ }
+
+ JID getJID() const {
+ return jid_;
+ }
+
+ String getName() const {
+ return name_;
+ }
+
+ void setError(const String& errorText) {error_ = true; errorText_ = errorText;}
+
+ void clearRooms() {rooms_.clear();}
+
+ void addRoom(const MUCRoom& room) {rooms_.push_back(room);}
+
+ std::vector<MUCRoom> getRooms() const {return rooms_;}
+ private:
+ String name_;
+ JID jid_;
+ std::vector<MUCRoom> rooms_;
+ bool complete_;
+ bool error_;
+ String errorText_;
+ };
+
+ class MUCSearchController {
+ public:
+ MUCSearchController(const JID& jid, UIEventStream* uiEventStream, MUCSearchWindowFactory* mucSearchWindowFactory, IQRouter* iqRouter);
+ ~MUCSearchController();
+ private:
+ void handleUIEvent(boost::shared_ptr<UIEvent> event);
+ void handleAddService(const JID& jid, bool userTriggered=false);
+ void handleDiscoInfoResponse(boost::shared_ptr<DiscoInfo> info, const boost::optional<ErrorPayload>& error, const JID& jid);
+ void handleRoomsItemsResponse(boost::shared_ptr<DiscoItems> items, const boost::optional<ErrorPayload>& error, const JID& jid);
+ void handleServerItemsResponse(boost::shared_ptr<DiscoItems> items, const boost::optional<ErrorPayload>& error, const JID& jid);
+ void handleDiscoError(const JID& jid, const ErrorPayload& error);
+ void removeService(const JID& jid);
+ void refreshView();
+ UIEventStream* uiEventStream_;
+ MUCSearchWindow* window_;
+ MUCSearchWindowFactory* factory_;
+ boost::bsignals::scoped_connection uiEventConnection_;
+ std::vector<JID> services_;
+ std::map<JID, MUCService> serviceDetails_;
+ IQRouter* iqRouter_;
+ JID jid_;
+ };
+}
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index e6dfe47..5be8e46 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -14,15 +14,16 @@
#include "Swiften/Application/Application.h"
#include "Swiften/Application/ApplicationMessageDisplay.h"
#include "Swift/Controllers/Chat/ChatController.h"
-#include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
+#include "Swift/Controllers/Chat/MUCSearchController.h"
+//#include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
#include "Swift/Controllers/Chat/ChatsManager.h"
#include "Swift/Controllers/EventController.h"
#include "Swift/Controllers/EventWindowController.h"
#include "Swift/Controllers/UIInterfaces/LoginWindow.h"
#include "Swift/Controllers/UIInterfaces/LoginWindowFactory.h"
-#include "Swift/Controllers/UIInterfaces/EventWindowFactory.h"
+//#include "Swift/Controllers/UIInterfaces/EventWindowFactory.h"
#include "Swift/Controllers/UIInterfaces/MainWindow.h"
-#include "Swift/Controllers/UIInterfaces/MainWindowFactory.h"
+//#include "Swift/Controllers/UIInterfaces/MainWindowFactory.h"
#include "Swift/Controllers/Chat/MUCController.h"
#include "Swift/Controllers/NickResolver.h"
#include "Swift/Controllers/ProfileSettingsProvider.h"
@@ -33,7 +34,7 @@
#include "Swift/Controllers/SystemTrayController.h"
#include "Swift/Controllers/XMLConsoleController.h"
#include "Swift/Controllers/XMPPRosterController.h"
-#include "Swift/Controllers/UIInterfaces/XMLConsoleWidgetFactory.h"
+//#include "Swift/Controllers/UIInterfaces/XMLConsoleWidgetFactory.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include "Swiften/Base/foreach.h"
#include "Swiften/Base/String.h"
@@ -60,7 +61,7 @@ static const String CLIENT_VERSION = "0.3";
static const String CLIENT_NODE = "http://swift.im";
-MainController::MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency)
+MainController::MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory, MUCSearchWindowFactory* mucSearchWindowFactory, bool useDelayForLatency)
: timerFactory_(&boostIOServiceThread_.getIOService()), idleDetector_(&idleQuerier_, &timerFactory_, 100), chatWindowFactory_(chatWindowFactory), mainWindowFactory_(mainWindowFactory), loginWindowFactory_(loginWindowFactory), settings_(settings), loginWindow_(NULL), useDelayForLatency_(useDelayForLatency) {
application_ = application;
presenceOracle_ = NULL;
@@ -77,6 +78,7 @@ MainController::MainController(ChatWindowFactory* chatWindowFactory, MainWindowF
presenceSender_ = NULL;
client_ = NULL;
+ mucSearchWindowFactory_ = mucSearchWindowFactory;
eventWindowFactory_ = eventWindowFactory;
chatListWindowFactory_ = chatListWindowFactory;
uiEventStream_ = new UIEventStream();
@@ -155,6 +157,8 @@ void MainController::resetClient() {
presenceSender_ = NULL;
delete client_;
client_ = NULL;
+ delete mucSearchController_;
+ mucSearchController_ = NULL;
}
@@ -203,6 +207,8 @@ void MainController::handleConnected() {
discoResponder_->setDiscoInfo(discoInfo);
discoResponder_->setDiscoInfo(capsInfo_->getNode() + "#" + capsInfo_->getVersion(), discoInfo);
serverDiscoInfo_ = boost::shared_ptr<DiscoInfo>(new DiscoInfo());
+
+ mucSearchController_ = new MUCSearchController(jid_, uiEventStream_, mucSearchWindowFactory_, client_);
}
boost::shared_ptr<GetDiscoInfoRequest> discoInfoRequest(new GetDiscoInfoRequest(JID(), client_));
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index 5d3f998..63e77f2 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -58,10 +58,12 @@ namespace Swift {
class XMLConsoleWidgetFactory;
class EventWindowFactory;
class EventWindowController;
+ class MUCSearchController;
+ class MUCSearchWindowFactory;
class MainController {
public:
- MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory_, bool useDelayForLatency);
+ MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory, ChatListWindowFactory* chatListWindowFactory_, MUCSearchWindowFactory* mucSearchWindowFactory, bool useDelayForLatency);
~MainController();
@@ -126,5 +128,7 @@ namespace Swift {
ChatListWindowFactory* chatListWindowFactory_;
boost::shared_ptr<ErrorEvent> lastDisconnectError_;
bool useDelayForLatency_;
+ MUCSearchController* mucSearchController_;
+ MUCSearchWindowFactory* mucSearchWindowFactory_;
};
}
diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript
index a7ddc79..eb63bed 100644
--- a/Swift/Controllers/SConscript
+++ b/Swift/Controllers/SConscript
@@ -21,11 +21,12 @@ if env["SCONS_STAGE"] == "build" :
"Chat/ChatController.cpp",
"Chat/ChatControllerBase.cpp",
"Chat/ChatsManager.cpp",
+ "Chat/MUCController.cpp",
+ "Chat/MUCSearchController.cpp",
"MainController.cpp",
"NickResolver.cpp",
"RosterController.cpp",
"XMPPRosterController.cpp",
- "Chat/MUCController.cpp",
"EventController.cpp",
"EventWindowController.cpp",
"SoundEventController.cpp",
diff --git a/Swift/Controllers/UIEvents/RequestMUCSearchUIEvent.h b/Swift/Controllers/UIEvents/RequestMUCSearchUIEvent.h
new file mode 100644
index 0000000..623cd00
--- /dev/null
+++ b/Swift/Controllers/UIEvents/RequestMUCSearchUIEvent.h
@@ -0,0 +1,15 @@
+/*
+ * 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/MUCSearchWindow.h b/Swift/Controllers/UIInterfaces/MUCSearchWindow.h
new file mode 100644
index 0000000..3114a5a
--- /dev/null
+++ b/Swift/Controllers/UIInterfaces/MUCSearchWindow.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/signals.hpp>
+
+#include "Swiften/Base/String.h"
+#include "Swiften/JID/JID.h"
+
+#include "Swift/Controllers/Chat/MUCSearchController.h"
+
+namespace Swift {
+
+ class MUCSearchWindow {
+ 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 show() = 0;
+
+ boost::signal<void (const JID&)> onAddService;
+ };
+}
diff --git a/Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h b/Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h
new file mode 100644
index 0000000..1f0bf90
--- /dev/null
+++ b/Swift/Controllers/UIInterfaces/MUCSearchWindowFactory.h
@@ -0,0 +1,19 @@
+/*
+ * 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/UIInterfaces/MUCSearchWindow.h"
+
+namespace Swift {
+ class UIEventStream;
+ class MUCSearchWindowFactory {
+ public:
+ virtual ~MUCSearchWindowFactory() {};
+
+ virtual MUCSearchWindow* createMUCSearchWindow(UIEventStream* eventStream) = 0;
+ };
+}