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/Chat
parent61078c4e4fd553bf952bae5c9d44da6cb96a3a70 (diff)
downloadswift-705bd7256fa4812045677743fc1e939ccfd66d05.zip
swift-705bd7256fa4812045677743fc1e939ccfd66d05.tar.bz2
List MUCs available on services.
Resolves: #276
Diffstat (limited to 'Swift/Controllers/Chat')
-rw-r--r--Swift/Controllers/Chat/MUCSearchController.cpp156
-rw-r--r--Swift/Controllers/Chat/MUCSearchController.h108
2 files changed, 264 insertions, 0 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_;
+ };
+}