From e3041b220e4846fb2f0273c720d8bcbd78cafaaf Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Sat, 23 Apr 2011 17:59:17 +0100
Subject: Sort MUC roles by role, rather than by name.

Resolves: #794
Release-Notes: Non-English translations will no longer have MUC role groups in the incorrect order.

diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 2914116..0604dee 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -4,7 +4,7 @@
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
 
-#include "Swift/Controllers/Chat/MUCController.h"
+#include <Swift/Controllers/Chat/MUCController.h>
 
 #include <boost/bind.hpp>
 #include <boost/regex.hpp>
@@ -12,23 +12,24 @@
 
 #include <Swift/Controllers/Intl.h>
 #include <Swiften/Base/format.h>
-#include "Swiften/Network/Timer.h"
-#include "Swiften/Network/TimerFactory.h"
-#include "Swiften/Base/foreach.h"
-#include "SwifTools/TabComplete.h"
-#include "Swiften/Base/foreach.h"
-#include "Swift/Controllers/XMPPEvents/EventController.h"
-#include "Swift/Controllers/UIInterfaces/ChatWindow.h"
-#include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
-#include "Swift/Controllers/UIEvents/UIEventStream.h"
-#include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"
-#include "Swiften/Avatars/AvatarManager.h"
-#include "Swiften/Elements/Delay.h"
-#include "Swiften/MUC/MUC.h"
-#include "Swiften/Client/StanzaChannel.h"
-#include "Swift/Controllers/Roster/Roster.h"
-#include "Swift/Controllers/Roster/SetAvatar.h"
-#include "Swift/Controllers/Roster/SetPresence.h"
+#include <Swiften/Network/Timer.h>
+#include <Swiften/Network/TimerFactory.h>
+#include <Swiften/Base/foreach.h>
+#include <SwifTools/TabComplete.h>
+#include <Swiften/Base/foreach.h>
+#include <Swift/Controllers/XMPPEvents/EventController.h>
+#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
+#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
+#include <Swift/Controllers/UIEvents/UIEventStream.h>
+#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
+#include <Swift/Controllers/Roster/GroupRosterItem.h>
+#include <Swiften/Avatars/AvatarManager.h>
+#include <Swiften/Elements/Delay.h>
+#include <Swiften/MUC/MUC.h>
+#include <Swiften/Client/StanzaChannel.h>
+#include <Swift/Controllers/Roster/Roster.h>
+#include <Swift/Controllers/Roster/SetAvatar.h>
+#include <Swift/Controllers/Roster/SetPresence.h>
 
 
 #define MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS 60000
