From 3fbab3b40dfc31da46924f13984415b18087a8d4 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Thu, 5 Nov 2009 22:05:15 +0000
Subject: A block of the work for roster pushes.

Still needs unit testing

diff --git a/Swift/Controllers/RosterController.cpp b/Swift/Controllers/RosterController.cpp
index 07edcf3..063d2a7 100644
--- a/Swift/Controllers/RosterController.cpp
+++ b/Swift/Controllers/RosterController.cpp
@@ -35,6 +35,8 @@ RosterController::RosterController(const JID& jid, boost::shared_ptr<XMPPRoster>
 	mainWindow_->onSignOutRequest.connect(boost::bind(boost::ref(onSignOutRequest)));
 	roster_->onUserAction.connect(boost::bind(&RosterController::handleUserAction, this, _1));
 	xmppRoster_->onJIDAdded.connect(boost::bind(&RosterController::handleOnJIDAdded, this, _1));
+	xmppRoster_->onJIDUpdated.connect(boost::bind(&RosterController::handleOnJIDUpdated, this, _1, _2, _3));
+	xmppRoster_->onJIDRemoved.connect(boost::bind(&RosterController::handleOnJIDRemoved, this, _1));
 	avatarManager_ = NULL;
 	setAvatarManager(avatarManager);
 	setNickResolver(nickResolver);
@@ -103,6 +105,34 @@ void RosterController::handleOnJIDAdded(const JID& jid) {
 	}
 }
 
+void RosterController::handleOnJIDRemoved(const JID& jid) {
+	roster_->removeContact(jid);
+}
+
+void RosterController::handleOnJIDUpdated(const JID& jid, const String& oldName, const std::vector<String> oldGroups) {
+	if (oldName != xmppRoster_->getNameForJID(jid)) {
+		handleOnJIDAdded(jid);
+		return;
+	}
+	std::vector<String> groups = xmppRoster_->getGroupsForJID(jid);
+	String name = xmppRoster_->getNameForJID(jid);
+	String contactsGroup = "Contacts";
+	if (groups.empty()) {
+		groups.push_back(contactsGroup);
+	}
+	foreach(const String& group, groups) {
+		if (std::find(oldGroups.begin(), oldGroups.end(), jid) == oldGroups.end()) {
+			roster_->addContact(jid, xmppRoster_->getNameForJID(jid), group);
+		}
+	} 
+	foreach(const String& group, oldGroups) {
+		if (std::find(groups.begin(), groups.end(), group) == groups.end()) {
+			roster_->removeContactFromGroup(jid, group);
+		}
+	}
+	
+}
+
 void RosterController::handleIncomingPresence(boost::shared_ptr<Presence> presence) {
 	roster_->applyOnItems(SetPresence(presence));
 }
diff --git a/Swift/Controllers/RosterController.h b/Swift/Controllers/RosterController.h
index 0da00ac..f3d96e1 100644
--- a/Swift/Controllers/RosterController.h
+++ b/Swift/Controllers/RosterController.h
@@ -37,6 +37,8 @@ namespace Swift {
 			void setEnabled(bool enabled);
 		private:
 			void handleOnJIDAdded(const JID &jid);
+			void handleOnJIDRemoved(const JID &jid);
+			void handleOnJIDUpdated(const JID &jid, const String& oldName, const std::vector<String> oldGroups);
 			void handleStartChatRequest(const JID& contact);
 			void handleJoinMUCRequest(const JID &muc, const String &nick);
 			void handleUserAction(boost::shared_ptr<UserRosterAction> action);
diff --git a/Swift/Controllers/XMPPRosterController.cpp b/Swift/Controllers/XMPPRosterController.cpp
index e1716e6..d089cff 100644
--- a/Swift/Controllers/XMPPRosterController.cpp
+++ b/Swift/Controllers/XMPPRosterController.cpp
@@ -33,6 +33,7 @@ void XMPPRosterController::requestRoster() {
 
 void XMPPRosterController::handleRosterReceived(boost::shared_ptr<RosterPayload> rosterPayload) {
 	foreach(const RosterItemPayload& item, rosterPayload->getItems()) {
+		//Don't worry about the updated case, the XMPPRoster sorts that out.
 		if (item.getSubscription() == RosterItemPayload::Remove) {
 			xmppRoster_->removeContact(item.getJID());
 		} else {
diff --git a/Swiften/Roster/Roster.cpp b/Swiften/Roster/Roster.cpp
index b09964c..28245af 100644
--- a/Swiften/Roster/Roster.cpp
+++ b/Swiften/Roster/Roster.cpp
@@ -72,6 +72,18 @@ void Roster::removeContact(const JID& jid) {
 	}
 }
 
+void Roster::removeContactFromGroup(const JID& jid, const String& groupName) {
+	std::vector<RosterItem*>::iterator it = children_.begin();
+	while (it != children_.end()) {
+		GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(*it);
+		if (group && group->getName() == groupName) {
+			group->removeChild(jid);
+		}
+		it++;
+	}
+}
+
+
 void Roster::applyOnItems(const RosterItemOperation& operation) {
 	std::deque<RosterItem*> queue(children_.begin(), children_.end());
 	while (!queue.empty()) {
diff --git a/Swiften/Roster/Roster.h b/Swiften/Roster/Roster.h
index cdd1407..6010832 100644
--- a/Swiften/Roster/Roster.h
+++ b/Swiften/Roster/Roster.h
@@ -27,6 +27,7 @@ class Roster {
 		GroupRosterItem* getGroup(const String& groupName);
 		void addContact(const JID& jid, const String& name, const String& group);
 		void removeContact(const JID& jid);
+		void removeContactFromGroup(const JID& jid, const String& group);
 		void applyOnItems(const RosterItemOperation& operation);
 		boost::signal<void (boost::shared_ptr<UserRosterAction>)> onUserAction;
 		void addFilter(RosterFilter *filter) {filters_.push_back(filter);filterAll();}
diff --git a/Swiften/Roster/XMPPRoster.cpp b/Swiften/Roster/XMPPRoster.cpp
index 9661171..a5cccaf 100644
--- a/Swiften/Roster/XMPPRoster.cpp
+++ b/Swiften/Roster/XMPPRoster.cpp
@@ -8,9 +8,12 @@ void XMPPRoster::addContact(const JID& jid, const String& name, const std::vecto
 	if (exists) {
 		entries_.erase(bareJID);
 	}
+	String oldName = getNameForJID(bareJID);
+	std::vector<String> oldGroups = entries_[bareJID].second;
 	entries_[bareJID] = std::pair<String, std::vector<String> >(name, groups);
 	if (exists) {
-		onJIDUpdated(bareJID);
+		
+		onJIDUpdated(bareJID, oldName, oldGroups);
 	} else {
 		onJIDAdded(bareJID);
 	}
diff --git a/Swiften/Roster/XMPPRoster.h b/Swiften/Roster/XMPPRoster.h
index f2afbb3..7a72e00 100644
--- a/Swiften/Roster/XMPPRoster.h
+++ b/Swiften/Roster/XMPPRoster.h
@@ -23,7 +23,7 @@ class XMPPRoster {
 
 		boost::signal<void (const JID&)> onJIDAdded;
 		boost::signal<void (const JID&)> onJIDRemoved;
-		boost::signal<void (const JID&)> onJIDUpdated;
+		boost::signal<void (const JID&, const String&, const std::vector<String>&)> onJIDUpdated;
 
 	private:
 		std::map<JID, std::pair<String, std::vector<String> > > entries_;
-- 
cgit v0.10.2-6-g49f6