gobjectification: b6473078: Fixed group adding

aluink at soc.pidgin.im aluink at soc.pidgin.im
Wed Jul 15 20:55:30 EDT 2009


-----------------------------------------------------------------
Revision: b64730787353d3c8678ee066953f1ab16e58cc35
Ancestor: 2ef380ad3a75f214245ca5e1a34e7fc3d4e23914
Author: aluink at soc.pidgin.im
Date: 2009-07-13T01:47:51
Branch: im.pidgin.gobjectification
URL: http://d.pidgin.im/viewmtn/revision/info/b64730787353d3c8678ee066953f1ab16e58cc35

Modified files:
        libpurple/blist-node.c libpurple/blist-node.h
        libpurple/blist.c libpurple/blist.h libpurple/contact.c
        libpurple/contact.h libpurple/group.c libpurple/group.h

ChangeLog: 

Fixed group adding

-------------- next part --------------
============================================================
--- libpurple/blist-node.c	284f162c202c47dce41901211e5a7148ea6382bc
+++ libpurple/blist-node.c	da7c3d2a7189adb0e489558fff95cd99ee5c86ed
@@ -430,18 +430,50 @@ purple_blist_node_get_extended_menu(Purp
 	return menu;
 }
 
-static void
-purple_blist_node_add_node(PurpleBlistNode *parent, PurpleBlistNode *child)
+gboolean
+purple_blist_node_contains(PurpleBlistNode *parent, PurpleBlistNode *node)
 {
+	return node->parent == parent;
 }
 
-static void
-purple_blist_node_remove_node(PurpleBlistNode *group, PurpleBlistNode *child)
+void
+purple_blist_node_add_child(PurpleBlistNode *parent, PurpleBlistNode *child)
 {
-	PurpleBlistNodeClass *gklass = PURPLE_GET_BLIST_NODE_CLASS(group);
-	PurpleBlistNode *contact = purple_blist_node_get_parent(child);
-	PurpleBlistNodeClass *cklass = PURPLE_GET_BLIST_NODE_CLASS(contact);
+	if (parent->child)
+		parent->child->prev = child;
+	child->prev = NULL;
+	child->next = parent->child;
+	parent->child = child;
+	child->parent = parent;
+}
 
