gobjectification: c17e26fc: Made the buddylist a PBNode. Did some n...

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


-----------------------------------------------------------------
Revision: c17e26fc622e75a7575bd83bc42422efad88aaf4
Ancestor: d24df4629a2e97deead4b96026c115b693d0e4ac
Author: aluink at soc.pidgin.im
Date: 2009-07-15T06:27:39
Branch: im.pidgin.gobjectification
URL: http://d.pidgin.im/viewmtn/revision/info/c17e26fc622e75a7575bd83bc42422efad88aaf4

Modified files:
        libpurple/blist-node.c libpurple/blist-node.h
        libpurple/blist.c libpurple/blist.h libpurple/buddy.c
        libpurple/chat.c libpurple/contact.c libpurple/group.c
        libpurple/group.h libpurple/protocols/bonjour/bonjour.c
        libpurple/protocols/myspace/myspace.c libpurple/status.c

ChangeLog: 

Made the buddylist a PBNode.  Did some naming clean up. More work on splitting blist

-------------- next part --------------
============================================================
--- libpurple/blist-node.c	8ae1698388babe08a9b9278e9a2bd146980f3444
+++ libpurple/blist-node.c	bcea2509ef5bb2d8c6260c4eef69dedce8c2e068
@@ -163,7 +163,7 @@ purple_blist_update_node_icon(PurpleBlis
 	g_return_if_fail(node != NULL);
 
 	if (ops && ops->update)
-		ops->update(purplebuddylist, node);
+		ops->update(purple_blist_get_list(), node);
 }
 
 
@@ -448,20 +448,9 @@ void
 }
 
 void
