From ce9b4d1865df52497cf0d336efe0de3d1dbb7dec Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Thu, 31 May 2012 19:11:54 +0100
Subject: Better MUC inviting


diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index da96603..4fc3752 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -585,7 +585,7 @@ void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional
 		if (createAsReservedIfNew) {
 			muc->setCreateAsReservedIfNew();
 		}
-		MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_);
+		MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_);
 		mucControllers_[mucJID] = controller;
 		controller->setAvailableServerFeatures(serverDiscoInfo_);
 		controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller));
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 3d04b34..94fd142 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -34,6 +34,7 @@
 #include <Swift/Controllers/Roster/SetAvatar.h>
 #include <Swift/Controllers/Roster/SetPresence.h>
 #include <Swiften/Disco/EntityCapsProvider.h>
+#include <Swiften/Roster/XMPPRoster.h>
 
 
 #define MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS 60000
@@ -57,7 +58,8 @@ MUCController::MUCController (
 		bool useDelayForLatency,
 		TimerFactory* timerFactory,
 		EventController* eventController,
-		EntityCapsProvider* entityCapsProvider) :
+		EntityCapsProvider* entityCapsProvider,
+		XMPPRoster* roster) :
 			ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider), muc_(muc), nick_(nick), desiredNick_(nick), password_(password) {
 	parting_ = true;
 	joined_ = false;
@@ -66,6 +68,7 @@ MUCController::MUCController (
 	doneGettingHistory_ = false;
 	events_ = uiEventStream;
 	inviteWindow_ = NULL;
+	xmppRoster_ = roster;
 	
 	roster_ = new Roster(false, true);
 	completer_ = new TabComplete();
@@ -727,6 +730,15 @@ void MUCController::handleInvitePersonToThisMUCRequest() {
 		inviteWindow_->onCompleted.connect(boost::bind(&MUCController::handleInviteToMUCWindowCompleted, this));
 		inviteWindow_->onDismissed.connect(boost::bind(&MUCController::handleInviteToMUCWindowDismissed, this));
 	}
+	std::vector<std::pair<JID, std::string> > autoCompletes;
+	foreach (XMPPRosterItem item, xmppRoster_->getItems()) {
+		std::pair<JID, std::string> jidName;
+		jidName.first = item.getJID();
+		jidName.second = item.getName();
+		autoCompletes.push_back(jidName);
+		std::cerr << "MUCController adding " << item.getJID().toString() << std::endl;
+	}
+	inviteWindow_->setAutoCompletions(autoCompletes);
 }
 
 void MUCController::handleInviteToMUCWindowDismissed() {
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 8b43dcf..6bf056b 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -32,6 +32,7 @@ namespace Swift {
 	class TimerFactory;
 	class TabComplete;
 	class InviteToChatWindow;
+	class XMPPRoster;
 
 	enum JoinPart {Join, Part, JoinThenPart, PartThenJoin};
 
@@ -43,7 +44,7 @@ namespace Swift {
 
 	class MUCController : public ChatControllerBase {
 		public:
-			MUCController(const JID& self, MUC::ref muc, const boost::optional<std::string>& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider);
+			MUCController(const JID& self, MUC::ref muc, const boost::optional<std::string>& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* roster);
 			~MUCController();
 			boost::signal<void ()> onUserLeft;
 			boost::signal<void ()> onUserJoined;
@@ -124,6 +125,7 @@ namespace Swift {
 			boost::posix_time::ptime lastActivity_;
 			boost::optional<std::string> password_;
 			InviteToChatWindow* inviteWindow_;
+			XMPPRoster* xmppRoster_;
 	};
 }
 
diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
index d4fbcfd..04fc2f7 100644
--- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
@@ -63,7 +63,7 @@ public:
 		entityCapsProvider_ = new DummyEntityCapsProvider();
 		muc_ = boost::make_shared<MUC>(stanzaChannel_, iqRouter_, directedPresenceSender_, mucJID_, mucRegistry_);
 		mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(muc_->getJID(), uiEventStream_).Return(window_);
-		controller_ = new MUCController (self_, muc_, boost::optional<std::string>(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_);
+		controller_ = new MUCController (self_, muc_, boost::optional<std::string>(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_, NULL);
 	};
 
 	void tearDown() {
diff --git a/Swift/Controllers/UIInterfaces/InviteToChatWindow.h b/Swift/Controllers/UIInterfaces/InviteToChatWindow.h
index f34a485..4070e01 100644
--- a/Swift/Controllers/UIInterfaces/InviteToChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/InviteToChatWindow.h
@@ -7,7 +7,7 @@
 #pragma once
 
 #include <vector>
-
+#include <utility>
 #include <string>
 #include <Swiften/Base/boost_bsignals.h>
 #include <Swiften/JID/JID.h>
@@ -17,6 +17,8 @@ namespace Swift {
 		public:
 			virtual ~InviteToChatWindow() {};
 
+			virtual void setAutoCompletions(std::vector<std::pair<JID, std::string> > completions) = 0;
+
 			virtual std::string getReason() const = 0;
 
 			virtual std::vector<JID> getJIDs() const = 0;
diff --git a/Swift/QtUI/QtInviteToChatWindow.cpp b/Swift/QtUI/QtInviteToChatWindow.cpp
index d53c493..3b8f1fc 100644
--- a/Swift/QtUI/QtInviteToChatWindow.cpp
+++ b/Swift/QtUI/QtInviteToChatWindow.cpp
@@ -19,8 +19,8 @@ namespace Swift {
 
 QtInviteToChatWindow::QtInviteToChatWindow(QWidget* parent) : QDialog(parent) {
 	QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, this);
-	layout->setContentsMargins(0,0,0,0);
-	layout->setSpacing(2);
+	//layout->setContentsMargins(0,0,0,0);
+	//layout->setSpacing(2);
 
 	QLabel* description = new QLabel(tr("Users to invite to this chat (one per line):"));
 	layout->addWidget(description);
@@ -45,6 +45,8 @@ QtInviteToChatWindow::QtInviteToChatWindow(QWidget* parent) : QDialog(parent) {
 
 	layout->addWidget(buttonBox);
 
+	jids_[0]->setFocus();
+
 	setModal(false);
 	show();
 }
@@ -81,7 +83,7 @@ std::vector<JID> QtInviteToChatWindow::getJIDs() const {
 
 void QtInviteToChatWindow::addJIDLine() {
 	QLineEdit* jid = new QLineEdit(this);
-	QCompleter* completer = new QCompleter(completions_, this);
+	QCompleter* completer = new QCompleter(&completions_, this);
 	completer->setCaseSensitivity(Qt::CaseInsensitive);
 	jid->setCompleter(completer);
 	jids_.push_back(jid);
@@ -101,6 +103,20 @@ void QtInviteToChatWindow::handleJIDTextChanged() {
 	}
 }
 
+typedef std::pair<JID, std::string> JIDString;
+
+void QtInviteToChatWindow::setAutoCompletions(std::vector<std::pair<JID, std::string> > completions) {
+	QStringList list;
+	foreach (JIDString jidPair, completions) {
+		QString line = P2QSTRING(jidPair.first.toString());
+		if (jidPair.second != jidPair.first.toString() && !jidPair.second.empty()) {
+			line = P2QSTRING(jidPair.second) + " - " + line;
+		}
+		list.append(line);
+	}
+	completions_.setStringList(list);
+}
+
 }
 
 
diff --git a/Swift/QtUI/QtInviteToChatWindow.h b/Swift/QtUI/QtInviteToChatWindow.h
index c009861..a0167db 100644
--- a/Swift/QtUI/QtInviteToChatWindow.h
+++ b/Swift/QtUI/QtInviteToChatWindow.h
@@ -9,7 +9,7 @@
 #include <Swift/Controllers/UIInterfaces/InviteToChatWindow.h>
 
 #include <QDialog>
-#include <QStringList>
+#include <QStringListModel>
 
 class QLineEdit;
 class QBoxLayout;
@@ -24,6 +24,7 @@ namespace Swift {
 			virtual std::string getReason() const;
 
 			virtual std::vector<JID> getJIDs() const;
+			virtual void setAutoCompletions(std::vector<std::pair<JID, std::string> > completions);
 		private:
 			void addJIDLine();
 		private slots:
@@ -31,7 +32,7 @@ namespace Swift {
 			void handleAccepting();
 			void handleRejecting();
 		private:
-			QStringList completions_;
+			QStringListModel completions_;
 			QLineEdit* reason_;
 			QBoxLayout* jidsLayout_;
 			std::vector<QLineEdit*> jids_;
-- 
cgit v0.10.2-6-g49f6