gobjectification: 1e6d3dad: Starting rearranging (and hopefully impr...

sadrul at pidgin.im sadrul at pidgin.im
Tue Jul 6 01:57:13 EDT 2010


----------------------------------------------------------------------
Revision: 1e6d3dadea74d8d1617a106115b42c10cb6a4c1d
Parent:   8bbcfe0485b9c93e124e574ddeecb5f1c19e02d2
Author:   sadrul at pidgin.im
Date:     07/05/10 23:23:44
Branch:   im.pidgin.gobjectification
URL: http://d.pidgin.im/viewmtn/revision/info/1e6d3dadea74d8d1617a106115b42c10cb6a4c1d

Changelog: 

Starting rearranging (and hopefully improving/fixing) buddylist code.

When a new group is created, it will be automatically added to the
buddylist. Likewise, when it's destroyed, the buddylist will update
itself.

Changes against parent 8bbcfe0485b9c93e124e574ddeecb5f1c19e02d2

  patched  libpurple/blist-node.c
  patched  libpurple/blist-node.h
  patched  libpurple/blist.c
  patched  libpurple/buddy.h
  patched  libpurple/group.c
  patched  libpurple/group.h

-------------- next part --------------
============================================================
--- libpurple/blist.c	60072e69e2dbf5d5fb9fa99d94afb38deffd0ed2
+++ libpurple/blist.c	8f952edc2ff49d1604c784afe08e8970215936c2
@@ -26,6 +26,7 @@
 #include "internal.h"
 #include "dbus-maybe.h"
 #include "debug.h"
+#include "gsignal.h"
 #include "server.h"
 #include "signals.h"
 #include "xmlnode.h"
@@ -49,7 +50,8 @@ struct _PurpleBuddyList {
  * The Buddy List
  */
 struct _PurpleBuddyList {
-	PurpleBlistNode node;        /**< The first node in the buddy list */
+	PurpleObject parent;
+	PurpleBlistNode *node;        /**< The first node in the buddy list */
 	GHashTable *buddies;          /**< Every buddy in this list */
 
 	/**
@@ -71,12 +73,12 @@ struct _PurpleBuddyListClass {
 };
 
 struct _PurpleBuddyListClass {
-	PurpleBlistNodeClass parent;
+	PurpleObjectClass parent;
 };
 
 static PurpleBlistUiOps *blist_ui_ops = NULL;
 
-static PurpleBlistNodeClass *parent_class = NULL;
+static PurpleObjectClass *parent_class = NULL;
 
 static void purple_blist_buddies_cache_add_account(PurpleAccount *account);
 
@@ -477,25 +479,23 @@ void purple_blist_rename_group(PurpleGro
 {
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
 	PurpleGroup *dest;
-	gchar *old_name;
+	const gchar *old_name;
 	gchar *new_name;
 	GList *moved_buddies = NULL;
 	GSList *accts;
-	char *tmp, *tmp2 = NULL, *tmp3 = NULL;
 
 	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, tmp = purple_group_get_name(source))) {
+	if (*new_name == '\0' || purple_strequal(new_name, purple_group_get_name(source))) {
 		g_free(new_name);
 		return;
 	}
-	g_free(tmp);
 
 	dest = purple_find_group(new_name);
-	if (dest != NULL && purple_utf8_strcasecmp(tmp3 = purple_group_get_name(source), tmp2 = purple_group_get_name(dest)) != 0) {
+	if (dest != NULL && purple_utf8_strcasecmp(purple_group_get_name(source), purple_group_get_name(dest)) != 0) {
 		/* We're merging two groups */
 		PurpleBlistNode *prev, *child, *next;
 
@@ -525,8 +525,7 @@ void purple_blist_rename_group(PurpleGro
 				prev = child;
 			} else {
 				purple_debug(PURPLE_DEBUG_ERROR, "blist",
-						"Unknown child type in group %s\n", tmp = purple_group_get_name(source));
-				g_free(tmp);
+						"Unknown child type in group %s\n", purple_group_get_name(source));
 			}
 			child = next;
 		}
@@ -553,10 +552,6 @@ void purple_blist_rename_group(PurpleGro
 		key = g_utf8_collate_key(new_name, -1);
 		g_hash_table_insert(list->groups_cache, key, source);
 	}
-	if(tmp2){
-		g_free(tmp2);
-		g_free(tmp3);
-	}
 
 	/* Save our changes */
 	if (ops && ops->save_node)
@@ -568,7 +563,7 @@ void purple_blist_rename_group(PurpleGro
 
 	/* Notify all PRPLs */
 	/* TODO: Is this condition needed?  Seems like it would always be TRUE */
-	if(old_name && !purple_strequal(tmp = purple_group_get_name(source), old_name)) {
+	if(old_name && !purple_strequal(purple_group_get_name(source), old_name)) {
 		for (accts = purple_group_get_accounts(source); accts; accts = g_slist_remove(accts, accts->data)) {
 			PurpleAccount *account = accts->data;
 			PurpleConnection *gc = NULL;
@@ -613,9 +608,7 @@ void purple_blist_rename_group(PurpleGro
 			g_list_free(buddies);
 		}
 	}
-	g_free(tmp);
 	g_list_free(moved_buddies);
-	g_free(old_name);
 }
 
 /*
@@ -664,113 +657,18 @@ purple_blist_node_renamed(PurpleBlistNod
 static void
 purple_blist_node_renamed(PurpleBlistNode *node, const char *old_name, const char *new_name)
 {
-	
 }
 
-static void
-purple_blist_add_group_prep(PurpleBlistNode *gnode)
-{
-	PurpleBlistUiOps *ops;
-	PurpleGroup *group;
-	PurpleBuddyList *list = PURPLE_BLIST;
-	gchar *key;
-	gchar *name;
-
-	g_return_if_fail(PURPLE_IS_GROUP(gnode));
-
-	group = PURPLE_GROUP(gnode);
-	name = purple_group_get_name(group);
-
-	ops = purple_blist_get_ui_ops();
-
-	if (purple_find_group(name)) {
-		/* This is just being moved */
-		/* It would be nice to have the client worry 
-		 * about this case, but we'll leave it in for now */
-
-		if (ops && ops->remove)
-			ops->remove(PURPLE_BLIST_NODE(group));
-
-		purple_blist_node_remove(gnode);
-	}
-	key = g_utf8_collate_key(name, -1);
-	g_hash_table_insert(list->groups_cache, key, group);
-	g_free(name);
-	g_free(key);
-}
-
-static void
-purple_blist_add_group_sibling(PurpleBlistNode *gnode, PurpleBlistNode *node)
-{
-	purple_blist_add_group_prep(gnode);
-	parent_class->add_sibling(gnode, node);
-	purple_blist_node_save(gnode);
-	purple_signal_emit(purple_blist_get_handle(), "blist-node-added", gnode);
-}
-
-static void
-purple_blist_add_group_child(PurpleBlistNode *parent, PurpleBlistNode *gnode)
-{
-	purple_blist_add_group_prep(gnode);
-	parent_class->add_child(parent, gnode);
-	purple_blist_node_save(gnode);
-	purple_signal_emit(purple_blist_get_handle(), "blist-node-added",	gnode);
-}
-
-static void
-purple_blist_remove_group(PurpleBlistNode *gnode)
-{
-	PurpleBuddyList *list = PURPLE_BLIST;
-	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
-	PurpleGroup *group;
-	GList *l;
-	gchar *key;
-	gchar *tmp;
-
-	g_return_if_fail(PURPLE_IS_GROUP(gnode));
-
-	group = PURPLE_GROUP(gnode);
-
-	key = g_utf8_collate_key(tmp = purple_group_get_name(group), -1);
-	g_hash_table_remove(list->groups_cache, key);
-	g_free(key);
-	g_free(tmp);
-
-	parent_class->remove(gnode);
-
-	/* Update the UI */
-	if (ops && ops->remove)
-		ops->remove(gnode);
-
-	if (ops && ops->remove_node)
-		ops->remove_node(gnode);
-
-	purple_signal_emit(purple_blist_get_handle(), "blist-node-removed",
-			PURPLE_BLIST_NODE(group));
-
-	/* Remove the group from all accounts that are online */
-	for (l = purple_connections_get_all(); l != NULL; l = l->next)
-	{
-		PurpleConnection *gc = (PurpleConnection *)l->data;
-
-		if (purple_connection_get_state(gc) == PURPLE_CONNECTION_STATE_CONNECTED)
-			purple_account_remove_group(purple_connection_get_account(gc), group);
-	}
-}
-
 PurpleGroup *purple_find_group(const char *name)
 {
 	PurpleBuddyList *list;
 	PurpleGroup *group;
-	gchar *key;
 
 	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
 
 	list = PURPLE_BLIST;
 
-	key = g_utf8_collate_key(name, -1);
-	group = g_hash_table_lookup(list->groups_cache, key);
-	g_free(key);
+	group = g_hash_table_lookup(list->groups_cache, name);
 
 	return group;
 }
@@ -825,7 +723,7 @@ GSList *purple_find_buddies(PurpleAccoun
 
 		hb.name = (gchar *)purple_normalize(account, name);
 		hb.account = account;
-		
+
 		node = purple_blist_node_first_child(PURPLE_BLIST_NODE(list));
 		for (; node != NULL; node = node->next) {
 			if (!node->child)
@@ -1002,7 +900,6 @@ void purple_blist_add_chat(PurpleChat *c
 	PurpleBlistNode *cnode = PURPLE_BLIST_NODE(chat);
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
 	PurpleBuddyList *list = PURPLE_BLIST;
-	gchar *tmp;
 
 	g_return_if_fail(chat != NULL);
 	g_return_if_fail(PURPLE_IS_CHAT(PURPLE_BLIST_NODE(chat)));
@@ -1012,10 +909,9 @@ void purple_blist_add_chat(PurpleChat *c
 			group = purple_group_new(_("Chats"));
 
 		/* Add group to blist if isn't already on it. Fixes #2752. */
-		if (!purple_find_group(tmp = purple_group_get_name(group))) {
+		if (!purple_find_group(purple_group_get_name(group))) {
 			purple_blist_node_add_child(PURPLE_BLIST_NODE(group), PURPLE_BLIST_NODE(list));
 		}
-		g_free(tmp);
 	} else {
 		group = PURPLE_GROUP(node->parent);
 	}
@@ -1085,7 +981,6 @@ void purple_blist_add_buddy(PurpleBuddy 
 	struct _purple_hbuddy *hb, *hb2;
 	GHashTable *account_buddies;
 	PurpleBuddyList *list = PURPLE_BLIST;
-	gchar *tmp;
 
 	g_return_if_fail(buddy != NULL);
 	g_return_if_fail(PURPLE_IS_BUDDY(PURPLE_BLIST_NODE(buddy)));
@@ -1109,10 +1004,9 @@ void purple_blist_add_buddy(PurpleBuddy 
 		if (g == NULL)
 			g = purple_group_new(_("Buddies"));
 		/* Add group to blist if isn't already on it. Fixes #2752. */
-		if (!purple_find_group(tmp = purple_group_get_name(g))) {
+		if (!purple_find_group(purple_group_get_name(g))) {
 			purple_blist_node_add_child(PURPLE_BLIST_NODE(g),PURPLE_BLIST_NODE(list));
 		}
-		g_free(tmp);
 		c = purple_contact_new();
 		purple_blist_node_add_sibling(PURPLE_BLIST_NODE(c),
 									 	purple_blist_get_last_child(PURPLE_BLIST_NODE(g)));
@@ -1453,17 +1347,38 @@ static void
 }
 
 static void
+new_group_added(PurpleGroup *group, gpointer null)
+{
+	/* A new group was created. Add it at the end of the list of groups. */
+	PurpleBuddyList *list = PURPLE_BLIST;
+	if (list->node == NULL)
+		list->node = PURPLE_BLIST_NODE(group);
+	else {
+		PurpleBlistNode *node = list->node, *next;
+		while ((next = purple_blist_node_next(node)))
+			node = next;
+		purple_blist_node_add_sibling(node, PURPLE_BLIST_NODE(group));
+	}
+
+	g_hash_table_insert(list->groups_cache, g_strdup(purple_group_get_name(group)),
+			group);
+}
+
+static void
+group_destroyed(PurpleGroup *group, gpointer null)
+{
+	PurpleBuddyList *list = PURPLE_BLIST;
+	if (list->node == PURPLE_BLIST_NODE(group))
+		list->node = purple_blist_node_next(PURPLE_BLIST_NODE(group));
+	g_hash_table_remove(list->groups_cache, purple_group_get_name(group));
+}
+
+static void
 purple_blist_class_init(PurpleBuddyListClass *klass)
 {
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 	void *handle = purple_blist_get_handle();
 
-
-	parent_class = PURPLE_BLIST_NODE_CLASS(klass);
-	parent_class->remove = purple_blist_remove_group;
-	parent_class->add_sibling = purple_blist_add_group_sibling;
-	parent_class->add_child = purple_blist_add_group_child;
-
 	parent_class = g_type_class_peek_parent(klass);
 	obj_class->finalize = purple_blist_finalize;
 
@@ -1562,10 +1477,15 @@ purple_blist_class_init(PurpleBuddyListC
 			PURPLE_CALLBACK(purple_blist_buddies_cache_remove_account),
 			NULL);
 
+#if 0
 	purple_signal_connect(purple_blist_node_get_handle(), "group-removed",
 			handle,
 			PURPLE_CALLBACK(purple_blist_remove_group),
 			NULL);
+#endif
+
+	purple_g_signal_connect(PURPLE_GROUP_TYPE, "new", G_CALLBACK(new_group_added), NULL);
+	purple_g_signal_connect(PURPLE_GROUP_TYPE, "destroying", G_CALLBACK(group_destroyed), NULL);
 }
 
 static void
@@ -1615,7 +1535,7 @@ purple_blist_get_gtype(void)
 			NULL					/* value_table		*/
 		};
 
-		type = g_type_register_static(PURPLE_BLIST_NODE_TYPE,
+		type = g_type_register_static(PURPLE_TYPE_OBJECT,
 									  "PurpleBuddyList",
 									  &info, 0);
 	}
============================================================
--- libpurple/blist-node.c	8d957029e6fb73aa918c3e8e4def6100963acbcf
+++ libpurple/blist-node.c	3d5629f1e4d8be1afb34ad94a4ab5f7d8f6fcc68
@@ -460,7 +460,7 @@ purple_blist_node_find_container(PurpleB
 		parent = purple_blist_node_parent(parent);
 	return parent;
 }
-				
+
 static void
 purple_blist_node_real_add_child(PurpleBlistNode *parent, PurpleBlistNode *child)
 {
@@ -473,32 +473,34 @@ static void
 }
 
 static void
-purple_blist_node_real_add_sibling(PurpleBlistNode *child, PurpleBlistNode *location)
+purple_blist_node_real_add_sibling(PurpleBlistNode *node, PurpleBlistNode *sibling)
 {
-	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;
+	g_return_if_fail(node);
+	g_return_if_fail(sibling);
+
+	sibling->parent = node->parent;
+	sibling->prev = node;
+	if ((sibling->next = node->next))
+		node->next->prev = sibling;
+	node->next = sibling;
 }
 
 
 static void
-purple_blist_node_real_remove(PurpleBlistNode *child)
+purple_blist_node_real_remove(PurpleBlistNode *node)
 {
 	/* Remove the node from its parent */
-	if (child->prev)
-		child->prev->next = child->next;
-	if (child->next)
-		child->next->prev = child->prev;
-	/* Is the child the first in the list? */
-	if ((child->parent != NULL) && (child->parent->child == child))
-		child->parent->child = child->next;
+	if (node->prev)
+		node->prev->next = node->next;
+	if (node->next)
+		node->next->prev = node->prev;
+	/* Is the node the first in the list? */
+	if ((node->parent != NULL) && (node->parent->child == node))
+		node->parent->child = node->next;
 
-	purple_blist_node_strip(child);
+	#warning Should node->child be removed?
+
+	purple_blist_node_strip(node);
 }
 
 static PurpleBlistNode *
@@ -579,11 +581,9 @@ purple_blist_node_remove(PurpleBlistNode
 	PurpleBlistNodeClass *klass;
 
 	g_return_if_fail(PURPLE_IS_BLIST_NODE(child));
-	if (child->parent == NULL)
-		return;
 
-	klass = PURPLE_GET_BLIST_NODE_CLASS(child->parent);
-	if(klass && klass->remove){
+	klass = PURPLE_GET_BLIST_NODE_CLASS(child);
+	if (klass && klass->remove) {
 		klass->remove(child);
 	}
 }
============================================================
--- libpurple/group.c	03ba27bae35be42a7983906555a63a9e992d31e6
+++ libpurple/group.c	3611bf43b3b35f55aaced8fbfb988f7a0269a819
@@ -113,7 +113,6 @@ purple_group_child_updated(PurpleGroup *
 	g_return_if_fail(PURPLE_IS_CONTACT(child) || PURPLE_IS_CHAT(child));
 	priv = PURPLE_GROUP_GET_PRIVATE(group);
 
-	
 	if(PURPLE_IS_CHAT(child)){
 		chat = PURPLE_CHAT(child);
 		if (purple_account_is_connected(purple_chat_get_account(chat))) {
@@ -132,107 +131,77 @@ static void
 }
 
 static void
-purple_group_add_child_helper(PurpleGroup *group, PurpleBlistNode *child)
+group_child_destroyed(PurpleBlistNode *node, PurpleGroup *group)
 {
-
-	PurpleChat *chat;
-	PurpleContact *contact;
 	PurpleGroupPrivate *priv;
-	g_return_if_fail(PURPLE_IS_GROUP(group));
-	g_return_if_fail(PURPLE_IS_CONTACT(child));
 	priv = PURPLE_GROUP_GET_PRIVATE(group);
 
-#warning: gotta be a better way than doing this over and over
-	/* Maybe when the group is created, then the children just have to emit it.
-	 * Then how will the group know if this is a child it's worried about or not?
-	 */
-	purple_signal_connect(purple_blist_node_get_handle(), "node-updated", /* What to connect to */
-		group, /* Object receiving the signal */
-		PURPLE_CALLBACK(purple_group_child_updated), /* Callback function */
-		group /* Data to pass to the callback function */
-	);
-
-	if(PURPLE_IS_CHAT(child)){
-		chat = PURPLE_CHAT(child);
-		if (purple_account_is_connected(purple_chat_get_account(chat))) {
-			priv->online++;
-			priv->currentsize++;
+	if (PURPLE_IS_CHAT(node)) {
+		PurpleChat *chat = PURPLE_CHAT(node);
+		PurpleAccount *account = purple_chat_get_account(chat);
+		if (purple_account_is_connected(account)) {
+			priv->online--;
+			priv->currentsize--;
 		}
-	} else if(PURPLE_IS_CONTACT(child)){
-		contact = PURPLE_CONTACT(child);
-		if(purple_contact_get_online(contact) > 0)
-			priv->online++;
-		if(purple_contact_get_currentsize(contact) > 0)
-			priv->currentsize++;
+	} else if (PURPLE_IS_CONTACT(node)) {
+		PurpleContact *contact = PURPLE_CONTACT(node);
+		if (purple_contact_get_online(contact) > 0)
+			priv->online--;
+		if (purple_contact_get_currentsize(contact) > 0)
+			priv->currentsize--;
 	} else {
-		#warning: is this an ok case?
-		g_warn_if_reached();
+		purple_debug_error("group", "Notified of a destruction of unknown blist-node.\n");
 	}
-	priv->totalsize++;
-
-	#warning Is this schedule save necessary?
-	purple_blist_schedule_save();
-	purple_signal_emit(purple_blist_node_get_handle(), "node-added", child);
-
 }
 
 static void
-purple_group_add_sibling(PurpleBlistNode *node, PurpleBlistNode *location)
+purple_group_add_child(PurpleBlistNode *parent, PurpleBlistNode *child)
 {
-	g_return_if_fail(PURPLE_IS_CONTACT(node) || PURPLE_IS_CHAT(node));
-	g_return_if_fail(PURPLE_IS_CONTACT(location) || PURPLE_IS_CHAT(location));
-	g_return_if_fail(PURPLE_IS_GROUP(purple_blist_node_parent(location)));
-	
-	purple_group_add_child_helper(PURPLE_GROUP(purple_blist_node_parent(location)), node);
+	PurpleGroupPrivate *priv;
+	PurpleGroup *group;
 
-	parent_class->add_sibling(node, location);
-}
-
-static void
-purple_group_add_child(PurpleBlistNode *parent, PurpleBlistNode *child)
-{
 	g_return_if_fail(PURPLE_IS_GROUP(parent));
 	g_return_if_fail(child);
 
-	purple_group_add_child_helper(PURPLE_GROUP(parent), child);
+	group = PURPLE_GROUP(parent);
+	priv = PURPLE_GROUP_GET_PRIVATE(group);
 
-	parent_class->add_child(parent, child);
-}
+	if (PURPLE_IS_BUDDY(child)) {
+		/* TODO: Create a PurpleContact with 'child', then add the contact. */
+	}
 
-static void
-purple_group_remove_node(PurpleBlistNode *child)
-{
-	PurpleContact *contact;
-	PurpleChat *chat;
-	PurpleGroupPrivate *priv;
-	g_return_if_fail(PURPLE_IS_CONTACT(child) || PURPLE_IS_CHAT(child));
-	g_return_if_fail(PURPLE_IS_GROUP(purple_blist_node_parent(child)));
-
-	priv = PURPLE_GROUP_GET_PRIVATE(purple_blist_node_parent(child));
-
-	if(PURPLE_IS_CHAT(child)){
-		chat = PURPLE_CHAT(child);
-		if (purple_account_is_connected(purple_chat_get_account(chat))) {
-			priv->online--;
-			priv->currentsize--;
+	if (PURPLE_IS_CHAT(child)) {
+		PurpleChat *chat = PURPLE_CHAT(child);
+		PurpleAccount *account = purple_chat_get_account(chat);
+		if (purple_account_is_connected(account)) {
+			priv->online++;
+			priv->currentsize++;
 		}
-	} else if(PURPLE_IS_CONTACT(child)){
-		contact = PURPLE_CONTACT(child);
-		if(purple_contact_get_online(contact) > 0)
-			priv->online--;
-		if(purple_contact_get_currentsize(contact) > 0)
-			priv->currentsize--;
+	} else if (PURPLE_IS_CONTACT(child)) {
+		PurpleContact *contact = PURPLE_CONTACT(child);
+		if (purple_contact_get_online(contact) > 0)
+			priv->online++;
+		if (purple_contact_get_currentsize(contact) > 0)
+			priv->currentsize++;
 	} else {
-		#warning: Is this an ok case?
-		g_warn_if_reached();
+		purple_debug_error("group", "Adding unknown node to group '%s'\n", priv->name);
+		return;
 	}
-	priv->totalsize--;
 
-	parent_class->remove(child);
+	/* Make sure we update the group when the child is:
+	 *	- destroyed
+	 *	- updated (TODO)
+	 */
+	g_signal_connect(G_OBJECT(child), "destroying", G_CALLBACK(group_child_destroyed), group);
 
+	parent_class->add_child(parent, child);
+}
+
+static void
+purple_group_remove_node(PurpleBlistNode *node)
+{
+	parent_class->remove(node);
 	purple_blist_schedule_save();
-
-	purple_signal_emit(purple_blist_node_get_handle(), "node-removed", child);
 }
 
 void
@@ -243,14 +212,14 @@ purple_group_destroy(PurpleGroup *group)
 	g_object_unref(G_OBJECT(group));
 }
 
-char *
+const char *
 purple_group_get_name(const PurpleGroup *group)
 {
 	PurpleGroupPrivate *priv;
 	g_return_val_if_fail(PURPLE_IS_GROUP(group), NULL);
 	priv = PURPLE_GROUP_GET_PRIVATE(group);
 
-	return strdup(priv->name);
+	return priv->name;
 }
 
 int purple_group_get_size(const PurpleGroup *group, gboolean offline)
@@ -262,7 +231,7 @@ int purple_group_get_size(const PurpleGr
 	return offline ? priv->totalsize : priv->currentsize;
 }
 
-void 
+void
 purple_group_set_online(PurpleGroup *group, int online)
 {
 	PurpleGroupPrivate *priv;
@@ -310,9 +279,19 @@ purple_group_set_name(PurpleGroup *group
 purple_group_set_name(PurpleGroup *group, const char *name)
 {
 	PurpleGroupPrivate *priv;
+	char *gname;
+
 	g_return_if_fail(group != NULL);
+
 	priv = PURPLE_GROUP_GET_PRIVATE(group);
-	priv->name = purple_utf8_strip_unprintables(name);
+	gname = purple_utf8_strip_unprintables(name);
+
+	if (purple_util_strings_equal(gname, priv->name))
+		g_free(gname);
+	else {
+		g_free(priv->name);
+		priv->name = gname;
+	}
 }
 
 /******************/
@@ -338,9 +317,13 @@ PurpleGroup *purple_group_new(const char
 	if (group != NULL)
 		 return group;
 
-	return g_object_new(	PURPLE_GROUP_TYPE, 
-												PROP_NAME_S, name, 
-												NULL);
+	group = g_object_new(PURPLE_GROUP_TYPE,
+			PROP_NAME_S, name,
+			NULL);
+
+	g_signal_emit_by_name(G_OBJECT(group), "new");
+
+	return group;
 }
 
 
@@ -384,6 +367,29 @@ purple_group_get_property(GObject *obj, 
 	}
 }
 
+#if 0
+static GObject *
+purple_group_constructor(GType type, guint n_props, GObjectConstructParam *props)
+{
+	PurpleGroup *group = NULL;
+	int i;
+
+	for (i = 0; i < n_props; i++) {
+		GObjectConstructParam *p = props + i;
+		const char *pname = g_param_spec_get_name(p->pspec);
+		if (pname && !strcmp(pname, PROP_NAME_S)) {
+			const char *name = g_value_get_string(p->value);
+			group = purple_find_group(name);
+			break;
+		}
+	}
+
+	if (group)
+		return group;
+	return G_OBJECT_CLASS(parent_class)->constructor(type, n_props, props);
+}
+#endif
+
 static void
 purple_group_class_init(PurpleGroupClass *klass)
 {
@@ -392,12 +398,14 @@ purple_group_class_init(PurpleGroupClass
 	g_type_class_add_private(klass, sizeof(PurpleGroupPrivate));
 
 	parent_class = PURPLE_BLIST_NODE_CLASS(klass);
-	parent_class->add_sibling = purple_group_add_sibling;
 	parent_class->add_child = purple_group_add_child;
 	parent_class->remove = purple_group_remove_node;
 
 	parent_class = g_type_class_peek_parent(klass);
 
+#if 0
+	obj_class->constructor = purple_group_constructor;
+#endif
 	obj_class->finalize = purple_group_finalize;
 	obj_class->set_property = purple_group_set_property;
 	obj_class->get_property = purple_group_get_property;
@@ -405,7 +413,7 @@ purple_group_class_init(PurpleGroupClass
 	g_object_class_install_property(obj_class, PROP_NAME,
 			g_param_spec_string(PROP_NAME_S, _("Name"),
 				_("The name for the group."), NULL,
-				G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)
+				G_PARAM_READWRITE)
 			);
 }
 
============================================================
--- libpurple/blist-node.h	f7dff5b4c076c14cfdaf95f0267916f7d78db6bb
+++ libpurple/blist-node.h	589f1a53393c3a8a3d94a2bea1590b5eeaf2b226
@@ -77,9 +77,9 @@ struct _PurpleBlistNodeClass {
 struct _PurpleBlistNodeClass {
 	PurpleObjectClass _parent;
 
-	void (*add_sibling)(PurpleBlistNode *child, PurpleBlistNode *location);
+	void (*add_sibling)(PurpleBlistNode *node, PurpleBlistNode *sibling);
 	void (*add_child)(PurpleBlistNode *parent, PurpleBlistNode *child);
-	void (*remove)(PurpleBlistNode *child);
+	void (*remove)(PurpleBlistNode *node);
 	PurpleBlistNode *(*first_child)(PurpleBlistNode *parent);
 	PurpleBlistNode *(*parent)(PurpleBlistNode *child);
 	PurpleBlistNode *(*next)(PurpleBlistNode *node);
@@ -183,12 +183,12 @@ void purple_blist_node_add_child(PurpleB
 void purple_blist_node_add_child(PurpleBlistNode *parent, PurpleBlistNode *child);
 
 /**
- * Add a node before a given node.
+ * Add a node after a given node.
  *
- * @param node The node to add
- * @param location The node to insert before, not NULL
+ * @param node The node to add a sibling to.
+ * @param sibling The sibling to add.
  */
-void purple_blist_node_add_sibling(PurpleBlistNode *node, PurpleBlistNode *location);
+void purple_blist_node_add_sibling(PurpleBlistNode *node, PurpleBlistNode *sibling);
 
 /**
  * Remove a node from its parent
============================================================
--- libpurple/buddy.h	6729830918de6ce3b5d4ce3d89b0b129e22bf5e3
+++ libpurple/buddy.h	f36d8ab3cd982c74dcb898dc0b05d4c490a9f8ea
@@ -51,7 +51,7 @@ struct _PurpleBuddy {
  */
 struct _PurpleBuddy {
 	PurpleBlistNode node;                     /**< The node that this buddy inherits from */
-	PurpleBuddyPrivate *priv;               /**< The private members */
+	PurpleBuddyPrivate *priv;
 };
 
 struct _PurpleBuddyClass {
============================================================
--- libpurple/group.h	bf4f8e9c94260fc911781aff457a67aebe353c0a
+++ libpurple/group.h	bf009625fefa170a2a25f8894be60cd9936eaeec
@@ -113,7 +113,7 @@ void purple_group_set_name(PurpleGroup *
  *
  * @return The a copy of the group name, caller is responsible for freeing it
  */
-char *purple_group_get_name(const PurpleGroup *group);
+const char *purple_group_get_name(const PurpleGroup *group);
 
 /**
  * Determines the total size of a group


More information about the Commits mailing list