+void
+purple_blist_node_add_sibling_before(PurpleBlistNode *child, PurpleBlistNode *location)
+{
+	g_return_if_fail(location);
+	g_return_if_fail(child);
+	child->next = location;
+	child->prev = location->prev;
+	location->prev->next = child;
+	location->prev = child;
+}
+
+void
+purple_blist_node_add_sibling_after(PurpleBlistNode *child, PurpleBlistNode *location)
+{
+	g_return_if_fail(child);
+	g_return_if_fail(location);
+	if (location->next)
+		location->next->prev = child;
+	child->next = location->next;
+	child->prev = location;
+	child->parent = location->parent;
+	location->next = child;
+}
+
+void
+purple_blist_node_remove(PurpleBlistNode *child)
+{
 	/* Remove the node from its parent */
 	if (child->prev)
 		child->prev->next = child->next;
@@ -451,10 +483,16 @@ purple_blist_node_remove_node(PurpleBlis
 	if ((child->parent != NULL) && (child->parent->child == child))
 		child->parent->child = child->next;
 
-	cklass->remove_node(contact, child);
-	gklass->remove_node(group, contact);
+	purple_blist_node_strip(child);
 }
 
+void
+purple_blist_node_strip(PurpleBlistNode *node)
+{
+	g_return_if_fail(node);
+	node->parent = node->child = node->next = node->prev = NULL;
+}
+
 /******************/
 /*  GObject Code  */
 /******************/
@@ -500,6 +538,13 @@ purple_blist_node_finalize(GObject *obje
 	parent_class->finalize(object);
 }
 
+static void *
+purple_blist_node_handle()
+{
+	static int handle;
+	return &handle;
+}
+
 static void
 purple_blist_node_class_init(PurpleBlistNodeClass *klass)
 {
@@ -510,8 +555,17 @@ purple_blist_node_class_init(PurpleBlist
 
 	g_type_class_add_private(klass, sizeof(PurpleBlistNodePrivate));
 
-	klass->add_node = purple_blist_node_add_node;
-	klass->remove_node = purple_blist_node_remove_node;
+	klass->add_node = purple_blist_node_add_child;
+	klass->remove_node = purple_blist_node_remove;
+
+	purple_signal_register( purple_blist_node_handle(),
+													"node-updated",
+													purple_marshal_VOID__POINTER,
+													NULL,
+													1,
+													purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_BLIST_NODE));
+
+
 }
 
 static void
============================================================
--- libpurple/blist-node.h	328c1b48a8d24bc2b1bc00afad46944896b6f4d6
+++ libpurple/blist-node.h	c68193160082d8caf7c874498fb0b599a61a577d
@@ -76,8 +76,8 @@ struct _PurpleBlistNodeClass {
 struct _PurpleBlistNodeClass {
 	PurpleObjectClass parent;
 
-	void (*add_node)(PurpleBlistNode *parent, PurpleBlistNode *child);
-	void (*remove_node)(PurpleBlistNode *parent, PurpleBlistNode *child);
+	void (*add_node)(PurpleBlistNode *parent, PurpleBlistNode *child, PurpleBlistNode *location);
+	void (*remove_node)(PurpleBlistNode *child);
 
 	void (*purple_reserved1)(void);
 	void (*purple_reserved2)(void);
@@ -152,6 +152,53 @@ PurpleBlistNode *purple_blist_node_get_s
 PurpleBlistNode *purple_blist_node_get_sibling_prev(PurpleBlistNode *node);
 
 /**
+ * Check whether a node is contained in a parent node. Simply checks if the node's parent is the other node.
+ *
+ * @param parent The containing node
+ * @param node The node to check with.
+ * @return Returns TRUE if node's parent is parent.
+ */
+gboolean purple_blist_node_contains(PurpleBlistNode *parent, PurpleBlistNode *node);
+
+/**
+ * Add a node as the first child of a given node.
+ *
+ * @param parent The parent node
+ * @param child The child node to add to parent
+ */
+void purple_blist_node_add_child(PurpleBlistNode *parent, PurpleBlistNode *child);
+
+/**
+ * Add a node before a given node.
+ *
+ * @param node The node to add
+ * @param location The node to insert before, not NULL
+ */
+void purple_blist_node_add_sibling_before(PurpleBlistNode *node, PurpleBlistNode *location);
+
+/**
+ * Add a node after a given node.
+ *
+ * @param node The node to add
+ * @param location The node to insert after, not NULL
+ */
+void purple_blist_node_add_sibling_after(PurpleBlistNode *node, PurpleBlistNode *location);
+
+/**
+ * Remove a node from its parent
+ *
+ * @param node The node to remove
+ */
+void purple_blist_node_remove(PurpleBlistNode *node);
+
+/**
+ * Isolate a node by making all its references NULL.
+ *
+ * @param node The node to isolate
+ */
+void purple_blist_node_strip(PurpleBlistNode *node);
+
+/**
  * Returns the UI data of a given node.
  *
  * @param node The node.
============================================================
--- libpurple/blist.c	35079d994842b0aad4a1e6a418ab888ffd3f6dd1
+++ libpurple/blist.c	d0d36f1e2aa8bde6b01ee6f7aac8a908914bf4f1
@@ -416,6 +416,134 @@ purple_strings_are_different(const char 
 }
 
 /*
+ * TODO: If merging, prompt the user if they want to merge.
+ */
+void purple_blist_rename_group(PurpleGroup *source, const char *name)
+{
+	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
+	PurpleGroup *dest;
+	gchar *old_name;
+	gchar *new_name;
+	GList *moved_buddies = NULL;
+	GSList *accts;
+
+	g_return_if_fail(source != NULL);
+	g_return_if_fail(name != NULL);
+
+	new_name = purple_utf8_strip_unprintables(name);
+
+	if (*new_name == '\0' || purple_strequal(new_name, source->name)) {
+		g_free(new_name);
+		return;
+	}
+
+	dest = purple_find_group(new_name);
+	if (dest != NULL && purple_utf8_strcasecmp(source->name, dest->name) != 0) {
+		/* We're merging two groups */
+		PurpleBlistNode *prev, *child, *next;
+
+		prev = purple_blist_get_last_child((PurpleBlistNode*)dest);
+		child = ((PurpleBlistNode*)source)->child;
+
+		/*
+		 * TODO: This seems like a dumb way to do this... why not just
+		 * append all children from the old group to the end of the new
+		 * one?  PRPLs might be expecting to receive an add_buddy() for
+		 * each moved buddy...
+		 */
+		while (child)	{
+			next = child->next;
+			if (PURPLE_IS_CONTACT(child)) {
+				PurpleBlistNode *bnode;
+				purple_blist_add_contact((PurpleContact *)child, dest, prev);
+				for (bnode = child->child; bnode != NULL; bnode = bnode->next) {
+					purple_blist_add_buddy((PurpleBuddy *)bnode, (PurpleContact *)child,
+							NULL, bnode->prev);
+					moved_buddies = g_list_append(moved_buddies, bnode);
+				}
+				prev = child;
+			} else if (PURPLE_IS_CHAT(child)) {
+				purple_blist_add_chat((PurpleChat *)child, dest, prev);
+				prev = child;
+			} else {
+				purple_debug(PURPLE_DEBUG_ERROR, "blist",
+						"Unknown child type in group %s\n", source->name);
+			}
+			child = next;
+		}
+
+		/* Make a copy of the old group name and then delete the old group */
+		old_name = g_strdup(source->name);
+		purple_blist_remove_group(source);
+		source = dest;
+		g_free(new_name);
+	} else {
+		/* A simple rename */
+		moved_buddies = purple_group_get_buddies(source);
+
+		old_name = source->name;
+		source->name = new_name;
+	}
+
+	/* Save our changes */
+	purple_blist_schedule_save();
+
+	/* Update the UI */
+	if (ops && ops->update)
+		ops->update(purplebuddylist, (PurpleBlistNode*)source);
+
+	/* Notify all PRPLs */
+	/* TODO: Is this condition needed?  Seems like it would always be TRUE */
+	if(old_name && !purple_strequal(source->name, old_name)) {
+		for (accts = purple_group_get_accounts(source); accts; accts = g_slist_remove(accts, accts->data)) {
+			PurpleAccount *account = accts->data;
+			PurpleConnection *gc = NULL;
+			PurplePlugin *prpl = NULL;
+			PurplePluginProtocolInfo *prpl_info = NULL;
+			GList *l = NULL, *buddies = NULL;
+
+			gc = purple_account_get_connection(account);
+
+			if(gc)
+				prpl = purple_connection_get_prpl(gc);
+
+			if(gc && prpl)
+				prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+			if(!prpl_info)
+				continue;
+
+			for(l = moved_buddies; l; l = l->next) {
+				PurpleBuddy *buddy = (PurpleBuddy *)l->data;
+
+				if(buddy && purple_buddy_get_account(buddy)== account)
+					buddies = g_list_append(buddies, (PurpleBlistNode *)buddy);
+			}
+
+			if(prpl_info->rename_group) {
+				prpl_info->rename_group(gc, old_name, source, buddies);
+			} else {
+				GList *cur, *groups = NULL;
+
+				/* Make a list of what the groups each buddy is in */
+				for(cur = buddies; cur; cur = cur->next) {
+					PurpleBlistNode *node = (PurpleBlistNode *)cur->data;
+					groups = g_list_prepend(groups, node->parent->parent);
+				}
+
+				purple_account_remove_buddies(account, buddies, groups);
+				g_list_free(groups);
+				purple_account_add_buddies(account, buddies);
+			}
+
+			g_list_free(buddies);
+		}
+	}
+	g_list_free(moved_buddies);
+	g_free(old_name);
+}
+
+/*
  * TODO: Maybe remove the call to this from server.c and call it
  * from oscar.c and toc.c instead?
  */
@@ -484,21 +612,20 @@ void purple_blist_add_contact(PurpleCont
 	gnode = (PurpleBlistNode*)g;
 	cnode = (PurpleBlistNode*)contact;
 
+	/* If node is already in the list somewhere */	
 	if (cnode->parent) {
-		if (cnode->parent->child == cnode)
-			cnode->parent->child = cnode->next;
-		if (cnode->prev)
-			cnode->prev->next = cnode->next;
-		if (cnode->next)
-			cnode->next->prev = cnode->prev;
-
-		if (cnode->parent != gnode) {
+		purple_blist_node_remove(cnode);
+		/* If node is in the group already */
+		if (purple_blist_node_contains(gnode, cnode)) {
 			bnode = cnode->child;
+			/* Iterate the buddies of the contact */
 			while (bnode) {
 				PurpleBlistNode *next_bnode = bnode->next;
 				PurpleBuddy *b = (PurpleBuddy*)bnode;
 				GHashTable *account_buddies;
 
+
+				/* Remove the buddy from the buddies and buddies_cache HTs */
 				struct _purple_hbuddy *hb, *hb2;
 				
 				hb = g_new(struct _purple_hbuddy, 1);
@@ -511,6 +638,7 @@ void purple_blist_add_contact(PurpleCont
 				account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, purple_buddy_get_account(b));
 				g_hash_table_remove(account_buddies, hb);
 
+				/* If buddy isn't in the group, then add it to the caches with the new group */
 				if (!purple_find_buddy_in_group(purple_buddy_get_account(b), purple_buddy_get_name(b), g)) {
 					hb->group = gnode;
 					g_hash_table_replace(purplebuddylist->buddies, hb, b);
@@ -525,6 +653,8 @@ void purple_blist_add_contact(PurpleCont
 					if (purple_account_get_connection(purple_buddy_get_account(b)))
 						serv_move_buddy(b, (PurpleGroup *)cnode->parent, g);
 				} else {
+					/* If it's already in the group, then we don't move it there,
+					 * we just remove it from the contact.*/
 					gboolean empty_contact = FALSE;
 
 					/* this buddy already exists in the group, so we're
@@ -534,6 +664,7 @@ void purple_blist_add_contact(PurpleCont
 					if (purple_account_get_connection(purple_buddy_get_account(b)))
 						purple_account_remove_buddy(purple_buddy_get_account(b), b, (PurpleGroup *)cnode->parent);
 
+					/* Since we removed it from the contact, the cnode might be empty */
 					if (!cnode->child->next)
 						empty_contact = TRUE;
 					purple_blist_remove_buddy(b);
@@ -541,6 +672,7 @@ void purple_blist_add_contact(PurpleCont
 					/** in purple_blist_remove_buddy(), if the last buddy in a
 					 * contact is removed, the contact is cleaned up and
 					 * g_free'd, so we mustn't try to reference bnode->next */
+					/* If the contact is empty, it's deleted, and thus there's nothing to move */
 					if (empty_contact)
 						return;
 				}
@@ -548,11 +680,8 @@ void purple_blist_add_contact(PurpleCont
 			}
 		}
 
-		if (purple_contact_get_online(contact) > 0)
-			((PurpleGroup*)cnode->parent)->online--;
-		if (purple_contact_get_currentsize(contact) > 0)
-			((PurpleGroup*)cnode->parent)->currentsize--;
-		((PurpleGroup*)cnode->parent)->totalsize--;
+		/*purple_group_remove_contact_count(PURPLE_GROUP(cnode->parent), contact);*/
+		PURPLE_GROUP(cnode->parent)->totalsize--;
 
 		if (ops && ops->remove)
 			ops->remove(purplebuddylist, cnode);
@@ -560,30 +689,10 @@ void purple_blist_add_contact(PurpleCont
 		purple_blist_schedule_save();
 	}
 
-	if (node && (PURPLE_IS_CONTACT(node) ||
-				PURPLE_IS_CHAT(node))) {
-		if (node->next)
-			node->next->prev = cnode;
-		cnode->next = node->next;
-		cnode->prev = node;
-		cnode->parent = node->parent;
-		node->next = cnode;
-	} else {
-		if (gnode->child)
-			gnode->child->prev = cnode;
-		cnode->prev = NULL;
-		cnode->next = gnode->child;
-		gnode->child = cnode;
-		cnode->parent = gnode;
-	}
+	/*purple_group_add_contact(g,contact,node);*/
 
-	if (purple_contact_get_online(contact) > 0)
-		g->online++;
-	if (purple_contact_get_currentsize(contact) > 0)
-		g->currentsize++;
-	g->totalsize++;
+	purple_blist_schedule_save();
 
-	purple_blist_schedule_save();
 
 	if (ops && ops->update)
 	{
@@ -595,6 +704,24 @@ void purple_blist_add_contact(PurpleCont
 	}
 }
 
+/**
+ * Return the group this node is contained in, or the node itself if the node is a group.
+ *
+ * @param node The node to search
+ * @return The group containing the node, or the node itself if the node is a group
+ */
+static PurpleGroup *
+purple_blist_get_containing_group(PurpleBlistNode *node)
+{
+	g_return_val_if_fail(node, NULL);
+	do {
+		if(PURPLE_IS_GROUP(node))
+			return PURPLE_GROUP(node);
+		node = node->parent;
+	} while(node);
+	return NULL;
+}
+
 void purple_blist_add_group(PurpleGroup *group, PurpleBlistNode *node)
 {
 	PurpleBlistUiOps *ops;
@@ -622,24 +749,20 @@ void purple_blist_add_group(PurpleGroup 
 
 		if (gnode == purplebuddylist->root)
 			purplebuddylist->root = gnode->next;
-		if (gnode->prev)
-			gnode->prev->next = gnode->next;
-		if (gnode->next)
-			gnode->next->prev = gnode->prev;
+		purple_blist_node_remove(gnode);
 	}
 
-	if (node && PURPLE_IS_GROUP(node)) {
-		gnode->next = node->next;
-		gnode->prev = node;
-		if (node->next)
-			node->next->prev = gnode;
-		node->next = gnode;
+	if (node) {
+		node = PURPLE_BLIST_NODE(purple_blist_get_containing_group(node));
+		purple_blist_node_add_sibling_after(gnode, node);
 	} else {
-		if (purplebuddylist->root)
-			purplebuddylist->root->prev = gnode;
-		gnode->next = purplebuddylist->root;
-		gnode->prev = NULL;
-		purplebuddylist->root = gnode;
+		if (purplebuddylist->root) {
+			purple_blist_node_add_sibling_before(gnode, purplebuddylist->root);
+		}
+		else {
+			purple_blist_node_strip(gnode);
+			purplebuddylist->root = gnode;
+		}
 	}
 
 	purple_blist_schedule_save();
@@ -681,12 +804,7 @@ void purple_blist_remove_contact(PurpleC
 		purple_blist_remove_buddy((PurpleBuddy*)node->child);
 	} else {
 		/* Remove the node from its parent */
-		if (gnode->child == node)
-			gnode->child = node->next;
-		if (node->prev)
-			node->prev->next = node->next;
-		if (node->next)
-			node->next->prev = node->prev;
+		purple_blist_node_remove(node);
 
 		purple_blist_schedule_save();
 
@@ -715,7 +833,8 @@ void purple_blist_remove_buddy(PurpleBud
 	cnode = purple_blist_node_get_parent(node);
 	gnode = purple_blist_node_get_parent(cnode);
 
-	PURPLE_GET_BLIST_NODE_CLASS(node)->remove_node(gnode, node);
+	purple_blist_node_remove(node);
+	
 	purple_blist_schedule_save();
 
 	/* Remove this buddy from the buddies hash table */
@@ -757,12 +876,7 @@ void purple_blist_remove_chat(PurpleChat
 	if (gnode != NULL)
 	{
 		/* Remove the node from its parent */
-		if (gnode->child == node)
-			gnode->child = node->next;
-		if (node->prev)
-			node->prev->next = node->next;
-		if (node->next)
-			node->next->prev = node->prev;
+		purple_blist_node_remove(node);
 
 		/* Adjust size counts */
 		if (purple_account_is_connected(chat->account)) {
@@ -800,12 +914,7 @@ void purple_blist_remove_group(PurpleGro
 		return;
 
 	/* Remove the node from its parent */
-	if (purplebuddylist->root == node)
-		purplebuddylist->root = node->next;
-	if (node->prev)
-		node->prev->next = node->next;
-	if (node->next)
-		node->next->prev = node->prev;
+	purple_blist_node_remove(node);
 
 	purple_blist_schedule_save();
 
============================================================
--- libpurple/blist.h	0dbe462ed24bf7230be59224963bf52e04029987
+++ libpurple/blist.h	4f36e6d84f8d69e8528c9e9be006c74e7c59670a
@@ -291,7 +291,7 @@ void purple_blist_add_buddy(PurpleBuddy 
 /**
  * Adds a new group to the buddy list.
  *
- * The new group will be inserted after insert or prepended to the list if
+ * The new group will be inserted after node or prepended to the list if
  * node is NULL.
  *
  * @param group  The group
============================================================
--- libpurple/contact.c	f225b58c37533bfdee32ee10d4ce4b8f00dd6a66
+++ libpurple/contact.c	0fce70049c47b2f7ccf898f4ee8834b3ebbbb8cb
@@ -280,6 +280,24 @@ gboolean purple_contact_on_account(Purpl
 	return FALSE;
 }
 
+GList *purple_contact_get_buddies(PurpleContact *contact)
+{
+	GList *buddies = NULL;
+	PurpleBlistNode *cnode;
+	PurpleBlistNode *itr;
+
+	g_return_val_if_fail(contact, NULL);
+	cnode = PURPLE_BLIST_NODE(contact);
+
+	for(itr = cnode->child;itr;itr = itr->next){
+		if(PURPLE_IS_BUDDY(itr)){
+			buddies = g_list_append(buddies,itr);
+		}
+	}
+
+	return buddies;
+}
+
 void purple_contact_invalidate_priority_buddy(PurpleContact *contact)
 {
 	g_return_if_fail(contact != NULL);
@@ -298,18 +316,19 @@ static void
 }
 
 static void
-purple_contact_add_buddy(PurpleBlistNode *parent, PurpleBlistNode *child)
+purple_contact_add_buddy(PurpleBlistNode *parent, PurpleBlistNode *child, PurpleBlistNode *location)
 {
 
 }
 
 static void
-purple_contact_remove_buddy(PurpleBlistNode *parent, PurpleBlistNode *child)
+purple_contact_remove_buddy(PurpleBlistNode *child)
 {
-	PurpleContact *contact = PURPLE_CONTACT(parent);
+	PurpleContact *contact;
 	PurpleBuddy *buddy = PURPLE_BUDDY(child);
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
-	g_return_if_fail(contact);
+	g_return_if_fail(purple_blist_node_get_parent(child));
+	contact = PURPLE_CONTACT(purple_blist_node_get_parent(child));
 
 	if (PURPLE_BUDDY_IS_ONLINE(buddy))
 		contact->online--;
@@ -317,14 +336,15 @@ purple_contact_remove_buddy(PurpleBlistN
 		contact->currentsize--;
 	contact->totalsize--;
 
-#warning The ui calls haven't been thought out yet, as to where they ought to go.
+	/* emit a node-updated signal here */
+
+#warning The ui calls havent been thought out yet, as to where they ought to go.
 	/* Re-sort the contact */
 	if (purple_blist_node_get_first_child(PURPLE_BLIST_NODE(contact)) && contact->priority == buddy) {
 		purple_contact_invalidate_priority_buddy(contact);
 		if (ops && ops->update)
 			ops->update(purplebuddylist, PURPLE_BLIST_NODE(contact));
 	}
-
 }
 
 /****************/
============================================================
--- libpurple/contact.h	72b439d3cc6745409bbf88509d8bae1a028ca382
+++ libpurple/contact.h	5d8bd3aa66ac07cddb3fb79ba83df13c8884e72e
@@ -128,6 +128,14 @@ const char *purple_contact_get_alias(Pur
 const char *purple_contact_get_alias(PurpleContact *contact);
 
 /**
+ * Get a list of buddies for this contact
+ *
+ * @param contact The contact
+ * @return the list of buddies
+ */
+GList *purple_contact_get_buddies(PurpleContact *contact);
+
+/**
  * Returns a buddy's contact.
  *
  * @param buddy The buddy.
============================================================
--- libpurple/group.c	1d155a7e3af1302b0948d34bc83e5727a7baf620
+++ libpurple/group.c	d6f3080aedb46426fa288810e3f3ef43d4db6b56
@@ -66,142 +66,6 @@ group_to_xmlnode(PurpleBlistNode *gnode)
 	return node;
 }
 
-/*
- * TODO: If merging, prompt the user if they want to merge.
- */
-void purple_blist_rename_group(PurpleGroup *source, const char *name)
-{
-	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
-	PurpleGroup *dest;
-	gchar *old_name;
-	gchar *new_name;
-	GList *moved_buddies = NULL;
-	GSList *accts;
-
-	g_return_if_fail(source != NULL);
-	g_return_if_fail(name != NULL);
-
-	new_name = purple_utf8_strip_unprintables(name);
-
-	if (*new_name == '\0' || purple_strequal(new_name, source->name)) {
-		g_free(new_name);
-		return;
-	}
-
-	dest = purple_find_group(new_name);
-	if (dest != NULL && purple_utf8_strcasecmp(source->name, dest->name) != 0) {
-		/* We're merging two groups */
-		PurpleBlistNode *prev, *child, *next;
-
-		prev = purple_blist_get_last_child((PurpleBlistNode*)dest);
-		child = ((PurpleBlistNode*)source)->child;
-
-		/*
-		 * TODO: This seems like a dumb way to do this... why not just
-		 * append all children from the old group to the end of the new
-		 * one?  PRPLs might be expecting to receive an add_buddy() for
-		 * each moved buddy...
-		 */
-		while (child)
-		{
-			next = child->next;
-			if (PURPLE_IS_CONTACT(child)) {
-				PurpleBlistNode *bnode;
-				purple_blist_add_contact((PurpleContact *)child, dest, prev);
-				for (bnode = child->child; bnode != NULL; bnode = bnode->next) {
-					purple_blist_add_buddy((PurpleBuddy *)bnode, (PurpleContact *)child,
-							NULL, bnode->prev);
-					moved_buddies = g_list_append(moved_buddies, bnode);
-				}
-				prev = child;
-			} else if (PURPLE_IS_CHAT(child)) {
-				purple_blist_add_chat((PurpleChat *)child, dest, prev);
-				prev = child;
-			} else {
-				purple_debug(PURPLE_DEBUG_ERROR, "blist",
-						"Unknown child type in group %s\n", source->name);
-			}
-			child = next;
-		}
-
-		/* Make a copy of the old group name and then delete the old group */
-		old_name = g_strdup(source->name);
-		purple_blist_remove_group(source);
-		source = dest;
-		g_free(new_name);
-	} else {
-		/* A simple rename */
-		PurpleBlistNode *cnode, *bnode;
-
-		/* Build a GList of all buddies in this group */
-		for (cnode = ((PurpleBlistNode *)source)->child; cnode != NULL; cnode = cnode->next) {
-			if (PURPLE_IS_CONTACT(cnode))
-				for (bnode = cnode->child; bnode != NULL; bnode = bnode->next)
-					moved_buddies = g_list_append(moved_buddies, bnode);
-		}
-
-		old_name = source->name;
-		source->name = new_name;
-	}
-
-	/* Save our changes */
-	purple_blist_schedule_save();
-
-	/* Update the UI */
-	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode*)source);
-
-	/* Notify all PRPLs */
-	/* TODO: Is this condition needed?  Seems like it would always be TRUE */
-	if(old_name && !purple_strequal(source->name, old_name)) {
-		for (accts = purple_group_get_accounts(source); accts; accts = g_slist_remove(accts, accts->data)) {
-			PurpleAccount *account = accts->data;
-			PurpleConnection *gc = NULL;
-			PurplePlugin *prpl = NULL;
-			PurplePluginProtocolInfo *prpl_info = NULL;
-			GList *l = NULL, *buddies = NULL;
-
-			gc = purple_account_get_connection(account);
-
-			if(gc)
-				prpl = purple_connection_get_prpl(gc);
-
-			if(gc && prpl)
-				prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-			if(!prpl_info)
-				continue;
-
-			for(l = moved_buddies; l; l = l->next) {
-				PurpleBuddy *buddy = (PurpleBuddy *)l->data;
-
-				if(buddy && purple_buddy_get_account(buddy)== account)
-					buddies = g_list_append(buddies, (PurpleBlistNode *)buddy);
-			}
-
-			if(prpl_info->rename_group) {
-				prpl_info->rename_group(gc, old_name, source, buddies);
-			} else {
-				GList *cur, *groups = NULL;
-
-				/* Make a list of what the groups each buddy is in */
-				for(cur = buddies; cur; cur = cur->next) {
-					PurpleBlistNode *node = (PurpleBlistNode *)cur->data;
-					groups = g_list_prepend(groups, node->parent->parent);
-				}
-
-				purple_account_remove_buddies(account, buddies, groups);
-				g_list_free(groups);
-				purple_account_add_buddies(account, buddies);
-			}
-
-			g_list_free(buddies);
-		}
-	}
-	g_list_free(moved_buddies);
-	g_free(old_name);
-}
-
 GSList *purple_group_get_accounts(PurpleGroup *group)
 {
 	GSList *l = NULL;
@@ -227,12 +91,17 @@ static void
 }
 
 static void
-purple_group_remove_node(PurpleBlistNode *parent, PurpleBlistNode *child)
+purple_group_remove_node(PurpleBlistNode *child)
 {
-	PurpleGroup *group = PURPLE_GROUP(parent);
-	PurpleContact *contact = PURPLE_CONTACT(child);
+	PurpleGroup *group;
+	PurpleContact *contact;
 	PurpleBlistNode *itr;
 
+	g_return_if_fail(child);
+	g_return_if_fail(purple_blist_node_get_parent(child));
+	group = PURPLE_GROUP(child->parent);
+	contact = PURPLE_CONTACT(child);
+
 #warning Consider optimizing this.
 	group->totalsize = 0;
 	group->currentsize = 0;
@@ -293,7 +162,58 @@ int purple_blist_get_group_online_count(
 	return group->online;
 }
 
+GList *purple_group_get_buddies(PurpleGroup *group)
+{
+	GList *buddies = NULL;
+	PurpleBlistNode *gnode;
+	PurpleBlistNode *itr;
+
+	g_return_val_if_fail(group,NULL);
+
+	gnode = PURPLE_BLIST_NODE(group);
+	for(itr = gnode->child;itr;itr = itr->next){
+		if(PURPLE_IS_CONTACT(itr)){
+			buddies = g_list_concat(buddies, purple_contact_get_buddies(PURPLE_CONTACT(itr)));
+		}
+	}
+
+	return buddies;
+}
+
+void
+purple_group_contact_updated(PurpleGroup *group, PurpleContact *contact)
+{
+	g_return_if_fail(group);
+	g_return_if_fail(contact);
+
+	if (purple_contact_get_online(contact) > 0)
+		group->online++;
+	else
+		group->online--;
+
+	if (purple_contact_get_currentsize(contact) > 0)
+		group->currentsize++;
+	else
+		group->currentsize--;
+}
+
 static void
+purple_group_add_contact(PurpleGroup *group, PurpleContact *contact, PurpleBlistNode *node)
+{
+	g_return_if_fail(group);
+	g_return_if_fail(contact);
+
+	if (node && (PURPLE_IS_CONTACT(node) ||
+				PURPLE_IS_CHAT(node))) {
+		purple_blist_node_add_sibling_after(PURPLE_BLIST_NODE(contact), node);
+	} else {
+		purple_blist_node_add_child(PURPLE_BLIST_NODE(group), PURPLE_BLIST_NODE(contact));
+	}	
+	purple_group_contact_updated(group, contact);
+	group->totalsize++;
+}
+
+static void
 purple_group_set_name(PurpleGroup *group, const char *name)
 {
 	g_return_if_fail(group != NULL);
============================================================
--- libpurple/group.h	fe615f7839c9eb8cc6b642e5ea5330f01923249d
+++ libpurple/group.h	e76a4c2517b9f0f267cbeb33ea9aa17aafc6390a
@@ -143,6 +143,22 @@ int purple_blist_get_group_online_count(
 int purple_blist_get_group_online_count(PurpleGroup *group);
 
 /**
+ * Update the counts based on a changed online/offline status of a contact
+ *
+ * @param group The group to alter
+ * @param contact The contact that's changed
+ */
+void purple_group_contact_updated(PurpleGroup *group, PurpleContact *contact);
+
+/**
+ * Get a list of all the buddies in this group
+ *
+ * @param group The group
+ * @return a list of buddies
+ */
+GList *purple_group_get_buddies(PurpleGroup *group);
+
+/**
  * Get the GType for PurpleGroup
  */
 GType purple_group_get_type(void);


More information about the Commits mailing list