@@ -206,7 +207,12 @@ void MUCController::handleOccupantJoined(const MUCOccupant& occupant) {
 	currentOccupants_.insert(occupant.getNick());
 	NickJoinPart event(occupant.getNick(), Join);
 	appendToJoinParts(joinParts_, event);
-	roster_->addContact(jid, realJID, occupant.getNick(), roleToGroupName(occupant.getRole()), avatarManager_->getAvatarPath(jid).string());
+	std::string groupName(roleToGroupName(occupant.getRole()));
+	roster_->addContact(jid, realJID, occupant.getNick(), groupName, avatarManager_->getAvatarPath(jid).string());
+	if (addedRosterGroups_.count(groupName) == 0) {
+		roster_->getGroup(groupName)->setManualSort(roleToSortName(occupant.getRole()));
+		addedRosterGroups_.insert(groupName);
+	}
 	if (joined_) {
 		std::string joinString;
 		MUCOccupant::Role role = occupant.getRole();
@@ -248,6 +254,16 @@ std::string MUCController::roleToFriendlyName(MUCOccupant::Role role) {
 	return "";
 }
 
+std::string MUCController::roleToSortName(MUCOccupant::Role role) {
+	switch (role) {
+	case MUCOccupant::Moderator: return "1";
+	case MUCOccupant::Participant: return "2";
+	case MUCOccupant::Visitor: return "3";
+	case MUCOccupant::NoRole: return "4";
+	}
+	return "5";
+}
+
 JID MUCController::nickToJID(const std::string& nick) {
 	return JID(toJID_.getNode(), toJID_.getDomain(), nick);
 }
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index ebdd6cd..e876791 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -7,18 +7,18 @@
 #pragma once
 
 #include <boost/shared_ptr.hpp>
-#include "Swiften/Base/boost_bsignals.h"
+#include <Swiften/Base/boost_bsignals.h>
 #include <boost/signals/connection.hpp>
 #include <set>
 
 #include <string>
-#include "Swiften/Network/Timer.h"
-#include "Swift/Controllers/Chat/ChatControllerBase.h"
-#include "Swiften/Elements/Message.h"
-#include "Swiften/Elements/DiscoInfo.h"
-#include "Swiften/JID/JID.h"
-#include "Swiften/MUC/MUC.h"
-#include "Swiften/Elements/MUCOccupant.h"
+#include <Swiften/Network/Timer.h>
+#include <Swift/Controllers/Chat/ChatControllerBase.h>
+#include <Swiften/Elements/Message.h>
+#include <Swiften/Elements/DiscoInfo.h>
+#include <Swiften/JID/JID.h>
+#include <Swiften/MUC/MUC.h>
+#include <Swiften/Elements/MUCOccupant.h>
 
 namespace Swift {
 	class StanzaChannel;
@@ -71,6 +71,7 @@ namespace Swift {
 			void handleJoinFailed(boost::shared_ptr<ErrorPayload> error);
 			void handleJoinTimeoutTick();
 			std::string roleToGroupName(MUCOccupant::Role role);
+			std::string roleToSortName(MUCOccupant::Role role);
 			JID nickToJID(const std::string& nick);
 			std::string roleToFriendlyName(MUCOccupant::Role role);
 			void receivedActivity();
@@ -97,6 +98,7 @@ namespace Swift {
 			std::set<std::string> currentOccupants_;
 			std::vector<NickJoinPart> joinParts_;
 			boost::posix_time::ptime lastActivity_;
+			std::set<std::string> addedRosterGroups_;
 	};
 }
 
diff --git a/Swift/Controllers/Roster/GroupRosterItem.cpp b/Swift/Controllers/Roster/GroupRosterItem.cpp
index f0a377a..b8fad07 100644
--- a/Swift/Controllers/Roster/GroupRosterItem.cpp
+++ b/Swift/Controllers/Roster/GroupRosterItem.cpp
@@ -12,7 +12,7 @@
 
 namespace Swift {
 
-GroupRosterItem::GroupRosterItem(const std::string& name, GroupRosterItem* parent, bool sortByStatus) : RosterItem(name, parent), sortByStatus_(sortByStatus) {
+GroupRosterItem::GroupRosterItem(const std::string& name, GroupRosterItem* parent, bool sortByStatus) : RosterItem(name, parent), sortByStatus_(sortByStatus), manualSort_(false) {
 	expanded_ = true;
 }
 
@@ -20,6 +20,19 @@ GroupRosterItem::~GroupRosterItem() {
 
 }
 
+void GroupRosterItem::setManualSort(const std::string& manualSortValue) {
+	manualSort_ = true;
+	bool changed = manualSortValue_ != manualSortValue;
+	manualSortValue_ = manualSortValue;
+	if (changed) {
+		onDataChanged();
+	}
+}
+
+const std::string& GroupRosterItem::getSortableDisplayName() const {
+	return manualSort_ ? manualSortValue_ : RosterItem::getSortableDisplayName();
+}
+
 bool GroupRosterItem::isExpanded() const {
 	return expanded_;
 }
diff --git a/Swift/Controllers/Roster/GroupRosterItem.h b/Swift/Controllers/Roster/GroupRosterItem.h
index 57fa9fa..beb7705 100644
--- a/Swift/Controllers/Roster/GroupRosterItem.h
+++ b/Swift/Controllers/Roster/GroupRosterItem.h
@@ -31,6 +31,8 @@ class GroupRosterItem : public RosterItem {
 		void setExpanded(bool expanded);
 		bool isExpanded() const;
 		boost::signal<void (bool)> onExpandedChanged;
+		void setManualSort(const std::string& manualSortValue);
+		virtual const std::string& getSortableDisplayName() const;
 	private:
 		void handleChildrenChanged(GroupRosterItem* group);
 		void handleDataChanged(RosterItem* item);
@@ -40,6 +42,8 @@ class GroupRosterItem : public RosterItem {
 		std::vector<RosterItem*> children_;
 		std::vector<RosterItem*> displayedChildren_;
 		bool sortByStatus_;
+		bool manualSort_;
+		std::string manualSortValue_;
 };
 
 }
diff --git a/Swift/Controllers/Roster/RosterItem.cpp b/Swift/Controllers/Roster/RosterItem.cpp
index 3f130bb..77db8a3 100644
--- a/Swift/Controllers/Roster/RosterItem.cpp
+++ b/Swift/Controllers/Roster/RosterItem.cpp
@@ -33,11 +33,11 @@ void RosterItem::setDisplayName(const std::string& name) {
 	onDataChanged();
 }
 
-std::string RosterItem::getDisplayName() const {
+const std::string& RosterItem::getDisplayName() const {
 	return name_;
 }
 
-std::string RosterItem::getSortableDisplayName() const {
+const std::string& RosterItem::getSortableDisplayName() const {
 	return sortableDisplayName_;
 }
 
diff --git a/Swift/Controllers/Roster/RosterItem.h b/Swift/Controllers/Roster/RosterItem.h
index ed8cb16..769f72d 100644
--- a/Swift/Controllers/Roster/RosterItem.h
+++ b/Swift/Controllers/Roster/RosterItem.h
@@ -20,8 +20,8 @@ class RosterItem {
 		boost::signal<void ()> onDataChanged;
 		GroupRosterItem* getParent() const;
 		void setDisplayName(const std::string& name);
-		std::string getDisplayName() const;
-		std::string getSortableDisplayName() const;
+		const std::string& getDisplayName() const;
+		virtual const std::string& getSortableDisplayName() const;
 	private:
 		std::string name_;
 		std::string sortableDisplayName_;
-- 
cgit v0.10.2-6-g49f6