-purple_blist_node_add_sibling_before(PurpleBlistNode *child, PurpleBlistNode *location)
+purple_blist_node_add_sibling(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;
@@ -471,8 +460,8 @@ purple_blist_node_add_sibling_after(Purp
 	location->next = child;
 }
 
-void
-purple_blist_node_remove(PurpleBlistNode *child)
+static void
+purple_blist_node_cls_remove(PurpleBlistNode *child)
 {
 	/* Remove the node from its parent */
 	if (child->prev)
@@ -487,6 +476,19 @@ void
 }
 
 void
+purple_blist_node_remove(PurpleBlistNode *child)
+{
+	PurpleBlistNodeClass *klass;
+
+	g_return_if_fail(PURPLE_IS_BLIST_NODE(child));
+
+	klass = PURPLE_GET_BLIST_NODE_CLASS(child->parent);
+	if(klass && klass->remove){
+		klass->remove(child);
+	}
+}
+
+void
 purple_blist_node_strip(PurpleBlistNode *node)
 {
 	g_return_if_fail(node);
@@ -496,7 +498,7 @@ purple_blist_node_is_empty(PurpleBlistNo
 gboolean
 purple_blist_node_is_empty(PurpleBlistNode *node)
 {
-	return node->child;
+	return node->child != NULL;
 }
 
 /******************/
@@ -529,18 +531,6 @@ purple_blist_node_finalize(GObject *obje
 
 	g_hash_table_destroy(priv->settings);
 
-	if (ui_ops && ui_ops->remove)
-		ui_ops->remove(purplebuddylist, node);
-
-	if (PURPLE_IS_BUDDY(node))
-		g_object_unref(node);
-	else if (PURPLE_IS_CHAT(node))
-		g_object_unref(node);
-	else if (PURPLE_IS_CONTACT(node))
-		g_object_unref(node);
-	else if (PURPLE_IS_GROUP(node))
-		g_object_unref(node);
-
 	parent_class->finalize(object);
 }
 
@@ -561,10 +551,18 @@ purple_blist_node_class_init(PurpleBlist
 
 	g_type_class_add_private(klass, sizeof(PurpleBlistNodePrivate));
 
-	klass->add_node = purple_blist_node_add_child;
-	klass->remove_node = purple_blist_node_remove;
+	klass->add_child = purple_blist_node_add_child;
+	klass->add_sibling = purple_blist_node_add_sibling;
+	klass->remove = purple_blist_node_cls_remove;
 
 	purple_signal_register( purple_blist_node_handle(),
+													"group-removed",
+													purple_marshal_VOID__POINTER,
+													NULL,
+													1,
+													purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_BLIST_GROUP));
+
+	purple_signal_register( purple_blist_node_handle(),
 													"node-updated",
 													purple_marshal_VOID__POINTER,
 													NULL,
@@ -606,3 +604,10 @@ purple_blist_node_get_gtype(void)
 
 	return type;
 }
+
+void *
+purple_blist_node_get_handle()
+{
+	static int handle;
+	return &handle;
+}
============================================================
--- libpurple/blist-node.h	3dc8b5ca3676ad0f0001783f85d7423b28a0b3be
+++ libpurple/blist-node.h	19aa20eb3e8976efc482b2767b9947b3d1b12977
@@ -50,6 +50,7 @@ typedef struct _PurpleBlistNodeClass Pur
 typedef struct _PurpleBlistNode PurpleBlistNode;
 typedef struct _PurpleBlistNodePrivate PurpleBlistNodePrivate;
 typedef struct _PurpleBlistNodeClass PurpleBlistNodeClass;
+
 #define PURPLE_BLIST_NODE_TYPE                  (purple_blist_node_get_gtype ())
 #define PURPLE_BLIST_NODE(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), PURPLE_BLIST_NODE_TYPE, PurpleBlistNode))
 #define PURPLE_IS_BLIST_NODE(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PURPLE_BLIST_NODE_TYPE))
@@ -76,8 +77,9 @@ struct _PurpleBlistNodeClass {
 struct _PurpleBlistNodeClass {
 	PurpleObjectClass parent;
 
-	void (*add_node)(PurpleBlistNode *parent, PurpleBlistNode *child, PurpleBlistNode *location);
-	void (*remove_node)(PurpleBlistNode *child);
+	void (*add_sibling)(PurpleBlistNode *child, PurpleBlistNode *location);
+	void (*add_child)(PurpleBlistNode *parent, PurpleBlistNode *child);
+	void (*remove)(PurpleBlistNode *child);
 
 	void (*purple_reserved1)(void);
 	void (*purple_reserved2)(void);
@@ -174,17 +176,9 @@ void purple_blist_node_add_child(PurpleB
  * @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);
+void purple_blist_node_add_sibling(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
@@ -320,6 +314,13 @@ void purple_blist_node_set_flags(PurpleB
 void purple_blist_node_set_flags(PurpleBlistNode *node, PurpleBlistNodeFlags flags);
 
 /**
+ * Get the blist-node handle
+ *
+ * @return the handle
+ */
+void *purple_blist_node_get_handle(void);
+
+/**
  * Get the current flags on a given node.
  *
  * @param node The node from which to get the flags.
============================================================
--- libpurple/blist.c	485859afe51764381515ff705ba07f6ae0158558
+++ libpurple/blist.c	d656a32ad237d7f22d7b510a884a6897e677de4f
@@ -46,8 +46,7 @@ struct _PurpleBuddyList {
  * The Buddy List
  */
 struct _PurpleBuddyList {
-PurpleObject parent;
-	PurpleBlistNode *root;        /**< The first node in the buddy list */
+	PurpleBlistNode node;        /**< The first node in the buddy list */
 	GHashTable *buddies;          /**< Every buddy in this list */
 	
 	/**
@@ -68,9 +67,9 @@ static PurpleBlistUiOps *blist_ui_ops = 
 
 static PurpleBlistUiOps *blist_ui_ops = NULL;
 
-PurpleBuddyList *purplebuddylist = NULL;
-static GObjectClass *parent_class = NULL;
+static PurpleBlistNodeClass *parent_class = NULL;
 
+static void purple_blist_buddies_cache_add_account(PurpleAccount *account);
 
 /*********************************************************************
  * Private utility functions                                         *
@@ -98,13 +97,13 @@ purple_blist_buddies_cache_add_account(P
 	GHashTable *account_buddies = g_hash_table_new_full((GHashFunc)_purple_blist_hbuddy_hash,
 						(GEqualFunc)_purple_blist_hbuddy_equal,
 						(GDestroyNotify)_purple_blist_hbuddy_free_key, NULL);
-	g_hash_table_insert(purplebuddylist->buddies_cache, account, account_buddies);
+	g_hash_table_insert(purple_blist_get_list()->buddies_cache, account, account_buddies);
 }
 
 static void
 purple_blist_buddies_cache_remove_account(const PurpleAccount *account)
 {
-	g_hash_table_remove(purplebuddylist->buddies_cache, account);
+	g_hash_table_remove(purple_blist_get_list()->buddies_cache, account);
 }
 
 /*********************************************************************
@@ -194,7 +193,7 @@ blist_to_xmlnode(void)
 
 	/* Write groups */
 	child = xmlnode_new_child(node, "blist");
-	for (gnode = purplebuddylist->root; gnode != NULL; gnode = gnode->next)
+	for (gnode = purple_blist_node_get_first_child(PURPLE_BLIST_NODE(purple_blist_get_list())); gnode != NULL; gnode = gnode->next)
 	{
 		if (!PURPLE_BLIST_NODE_SHOULD_SAVE(gnode))
 			continue;
@@ -222,7 +221,7 @@ purple_blist_sync(void)
 	xmlnode *node;
 	char *data;
 
-	if (!purplebuddylist->blist_loaded)
+	if (!purple_blist_get_list()->blist_loaded)
 	{
 		purple_debug_error("blist", "Attempted to save buddy list before it "
 						 "was read!\n");
@@ -240,15 +239,15 @@ save_cb(gpointer data)
 save_cb(gpointer data)
 {
 	purple_blist_sync();
-	purplebuddylist->save_timer = 0;
+	purple_blist_get_list()->save_timer = 0;
 	return FALSE;
 }
 
 void
 purple_blist_schedule_save()
 {
-	if (purplebuddylist && purplebuddylist->save_timer == 0)
-		purplebuddylist->save_timer = purple_timeout_add_seconds(5, save_cb, NULL);
+	if (purple_blist_get_list()->save_timer == 0)
+		purple_blist_get_list()->save_timer = purple_timeout_add_seconds(5, save_cb, NULL);
 }
 
 
@@ -268,7 +267,7 @@ parse_group(xmlnode *groupnode)
 
 	group = purple_group_new(name);
 	purple_blist_add_group(group,
-	purple_blist_get_last_sibling(purplebuddylist->root));
+	purple_blist_node_get_first_child(PURPLE_BLIST_NODE(purple_blist_get_list())));
 
 	for (cnode = groupnode->child; cnode; cnode = cnode->next) {
 		if (cnode->type != XMLNODE_TYPE_TAG)
@@ -289,7 +288,7 @@ purple_blist_load()
 {
 	xmlnode *purple, *blist, *privacy;
 
-	purplebuddylist->blist_loaded = TRUE;
+	purple_blist_get_list()->blist_loaded = TRUE;
 
 	purple = purple_util_read_xml_from_file("blist.xml", _("buddy list"));
 
@@ -360,27 +359,39 @@ PurpleBuddyList *
  *****************************************************************************/
 
 PurpleBuddyList *
-purple_get_blist()
+purple_blist_get_list()
 {
-	return purplebuddylist;
+	static PurpleBuddyList *list = NULL;
+	if(!list){
+		GList *account;
+		PurpleBlistUiOps *ui_ops = purple_blist_get_ui_ops();
+		list = g_object_new(PURPLE_BUDDY_LIST_TYPE, NULL);
+		for (account = purple_accounts_get_all(); account != NULL; account = account->next)	{
+			purple_blist_buddies_cache_add_account(account->data);
+		}
+
+		if (ui_ops != NULL && ui_ops->new_list != NULL)
+			ui_ops->new_list(list);
+	}
+	return list;
 }
 
 PurpleBlistNode *
 purple_blist_get_root()
 {
-	return purplebuddylist ? purplebuddylist->root : NULL;
+	return PURPLE_BLIST_NODE(purple_blist_get_list());
 }
 
 void *
 purple_blist_get_ui_data()
 {
-	return purplebuddylist->ui_data;
+	return purple_blist_get_list()->ui_data;
 }
 
 void
 purple_blist_set_ui_data(void *ui_data)
 {
-	purplebuddylist->ui_data = ui_data;
+	purple_blist_get_list()->ui_data = ui_data;
 }
 
 void purple_blist_show()
@@ -388,14 +399,14 @@ void purple_blist_show()
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
 
 	if (ops && ops->show)
-		ops->show(purplebuddylist);
+		ops->show(purple_blist_get_list());
 }
 
 void purple_blist_destroy()
 {
 	/* This function is only a hack for api breakage */
-	g_return_if_fail(purplebuddylist != NULL);
-	g_object_unref(G_OBJECT(purplebuddylist));
+	g_return_if_fail(purple_blist_get_list() != NULL);
+	g_object_unref(G_OBJECT(purple_blist_get_list()));
 }
 
 void purple_blist_set_visible(gboolean show)
@@ -403,7 +414,7 @@ void purple_blist_set_visible(gboolean s
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
 
 	if (ops && ops->set_visible)
-		ops->set_visible(purplebuddylist, show);
+		ops->set_visible(purple_blist_get_list(), show);
 }
 
 
@@ -474,7 +485,7 @@ void purple_blist_rename_group(PurpleGro
 
 		/* 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);
+		purple_blist_node_remove(PURPLE_BLIST_NODE(source));
 		source = dest;
 		g_free(new_name);
 	} else {
@@ -490,7 +501,7 @@ void purple_blist_rename_group(PurpleGro
 
 	/* Update the UI */
 	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode*)source);
+		ops->update(purple_blist_get_list(), (PurpleBlistNode*)source);
 
 	/* Notify all PRPLs */
 	/* TODO: Is this condition needed?  Seems like it would always be TRUE */
@@ -559,14 +570,14 @@ void purple_blist_rename_buddy(PurpleBud
 	hb->name = g_strdup(purple_normalize(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)));
 	hb->account = purple_buddy_get_account(buddy);
 	hb->group = ((PurpleBlistNode *)buddy)->parent->parent;
-	g_hash_table_remove(purplebuddylist->buddies, hb);
+	g_hash_table_remove(purple_blist_get_list()->buddies, hb);
 	
-	account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, purple_buddy_get_account(buddy));
+	account_buddies = g_hash_table_lookup(purple_blist_get_list()->buddies_cache, purple_buddy_get_account(buddy));
 	g_hash_table_remove(account_buddies, hb);
 
 	g_free(hb->name);
 	hb->name = g_strdup(purple_normalize(purple_buddy_get_account(buddy), name));
-	g_hash_table_replace(purplebuddylist->buddies, hb, buddy);
+	g_hash_table_replace(purple_blist_get_list()->buddies, hb, buddy);
 
 	hb2 = g_new(struct _purple_hbuddy, 1);
 	hb2->name = g_strdup(hb->name);
@@ -580,7 +591,7 @@ void purple_blist_rename_buddy(PurpleBud
 	purple_blist_schedule_save();
 
 	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
+		ops->update(purple_blist_get_list(), (PurpleBlistNode *)buddy);
 }
 
 void purple_blist_add_contact(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node)
@@ -605,7 +616,7 @@ void purple_blist_add_contact(PurpleCont
 		if (g == NULL) {
 			g = purple_group_new(_("Buddies"));
 			purple_blist_add_group(g,
-					purple_blist_get_last_sibling(purplebuddylist->root));
+					purple_blist_node_get_first_child(PURPLE_BLIST_NODE(purple_blist_get_list())));
 		}
 	}
 
@@ -633,15 +644,15 @@ void purple_blist_add_contact(PurpleCont
 				hb->account = purple_buddy_get_account(b);
 				hb->group = cnode->parent;
 
-				g_hash_table_remove(purplebuddylist->buddies, hb);
+				g_hash_table_remove(purple_blist_get_list()->buddies, hb);
 
-				account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, purple_buddy_get_account(b));
+				account_buddies = g_hash_table_lookup(purple_blist_get_list()->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);
+					g_hash_table_replace(purple_blist_get_list()->buddies, hb, b);
 
 					hb2 = g_new(struct _purple_hbuddy, 1);
 					hb2->name = g_strdup(hb->name);
@@ -684,7 +695,7 @@ void purple_blist_add_contact(PurpleCont
 		PURPLE_GROUP(cnode->parent)->totalsize--;
 
 		if (ops && ops->remove)
-			ops->remove(purplebuddylist, cnode);
+			ops->remove(purple_blist_get_list(), cnode);
 
 		purple_blist_schedule_save();
 	}
@@ -697,10 +708,10 @@ void purple_blist_add_contact(PurpleCont
 	if (ops && ops->update)
 	{
 		if (cnode->child)
-			ops->update(purplebuddylist, cnode);
+			ops->update(purple_blist_get_list(), cnode);
 
 		for (bnode = cnode->child; bnode; bnode = bnode->next)
-			ops->update(purplebuddylist, bnode);
+			ops->update(purple_blist_get_list(), bnode);
 	}
 }
 
@@ -732,11 +743,6 @@ void purple_blist_add_group(PurpleGroup 
 
 	ops = purple_blist_get_ui_ops();
 
-	if (!purplebuddylist->root) {
-		purplebuddylist->root = gnode;
-		return;
-	}
-
 	/* if we're moving to overtop of ourselves, do nothing */
 	if (gnode == node)
 		return;
@@ -745,32 +751,24 @@ void purple_blist_add_group(PurpleGroup 
 		/* This is just being moved */
 
 		if (ops && ops->remove)
-			ops->remove(purplebuddylist, (PurpleBlistNode *)group);
+			ops->remove(purple_blist_get_list(), (PurpleBlistNode *)group);
 
-		if (gnode == purplebuddylist->root)
-			purplebuddylist->root = gnode->next;
 		purple_blist_node_remove(gnode);
 	}
 
 	if (node) {
 		node = PURPLE_BLIST_NODE(purple_blist_get_containing_group(node));
-		purple_blist_node_add_sibling_after(gnode, node);
+		purple_blist_node_add_sibling(gnode, node);
 	} else {
-		if (purplebuddylist->root) {
-			purple_blist_node_add_sibling_before(gnode, purplebuddylist->root);
-		}
-		else {
-			purple_blist_node_strip(gnode);
-			purplebuddylist->root = gnode;
-		}
+		purple_blist_node_add_child(PURPLE_BLIST_NODE(purple_blist_get_list()), gnode);
 	}
 
 	purple_blist_schedule_save();
 
 	if (ops && ops->update) {
-		ops->update(purplebuddylist, gnode);
+		ops->update(purple_blist_get_list(), gnode);
 		for (node = gnode->child; node; node = node->next)
-			ops->update(purplebuddylist, node);
+			ops->update(purple_blist_get_list(), node);
 	}
 
 	purple_signal_emit(purple_blist_get_handle(), "blist-node-added",
@@ -810,7 +808,7 @@ void purple_blist_remove_contact(PurpleC
 
 		/* Update the UI */
 		if (ops && ops->remove)
-			ops->remove(purplebuddylist, node);
+			ops->remove(purple_blist_get_list(), node);
 
 		purple_signal_emit(purple_blist_get_handle(), "blist-node-removed",
 				PURPLE_BLIST_NODE(contact));
@@ -841,16 +839,16 @@ void purple_blist_remove_buddy(PurpleBud
 	hb.name = g_strdup(purple_normalize(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)));
 	hb.account = purple_buddy_get_account(buddy);
 	hb.group = gnode;
-	g_hash_table_remove(purplebuddylist->buddies, &hb);
+	g_hash_table_remove(purple_blist_get_list()->buddies, &hb);
 
-	account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, purple_buddy_get_account(buddy));
+	account_buddies = g_hash_table_lookup(purple_blist_get_list()->buddies_cache, purple_buddy_get_account(buddy));
 	g_hash_table_remove(account_buddies, &hb);
 
 	g_free(hb.name);
 
 	/* Update the UI */
 	if (ops && ops->remove)
-		ops->remove(purplebuddylist, node);
+		ops->remove(purple_blist_get_list(), node);
 
 	/* Signal that the buddy has been removed before freeing the memory for it */
 	purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy);
@@ -890,7 +888,7 @@ void purple_blist_remove_chat(PurpleChat
 
 	/* Update the UI */
 	if (ops && ops->remove)
-		ops->remove(purplebuddylist, node);
+		ops->remove(purple_blist_get_list(), node);
 
 	purple_signal_emit(purple_blist_get_handle(), "blist-node-removed",
 			PURPLE_BLIST_NODE(chat));
@@ -899,7 +897,8 @@ void purple_blist_remove_chat(PurpleChat
 	purple_chat_destroy(chat);
 }
 
-void purple_blist_remove_group(PurpleGroup *group)
+static void
+purple_blist_remove_group(PurpleGroup *group)
 {
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
 	PurpleBlistNode *node;
@@ -909,18 +908,12 @@ void purple_blist_remove_group(PurpleGro
 
 	node = (PurpleBlistNode *)group;
 
-	/* Make sure the group is empty */
-	if (purple_blist_node_is_empty(node))
+	if (purple_blist_node_is_empty(PURPLE_BLIST_NODE(group)))
 		return;
 
-	/* Remove the node from its parent */
-	purple_blist_node_remove(node);
-
-	purple_blist_schedule_save();
-
 	/* Update the UI */
 	if (ops && ops->remove)
-		ops->remove(purplebuddylist, node);
+		ops->remove(purple_blist_get_list(), node);
 
 	purple_signal_emit(purple_blist_get_handle(), "blist-node-removed",
 			PURPLE_BLIST_NODE(group));
@@ -933,19 +926,15 @@ void purple_blist_remove_group(PurpleGro
 		if (purple_connection_get_state(gc) == PURPLE_CONNECTION_STATE_CONNECTED)
 			purple_account_remove_group(purple_connection_get_account(gc), group);
 	}
-
-	/* Delete the node */
-	purple_group_destroy(group);
 }
 
 PurpleGroup *purple_find_group(const char *name)
 {
 	PurpleBlistNode *node;
 
-	g_return_val_if_fail(purplebuddylist != NULL, NULL);
 	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
 
-	for (node = purplebuddylist->root; node != NULL; node = node->next) {
+	for (node = purple_blist_node_get_first_child(PURPLE_BLIST_NODE(purple_blist_get_list())); node != NULL; node = node->next) {
 		if (!purple_utf8_strcasecmp(((PurpleGroup *)node)->name, name))
 			return (PurpleGroup *)node;
 	}
@@ -959,16 +948,16 @@ PurpleBuddy *purple_find_buddy(PurpleAcc
 	struct _purple_hbuddy hb;
 	PurpleBlistNode *group;
 
-	g_return_val_if_fail(purplebuddylist != NULL, NULL);
+	g_return_val_if_fail(purple_blist_get_list() != NULL, NULL);
 	g_return_val_if_fail(account != NULL, NULL);
 	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
 
 	hb.account = account;
 	hb.name = g_strdup(purple_normalize(account, name));
 
-	for (group = purplebuddylist->root; group; group = group->next) {
+	for (group = purple_blist_node_get_first_child(PURPLE_BLIST_NODE(purple_blist_get_list())); group; group = group->next) {
 		hb.group = group;
-		if ((buddy = g_hash_table_lookup(purplebuddylist->buddies, &hb))) {
+		if ((buddy = g_hash_table_lookup(purple_blist_get_list()->buddies, &hb))) {
 			g_free(hb.name);
 			return buddy;
 		}
@@ -992,7 +981,6 @@ GSList *purple_find_buddies(PurpleAccoun
 	PurpleBlistNode *node;
 	GSList *ret = NULL;
 
-	g_return_val_if_fail(purplebuddylist != NULL, NULL);
 	g_return_val_if_fail(account != NULL, NULL);
 
 	if ((name != NULL) && (*name != '\0')) {
@@ -1001,15 +989,15 @@ GSList *purple_find_buddies(PurpleAccoun
 		hb.name = g_strdup(purple_normalize(account, name));
 		hb.account = account;
 
-		for (node = purplebuddylist->root; node != NULL; node = node->next) {
+		for (node = purple_blist_node_get_first_child(PURPLE_BLIST_NODE(purple_blist_get_list())); node != NULL; node = node->next) {
 			hb.group = node;
-			if ((buddy = g_hash_table_lookup(purplebuddylist->buddies, &hb)) != NULL)
+			if ((buddy = g_hash_table_lookup(purple_blist_get_list()->buddies, &hb)) != NULL)
 				ret = g_slist_prepend(ret, buddy);
 		}
 		g_free(hb.name);
 	} else {
 		GSList *list = NULL;
-		GHashTable *buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, account);
+		GHashTable *buddies = g_hash_table_lookup(purple_blist_get_list()->buddies_cache, account);
 		g_hash_table_foreach(buddies, find_acct_buddies, &list);
 		ret = list;
 	}
@@ -1022,12 +1010,11 @@ void purple_blist_add_account(PurpleAcco
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
 	PurpleBlistNode *gnode, *cnode, *bnode;
 
-	g_return_if_fail(purplebuddylist != NULL);
 
 	if (!ops || !ops->update)
 		return;
 
-	for (gnode = purplebuddylist->root; gnode; gnode = gnode->next) {
+	for (gnode = purple_blist_node_get_first_child(PURPLE_BLIST_NODE(purple_blist_get_list())); gnode; gnode = gnode->next) {
 		if (!PURPLE_IS_GROUP(gnode))
 			continue;
 		for (cnode = gnode->child; cnode; cnode = cnode->next) {
@@ -1040,22 +1027,22 @@ void purple_blist_add_account(PurpleAcco
 							((PurpleContact*)cnode)->currentsize++;
 							if (((PurpleContact*)cnode)->currentsize == 1)
 								((PurpleGroup*)gnode)->currentsize++;
-							ops->update(purplebuddylist, bnode);
+							ops->update(purple_blist_get_list(), bnode);
 						}
 					}
 					if (recompute ||
 							purple_blist_node_get_bool(cnode, "show_offline")) {
 						purple_contact_invalidate_priority_buddy((PurpleContact*)cnode);
-						ops->update(purplebuddylist, cnode);
+						ops->update(purple_blist_get_list(), cnode);
 					}
 			} else if (PURPLE_IS_CHAT(cnode) &&
 					((PurpleChat*)cnode)->account == account) {
 				((PurpleGroup *)gnode)->online++;
 				((PurpleGroup *)gnode)->currentsize++;
-				ops->update(purplebuddylist, cnode);
+				ops->update(purple_blist_get_list(), cnode);
 			}
 		}
-		ops->update(purplebuddylist, gnode);
+		ops->update(purple_blist_get_list(), gnode);
 	}
 }
 
@@ -1069,9 +1056,8 @@ void purple_blist_remove_account(PurpleA
 	PurpleGroup *group;
 	GList *list = NULL, *iter = NULL;
 
-	g_return_if_fail(purplebuddylist != NULL);
 
-	for (gnode = purplebuddylist->root; gnode; gnode = gnode->next) {
+	for (gnode = purple_blist_node_get_first_child(PURPLE_BLIST_NODE(purple_blist_get_list())); gnode; gnode = gnode->next) {
 		if (!PURPLE_IS_GROUP(gnode))
 			continue;
 
@@ -1114,14 +1100,14 @@ void purple_blist_remove_account(PurpleA
 							recompute = TRUE;
 
 						if (ops && ops->remove) {
-							ops->remove(purplebuddylist, bnode);
+							ops->remove(purple_blist_get_list(), bnode);
 						}
 					}
 				}
 				if (recompute) {
 					purple_contact_invalidate_priority_buddy(contact);
 					if (ops && ops->update)
-						ops->update(purplebuddylist, cnode);
+						ops->update(purple_blist_get_list(), cnode);
 				}
 			} else if (PURPLE_IS_CHAT(cnode)) {
 				chat = (PurpleChat *)cnode;
@@ -1131,7 +1117,7 @@ void purple_blist_remove_account(PurpleA
 					group->online--;
 
 					if (ops && ops->remove)
-						ops->remove(purplebuddylist, cnode);
+						ops->remove(purple_blist_get_list(), cnode);
 				}
 			}
 		}
@@ -1176,12 +1162,13 @@ void purple_blist_add_chat(PurpleChat *c
 		/* Add group to blist if isn't already on it. Fixes #2752. */
 		if (!purple_find_group(group->name)) {
 			purple_blist_add_group(group,
-					purple_blist_get_last_sibling(purplebuddylist->root));
+					purple_blist_node_get_first_child(PURPLE_BLIST_NODE(purple_blist_get_list())));
 		}
 	} else {
 		group = (PurpleGroup*)node->parent;
 	}
 
+
 	/* if we're moving to overtop of ourselves, do nothing */
 	if (cnode == node)
 		return;
@@ -1190,20 +1177,11 @@ void purple_blist_add_chat(PurpleChat *c
 		/* This chat was already in the list and is
 		 * being moved.
 		 */
-		((PurpleGroup *)cnode->parent)->totalsize--;
-		if (purple_account_is_connected(chat->account)) {
-			((PurpleGroup *)cnode->parent)->online--;
-			((PurpleGroup *)cnode->parent)->currentsize--;
-		}
-		if (cnode->next)
-			cnode->next->prev = cnode->prev;
-		if (cnode->prev)
-			cnode->prev->next = cnode->next;
-		if (cnode->parent->child == cnode)
-			cnode->parent->child = cnode->next;
 
+		PURPLE_GET_BLIST_NODE_CLASS(cnode->parent)->remove(cnode);
+
 		if (ops && ops->remove)
-			ops->remove(purplebuddylist, cnode);
+			ops->remove(purple_blist_get_list(), cnode);
 		/* ops->remove() cleaned up the cnode's ui_data, so we need to
 		 * reinitialize it */
 		if (ops && ops->new_node)
@@ -1241,7 +1219,7 @@ void purple_blist_add_chat(PurpleChat *c
 	purple_blist_schedule_save();
 
 	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode *)cnode);
+		ops->update(purple_blist_get_list(), (PurpleBlistNode *)cnode);
 
 	purple_signal_emit(purple_blist_get_handle(), "blist-node-added",
 			cnode);
@@ -1280,7 +1258,7 @@ void purple_blist_add_buddy(PurpleBuddy 
 		/* Add group to blist if isn't already on it. Fixes #2752. */
 		if (!purple_find_group(g->name)) {
 			purple_blist_add_group(g,
-					purple_blist_get_last_sibling(purplebuddylist->root));
+					purple_blist_node_get_first_child(PURPLE_BLIST_NODE(purple_blist_get_list())));
 		}
 		c = purple_contact_new();
 		purple_blist_add_contact(c, g,
@@ -1314,7 +1292,7 @@ void purple_blist_add_buddy(PurpleBuddy 
 			bnode->parent->child = bnode->next;
 
 		if (ops && ops->remove)
-			ops->remove(purplebuddylist, bnode);
+			ops->remove(purple_blist_get_list(), bnode);
 
 		purple_blist_schedule_save();
 
@@ -1323,9 +1301,9 @@ void purple_blist_add_buddy(PurpleBuddy 
 			hb->name = g_strdup(purple_normalize(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)));
 			hb->account = purple_buddy_get_account(buddy);
 			hb->group = bnode->parent->parent;
-			g_hash_table_remove(purplebuddylist->buddies, hb);
+			g_hash_table_remove(purple_blist_get_list()->buddies, hb);
 
-			account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, purple_buddy_get_account(buddy));
+			account_buddies = g_hash_table_lookup(purple_blist_get_list()->buddies_cache, purple_buddy_get_account(buddy));
 			g_hash_table_remove(account_buddies, hb);
 
 			g_free(hb->name);
@@ -1337,7 +1315,7 @@ void purple_blist_add_buddy(PurpleBuddy 
 		} else {
 			purple_contact_invalidate_priority_buddy((PurpleContact*)bnode->parent);
 			if (ops && ops->update)
-				ops->update(purplebuddylist, bnode->parent);
+				ops->update(purple_blist_get_list(), bnode->parent);
 		}
 	}
 
@@ -1372,9 +1350,9 @@ void purple_blist_add_buddy(PurpleBuddy 
 	hb->account = purple_buddy_get_account(buddy);
 	hb->group = ((PurpleBlistNode*)buddy)->parent->parent;
 
-	g_hash_table_replace(purplebuddylist->buddies, hb, buddy);
+	g_hash_table_replace(purple_blist_get_list()->buddies, hb, buddy);
 
-	account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, purple_buddy_get_account(buddy));
+	account_buddies = g_hash_table_lookup(purple_blist_get_list()->buddies_cache, purple_buddy_get_account(buddy));
 
 	hb2 = g_new(struct _purple_hbuddy, 1);
 	hb2->name = g_strdup(hb->name);
@@ -1388,7 +1366,7 @@ void purple_blist_add_buddy(PurpleBuddy 
 	purple_blist_schedule_save();
 
 	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode*)buddy);
+		ops->update(purple_blist_get_list(), (PurpleBlistNode*)buddy);
 
 	/* Signal that the buddy has been added */
 	purple_signal_emit(purple_blist_get_handle(), "buddy-added", buddy);
@@ -1409,7 +1387,6 @@ purple_blist_find_chat(PurpleAccount *ac
 	GList *parts;
 	char *normname;
 
-	g_return_val_if_fail(purplebuddylist != NULL, NULL);
 	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
 
 	if (!purple_account_is_connected(account))
@@ -1422,7 +1399,7 @@ purple_blist_find_chat(PurpleAccount *ac
 		return prpl_info->find_blist_chat(account, name);
 
 	normname = g_strdup(purple_normalize(account, name));
-	for (group = purplebuddylist->root; group != NULL; group = group->next) {
+	for (group = purple_blist_node_get_first_child(PURPLE_BLIST_NODE(purple_blist_get_list())); group != NULL; group = group->next) {
 		for (node = group->child; node != NULL; node = node->next) {
 			if (PURPLE_IS_CHAT(node)) {
 
@@ -1459,7 +1436,6 @@ PurpleBuddy *purple_find_buddy_in_group(
 	struct _purple_hbuddy hb;
 	PurpleBuddy *ret;
 
-	g_return_val_if_fail(purplebuddylist != NULL, NULL);
 	g_return_val_if_fail(account != NULL, NULL);
 	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
 
@@ -1467,7 +1443,7 @@ PurpleBuddy *purple_find_buddy_in_group(
 	hb.account = account;
 	hb.group = (PurpleBlistNode*)group;
 
-	ret = g_hash_table_lookup(purplebuddylist->buddies, &hb);
+	ret = g_hash_table_lookup(purple_blist_get_list()->buddies, &hb);
 	g_free(hb.name);
 
 	return ret;
@@ -1493,10 +1469,7 @@ purple_blist_get_buddies()
 {
 	GSList *buddies = NULL;
 
-	if (!purplebuddylist)
-		return NULL;
-
-	g_hash_table_foreach(purplebuddylist->buddies, append_buddy, &buddies);
+	g_hash_table_foreach(purple_blist_get_list()->buddies, append_buddy, &buddies);
 	return buddies;
 }
 
@@ -1560,7 +1533,6 @@ purple_blist_init(void)
 void
 purple_blist_init(void)
 {
-	purplebuddylist = g_object_new(PURPLE_BUDDY_LIST_TYPE, NULL);
 }
 
 void
@@ -1568,13 +1540,9 @@ purple_blist_uninit(void)
 {
 	PurpleBlistNode *node, *next_node;
 
-	/* This happens if we quit before purple_set_blist is called. */
-	if (purplebuddylist == NULL)
-		return;
-
-	if (purplebuddylist->save_timer != 0) {
-		purple_timeout_remove(purplebuddylist->save_timer);
-		purplebuddylist->save_timer = 0;
+	if (purple_blist_get_list()->save_timer != 0) {
+		purple_timeout_remove(purple_blist_get_list()->save_timer);
+		purple_blist_get_list()->save_timer = 0;
 		purple_blist_sync();
 	}
 
@@ -1584,15 +1552,51 @@ purple_blist_uninit(void)
 		purple_blist_node_destroy(node);
 		node = next_node;
 	}
-	purplebuddylist->root = NULL;
-	
-	g_hash_table_destroy(purplebuddylist->buddies);
-	g_hash_table_destroy(purplebuddylist->buddies_cache);
 
+	g_hash_table_destroy(purple_blist_get_list()->buddies);
+	g_hash_table_destroy(purple_blist_get_list()->buddies_cache);
+
 	purple_signals_disconnect_by_handle(purple_blist_get_handle());
 	purple_signals_unregister_by_instance(purple_blist_get_handle());
 };
 
+static void
+purple_blist_remove_node(PurpleBlistNode *node)
+{
+	PurpleGroup *group;
+
+	g_return_if_fail(node);
+	parent_class->remove(node);
+	
+	group = PURPLE_GROUP(node);
+}
+
+static void
+purple_blist_add_sibling(PurpleBlistNode *child, PurpleBlistNode *location)
+{
+	PurpleGroup *group;
+	PurpleGroup *ref_group;
+
+	g_return_if_fail(child);
+	g_return_if_fail(location);
+	parent_class->add_sibling(child, location);
+
+	group = PURPLE_GROUP(child);
+	ref_group = PURPLE_GROUP(location);
+}
+
+static void
+purple_blist_add_child(PurpleBlistNode *parent, PurpleBlistNode *child)
+{
+	PurpleGroup *group;
+
+	g_return_if_fail(parent);
+	g_return_if_fail(child);
+	parent_class->add_child(parent, child);
+
+ 	group	= PURPLE_GROUP(child);
+}
+
 /******************/
 /*  GObject Code  */
 /******************/
@@ -1607,7 +1611,7 @@ purple_blist_finalize(GObject *object)
 
 	if (ops && ops->destroy)
 		ops->destroy(purplebuddylist);
-	parent_class->finalize(object);
+	G_OBJECT_CLASS(parent_class)->finalize(object);
 }
 
 static void
@@ -1616,6 +1620,12 @@ purple_blist_class_init(PurpleBuddyListC
 	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_node;
+	parent_class->add_sibling = purple_blist_add_sibling;
+	parent_class->add_child = purple_blist_add_child;
+
 	parent_class = g_type_class_peek_parent(klass);
 	obj_class->finalize = purple_blist_finalize;
 
@@ -1706,21 +1716,22 @@ purple_blist_class_init(PurpleBuddyListC
 			handle,
 			PURPLE_CALLBACK(purple_blist_buddies_cache_remove_account),
 			NULL);
+
+	purple_signal_connect(purple_blist_node_get_handle(), "group-removed",
+			handle,
+			PURPLE_CALLBACK(purple_blist_remove_group),
+			NULL);
 }
 
 static void
 purple_blist_instance_init(GTypeInstance *instance, gpointer class)
 {
 	PurpleBlistUiOps *ui_ops;
-	GList *account;
 	PurpleBuddyList *gbl = PURPLE_BUDDY_LIST(instance);
 	PURPLE_DBUS_REGISTER_POINTER(gbl, PurpleBuddyList);
 
 	ui_ops = purple_blist_get_ui_ops();
 
-	#warning: This has to be set here or we cant add the buddies cache
-	purplebuddylist = gbl;
-
 	gbl->buddies = g_hash_table_new_full((GHashFunc)_purple_blist_hbuddy_hash,
 					 (GEqualFunc)_purple_blist_hbuddy_equal,
 					 (GDestroyNotify)_purple_blist_hbuddy_free_key, NULL);
@@ -1728,15 +1739,7 @@ purple_blist_instance_init(GTypeInstance
 	gbl->buddies_cache = g_hash_table_new_full(g_direct_hash, g_direct_equal,
 					 NULL, (GDestroyNotify)g_hash_table_destroy);
 
-	for (account = purple_accounts_get_all(); account != NULL; account = account->next)
-	{
-		purple_blist_buddies_cache_add_account(account->data);
-	}
-
-	if (ui_ops != NULL && ui_ops->new_list != NULL)
-		ui_ops->new_list(gbl);
-
-	gbl->save_timer = 0;
+		gbl->save_timer = 0;
 	gbl->blist_loaded = FALSE;
 
 	purple_blist_load();
@@ -1761,7 +1764,7 @@ purple_blist_get_gtype(void)
 			NULL					/* value_table		*/
 		};
 
-		type = g_type_register_static(PURPLE_TYPE_OBJECT,
+		type = g_type_register_static(PURPLE_BLIST_NODE_TYPE,
 									  "PurpleBuddyList",
 									  &info, 0);
 	}
============================================================
--- libpurple/blist.h	4f36e6d84f8d69e8528c9e9be006c74e7c59670a
+++ libpurple/blist.h	10be254bab3feda7127abc7cfeefd63cff5d569f
@@ -112,8 +112,6 @@ struct _purple_hbuddy {
 	PurpleBlistNode *group;
 };
 
-extern PurpleBuddyList* purplebuddylist;
-
 void purple_blist_node_initialize_settings(PurpleBlistNode *node);
 void purple_blist_node_destroy(PurpleBlistNode* node);
 
@@ -140,7 +138,7 @@ PurpleBuddyList *purple_blist_new(void);
  *
  * @return The main buddy list.
  */
-PurpleBuddyList *purple_get_blist(void);
+PurpleBuddyList *purple_blist_get_list(void);
 
 /**
  * Returns the root node of the main buddy list.
@@ -340,14 +338,6 @@ void purple_blist_remove_chat(PurpleChat
 void purple_blist_remove_chat(PurpleChat *chat);
 
 /**
- * Removes a group from the buddy list and frees the memory allocated to it and to
- * its children
- *
- * @param group   The group to be removed
- */
-void purple_blist_remove_group(PurpleGroup *group);
-
-/**
  * Finds the buddy struct given a name and an account
  *
  * @param account The account this buddy belongs to
============================================================
--- libpurple/buddy.c	8b4b8b61784bf6345933021c8479511e334abeeb
+++ libpurple/buddy.c	0f0c51b29947683f99fa50a5080c308b4319fb7b
@@ -133,7 +133,7 @@ purple_blist_update_buddy_status(PurpleB
 	 */
 	purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy));
 	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
+		ops->update(purple_blist_get_list(), (PurpleBlistNode *)buddy);
 }
 
 void
@@ -172,7 +172,7 @@ void purple_buddy_set_alias(PurpleBuddy 
 	purple_blist_schedule_save();
 
 	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
+		ops->update(purple_blist_get_list(), (PurpleBlistNode *)buddy);
 
 	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, priv->name,
 											   priv->account);
@@ -227,7 +227,7 @@ void purple_blist_server_alias_buddy(Pur
 	purple_blist_schedule_save();
 
 	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
+		ops->update(purple_blist_get_list(), (PurpleBlistNode *)buddy);
 
 	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, priv->name,
 											   priv->account);
============================================================
--- libpurple/chat.c	aa22eac2976ee860b6ee0bbfd7136babf200961a
+++ libpurple/chat.c	4e29a66863b56b4eaa11901680576061e8451635
@@ -151,7 +151,7 @@ void purple_chat_set_alias(PurpleChat *c
 	purple_blist_schedule_save();
 
 	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode *)chat);
+		ops->update(purple_blist_get_list(), (PurpleBlistNode *)chat);
 
 	purple_signal_emit(purple_blist_get_handle(), "blist-node-aliased",
 					 chat, old_alias);
============================================================
--- libpurple/contact.c	0fce70049c47b2f7ccf898f4ee8834b3ebbbb8cb
+++ libpurple/contact.c	15964a5a97cba93677ed3edb223c4d0c3520f38c
@@ -173,7 +173,7 @@ void purple_blist_alias_contact(PurpleCo
 	purple_blist_schedule_save();
 
 	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode *)contact);
+		ops->update(purple_blist_get_list(), (PurpleBlistNode *)contact);
 
 	for(bnode = ((PurpleBlistNode *)contact)->child; bnode != NULL; bnode = bnode->next)
 	{
@@ -316,12 +316,18 @@ static void
 }
 
 static void
-purple_contact_add_buddy(PurpleBlistNode *parent, PurpleBlistNode *child, PurpleBlistNode *location)
+purple_contact_add_buddy_child(PurpleBlistNode *parent, PurpleBlistNode *child)
 {
 
 }
 
 static void
+purple_contact_add_buddy_sibling(PurpleBlistNode *child, PurpleBlistNode *location)
+{
+
+}
+
+static void
 purple_contact_remove_buddy(PurpleBlistNode *child)
 {
 	PurpleContact *contact;
@@ -343,7 +349,7 @@ purple_contact_remove_buddy(PurpleBlistN
 	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));
+			ops->update(purple_blist_get_list(), PURPLE_BLIST_NODE(contact));
 	}
 }
 
@@ -367,8 +373,9 @@ purple_contact_class_init(PurpleContactC
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
 	parent_class = g_type_class_peek_parent(klass);
-	parent_class->add_node = purple_contact_add_buddy;
-	parent_class->remove_node = purple_contact_remove_buddy;
+	parent_class->add_sibling = purple_contact_add_buddy_sibling;
+	parent_class->add_child = purple_contact_add_buddy_child;
+	parent_class->remove = purple_contact_remove_buddy;
 
 	obj_class->finalize = purple_contact_finalize;
 }
============================================================
--- libpurple/group.c	d6f3080aedb46426fa288810e3f3ef43d4db6b56
+++ libpurple/group.c	e53cc2d332d436a80cc52b9081762866fad9f83e
@@ -31,6 +31,8 @@
 #include "signals.h"
 #include "xmlnode.h"
 
+static PurpleBlistNodeClass *parent_class = NULL;
+
 xmlnode *
 group_to_xmlnode(PurpleBlistNode *gnode)
 {
@@ -95,30 +97,35 @@ purple_group_remove_node(PurpleBlistNode
 {
 	PurpleGroup *group;
 	PurpleContact *contact;
-	PurpleBlistNode *itr;
+	PurpleChat *chat;
 
 	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;
-	group->online = 0;
-
-	/* Update size counts */
-  for(itr	= group->node.child;itr;itr = itr->next){
-		if(PURPLE_CONTACT(itr)->online > 0)
-			group->online++;
-		if(PURPLE_CONTACT(itr)->currentsize > 0)
-			group->currentsize++;
-		group->totalsize++;
+	if(PURPLE_IS_CHAT(child)){
+		chat = PURPLE_CHAT(child);
+		if (purple_account_is_connected(chat->account)) {
+			group->online--;
+			group->currentsize--;
+		}
+	} else if(PURPLE_IS_CONTACT(child)){
+		contact = PURPLE_CONTACT(child);
+		if(purple_contact_get_online(contact) > 0)
+			group->online--;
+		if(purple_contact_get_currentsize(contact) > 0)
+			group->currentsize--;
+	} else {
+		g_warn_if_reached();
 	}
+	group->totalsize--;
 
-	/* If the contact is empty then remove it */
-	if ((contact != NULL) && !PURPLE_BLIST_NODE(contact)->child)
-		purple_blist_remove_contact(contact);
+	parent_class->remove(child);
+
+	purple_blist_schedule_save();
+
+	purple_signal_emit(purple_blist_node_get_handle(), "node-removed", child);
+	g_object_unref(G_OBJECT(child));
 }
 
 PurpleGroup *purple_buddy_get_group(PurpleBuddy *buddy)
@@ -205,7 +212,7 @@ purple_group_add_contact(PurpleGroup *gr
 
 	if (node && (PURPLE_IS_CONTACT(node) ||
 				PURPLE_IS_CHAT(node))) {
-		purple_blist_node_add_sibling_after(PURPLE_BLIST_NODE(contact), node);
+		purple_blist_node_add_sibling(PURPLE_BLIST_NODE(contact), node);
 	} else {
 		purple_blist_node_add_child(PURPLE_BLIST_NODE(group), PURPLE_BLIST_NODE(contact));
 	}	
@@ -248,7 +255,6 @@ PurpleGroup *purple_group_new(const char
 												NULL);
 }
 
-static PurpleBlistNodeClass *parent_class = NULL;
 
 static void
 purple_group_finalize(GObject *object)
@@ -291,11 +297,13 @@ purple_group_class_init(PurpleGroupClass
 purple_group_class_init(PurpleGroupClass *klass)
 {
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	PurpleBlistNodeClass *bklass = PURPLE_BLIST_NODE_CLASS(klass);
 
 	parent_class = g_type_class_peek_parent(klass);
-	parent_class->remove_node = purple_group_remove_node;
+	
+	bklass->remove = purple_group_remove_node;
+
 	obj_class->finalize = purple_group_finalize;
-
 	obj_class->set_property = purple_group_set_property;
 	obj_class->get_property = purple_group_get_property;
 
============================================================
--- libpurple/group.h	e76a4c2517b9f0f267cbeb33ea9aa17aafc6390a
+++ libpurple/group.h	9e7f4f457edcf2509eedc8edfc0dcae558665e25
@@ -36,6 +36,7 @@ typedef struct _PurpleGroupClass PurpleG
 #include "buddy.h"
 #include "chat.h"
 #include "contact.h"
+#include "blist-node.h"
 
 #define PURPLE_GROUP_TYPE                  (purple_group_get_type ())
 #define PURPLE_GROUP(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), PURPLE_GROUP_TYPE, PurpleGroup))
============================================================
--- libpurple/protocols/bonjour/bonjour.c	7f1efe1bddffad9fb010a6131afe74e92b96fffd
+++ libpurple/protocols/bonjour/bonjour.c	0cd60df8a1c8f9e5e28fbf5ca293a8b17776395c
@@ -173,7 +173,7 @@ bonjour_close(PurpleConnection *connecti
 
 	/* Delete the bonjour group */
 	if (bonjour_group != NULL)
-		purple_blist_remove_group(bonjour_group);
+		purple_blist_node_remove(PURPLE_BLIST_NODE(bonjour_group));
 
 	/* Cancel any file transfers */
 	while (bd != NULL && bd->xfer_lists) {
============================================================
--- libpurple/protocols/myspace/myspace.c	4e0bc11270993ad7fb09931d60a443e8b7434a31
+++ libpurple/protocols/myspace/myspace.c	5032c737d9ea7fcb96318b6770e8d8dcd6b92893
@@ -1363,7 +1363,7 @@ msim_incoming_status(MsimSession *sessio
 	purple_debug_info("msim", "msim_status: %s's status code = %d\n", username, status_code);
 	status_headline = msim_msg_get_string_from_element(g_list_nth_data(list, MSIM_STATUS_ORDINAL_HEADLINE));
 
-	blist = purple_get_blist();
+	blist = purple_blist_get_list();
 
 	/* Add buddy if not found.
 	 * TODO: Could this be responsible for #3444? */
============================================================
--- libpurple/status.c	9868393be4980907ec0a4203e0b8f85e8d755d64
+++ libpurple/status.c	e0d0953658866ad7b9cdb86bdd03836f4030f0f0
@@ -1341,7 +1341,7 @@ update_buddy_idle(PurpleBuddy *buddy, Pu
 	 */
 
 	if (ops != NULL && ops->update != NULL)
-		ops->update(purple_get_blist(), (PurpleBlistNode *)buddy);
+		ops->update(purple_blist_get_list(), (PurpleBlistNode *)buddy);
 }
 
 void


More information about the Commits mailing list