From 8d0ff396b17bc14972bca34d396276f71a04cb9f Mon Sep 17 00:00:00 2001
From: Stephan Erb <steve-e@h3c.de>
Date: Sat, 29 Nov 2008 23:43:23 +0000
Subject: [PATCH] Do not duplicate a contact in roster on subscription changes.
 Fixes #4524.

For performance reasons, get_contact_iters() cannot find a contact if get_shown_groups() returns something different to what has been applied to roster model. The contact was therefore duplicated as it was believed not to be there...
---
 src/gajim.py         | 20 +++++++++++---------
 src/roster_window.py |  3 +--
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/src/gajim.py b/src/gajim.py
index 4d48269724..1b9d396b6c 100755
--- a/src/gajim.py
+++ b/src/gajim.py
@@ -1489,7 +1489,7 @@ class Interface:
 		contacts = gajim.contacts.get_contacts(account, jid)
 		if (not sub or sub == 'none') and (not ask or ask == 'none') and \
 		not name and not groups:
-			# contact removes us.
+			# contact removed us.
 			if contacts:
 				self.roster.remove_contact(jid, account, backend=True)
 				return
@@ -1504,22 +1504,24 @@ class Interface:
 		else:
 			# it is an existing contact that might has changed
 			re_draw = False
-			# if sub or groups changed: remove and re-add
-			# Maybe observer status changed:
-			# according to xep 0162, contact is not an observer anymore when 
-			# we asked him is auth, so also remove him if ask changed
-			old_groups = contacts[0].get_shown_groups()
+			# If contact has changed (sub, ask or group) update roster
+			# Mind about observer status changes:
+			# 	According to xep 0162, a contact is not an observer anymore when 
+			# 	we asked for auth, so also remove him if ask changed
+			old_groups = contacts[0].groups
 			if contacts[0].sub != sub or contacts[0].ask != ask\
 			or old_groups != groups:
 				re_draw = True
+			if re_draw:
+				# c.get_shown_groups() has changed. Reflect that in roster_winodow
+				self.roster.remove_contact(jid, account, force=True)
 			for contact in contacts:
-				if not name:
-					name = ''
-				contact.name = name
+				contact.name = name or ''
 				contact.sub = sub
 				contact.ask = ask
 				contact.groups = groups or []
 			if re_draw:
+				self.roster.add_contact(jid, account)
 				# Refilter and update old groups
 				for group in old_groups:
 					self.roster.draw_group(group, account)
diff --git a/src/roster_window.py b/src/roster_window.py
index 6732e02393..c6aa44655b 100644
--- a/src/roster_window.py
+++ b/src/roster_window.py
@@ -872,12 +872,11 @@ class RosterWindow:
 		for contact in gajim.contacts.get_contacts(account, jid):
 			for group in groups:
 				if group in contact.groups:
-					# Needed when we remove from "General"
+					# Needed when we remove from "General" or "Observers"
 					contact.groups.remove(group)
 			if update:
 				gajim.connections[account].update_contact(jid, contact.name,
 					contact.groups)
-
 		self.add_contact(jid, account)
 		
 		# Also redraw old groups
-- 
GitLab