changeset 25103:edb03a8d54bd

Fixed gtkblist-loader_build to no longer assume xml file is correct, added set methods to gtkblist-theme
author Justin Rodriguez <ffdragon@soc.pidgin.im>
date Thu, 17 Jul 2008 19:40:13 +0000
parents 4aeef8c3cce3
children 2ccad3a8d9fe
files pidgin/gtkblist-loader.c pidgin/gtkblist-theme.c pidgin/gtkblist-theme.h pidgin/gtkblist.c
diffstat 4 files changed, 584 insertions(+), 162 deletions(-) [+]
line wrap: on
line diff
--- a/pidgin/gtkblist-loader.c	Tue Jul 15 06:29:46 2008 +0000
+++ b/pidgin/gtkblist-loader.c	Thu Jul 17 19:40:13 2008 +0000
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 
 #include "xmlnode.h"
+
 #include "gtkblist-loader.h"
 #include "gtkblist-theme.h"
 
@@ -31,7 +32,7 @@
  * Globals
  *****************************************************************************/
 /*****************************************************************************
- * Sound Theme Builder                                                      
+ * Buddy List Theme Builder                                                      
  *****************************************************************************/
 
 static gpointer
@@ -39,21 +40,12 @@
 {
 	xmlnode *root_node, *sub_node, *sub_sub_node;
 	gchar *filename, *filename_full, *data;
-	const gchar *icon_theme;
-	GdkColor *bgcolor = NULL, 
-		 *expanded_bgcolor = NULL,
-		 *minimized_bgcolor = NULL, 
-		 *buddy_bgcolor1 = NULL,
-		 *buddy_bgcolor2 = NULL;
-	font_color_pair *expanded = g_new0(font_color_pair, 1), 
-			*minimized = g_new0(font_color_pair, 1), 
-			*online = g_new0(font_color_pair, 1),
-			*away = g_new0(font_color_pair, 1),
-			*offline = g_new0(font_color_pair, 1), 
-			*message = g_new0(font_color_pair, 1), 
-			*status = g_new0(font_color_pair, 1);
+	const gchar *icon_theme = NULL, *tmp;
+	gboolean sucess = TRUE;
+	GdkColor *bgcolor, *expanded_bgcolor, *collapsed_bgcolor, *buddy_bgcolor1, *buddy_bgcolor2;
+	FontColorPair *expanded, *collapsed, *online, *away, *offline, *message, *status;
 	gdouble transparency;
-	blist_layout *layout = g_new0(blist_layout, 1);
+	PidginBlistLayout *layout = g_new0(PidginBlistLayout, 1);
 	GDir *gdir;
 	PidginBlistTheme *theme;
 
@@ -64,85 +56,180 @@
 	while ((filename = g_strdup(g_dir_read_name(gdir))) != NULL && ! g_str_has_suffix(filename, ".xml"))
 		g_free(filename);
 	
-	g_return_val_if_fail(filename != NULL, NULL);
+	if (filename == NULL){
+		g_dir_close(gdir);
+		return NULL;
+	}
 	
 	/* Build the xml tree */
 	filename_full = g_build_filename(dir, filename, NULL);
 
-	root_node = xmlnode_from_file(dir, filename, "sound themes", "sound-loader");
+	root_node = xmlnode_from_file(dir, filename, "blist themes", "blist-loader");
 	g_return_val_if_fail(root_node != NULL, NULL);
 
+	/* colors */
+	bgcolor = g_new0(GdkColor, 1);
+	expanded_bgcolor = g_new0(GdkColor, 1);
+	collapsed_bgcolor = g_new0(GdkColor, 1); 
+	buddy_bgcolor1 = g_new0(GdkColor, 1);
+	buddy_bgcolor2 = g_new0(GdkColor, 1);
+	
+	/* font color pairs */
+	expanded = g_new0(FontColorPair, 1);
+	expanded->color = g_new0(GdkColor, 1);
+	collapsed = g_new0(FontColorPair, 1);
+	collapsed->color = g_new0(GdkColor, 1);
+	online = g_new0(FontColorPair, 1);
+	online->color = g_new0(GdkColor, 1);
+	away = g_new0(FontColorPair, 1);
+	away->color = g_new0(GdkColor, 1);
+	offline = g_new0(FontColorPair, 1);
+	offline->color = g_new0(GdkColor, 1); 
+	message = g_new0(FontColorPair, 1);
+	message->color = g_new0(GdkColor, 1); 
+	status = g_new0(FontColorPair, 1);
+	status->color = g_new0(GdkColor, 1);
+
 	/* Parse the tree */	
 	sub_node = xmlnode_get_child(root_node, "description");
 	data = xmlnode_get_data(sub_node);
 
 	/* <icon_theme> */
-	sub_node = xmlnode_get_child(root_node, "icon_theme");
-	icon_theme = xmlnode_get_attrib(sub_node, "name");
+	if ((sucess = (sub_node = xmlnode_get_child(root_node, "icon_theme")) != NULL))
+		icon_theme = xmlnode_get_attrib(sub_node, "name");
 
 	/* <blist> */
-	sub_node = xmlnode_get_child(root_node, "blist");
-	transparency = atof(xmlnode_get_attrib(sub_node, "transparency"));
-	if(gdk_color_parse(xmlnode_get_attrib(sub_node, "color"), bgcolor))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), bgcolor, FALSE, TRUE);
-	
+	if ((sucess = sucess && (sub_node = xmlnode_get_child(root_node, "blist")) != NULL)) {
+		transparency = atof(xmlnode_get_attrib(sub_node, "transparency"));
+
+		if ((tmp = xmlnode_get_attrib(sub_node, "color")) != NULL && gdk_color_parse(tmp, bgcolor))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), bgcolor, FALSE, TRUE);
+		else {
+			g_free(bgcolor);
+			bgcolor = NULL;
+		}
+	}
 
 	/* <groups> */
-	sub_node = xmlnode_get_child(root_node, "groups");
-	sub_sub_node = xmlnode_get_child(root_node, "expanded");
-	expanded->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
-	if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), expanded->color))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), expanded->color, FALSE, TRUE);
-	if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "background"), expanded_bgcolor))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), expanded_bgcolor, FALSE, TRUE);
+	if ((sucess = sucess && (sub_node = xmlnode_get_child(root_node, "groups")) != NULL
+		     && (sub_sub_node = xmlnode_get_child(sub_node, "expanded")) != NULL)) {
+
+		expanded->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
+
+		if ((tmp = xmlnode_get_attrib(sub_sub_node, "color")) != NULL && gdk_color_parse(tmp, expanded->color))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), expanded->color, FALSE, TRUE);
+		else {
+			g_free(expanded->color);
+			expanded->color = NULL;
+		}
+	
 
-	sub_sub_node = xmlnode_get_child(root_node, "minimized");
-	minimized->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
-	if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), minimized->color))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), minimized->color, FALSE, TRUE);
-	if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "background"), minimized_bgcolor))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), minimized_bgcolor, FALSE, TRUE);
+		if ((tmp = xmlnode_get_attrib(sub_sub_node, "background")) != NULL && gdk_color_parse(tmp, expanded_bgcolor))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), expanded_bgcolor, FALSE, TRUE);
+		else {
+			g_free(expanded_bgcolor);
+			expanded_bgcolor = NULL;
+		}
+	}
+
+	if ((sucess = sucess && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "collapsed")) != NULL)) {
+		collapsed->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
+
+		if((tmp = xmlnode_get_attrib(sub_sub_node, "color")) != NULL && gdk_color_parse(tmp, collapsed->color))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), collapsed->color, FALSE, TRUE);
+		else {
+			g_free(collapsed->color);
+			collapsed->color = NULL;
+		}
+		if ((tmp = xmlnode_get_attrib(sub_sub_node, "background")) != NULL && gdk_color_parse(tmp, collapsed_bgcolor))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), collapsed_bgcolor, FALSE, TRUE);
+		else {
+			g_free(collapsed_bgcolor);
+			collapsed_bgcolor = NULL;
+		}
+	}
 
 	/* <buddys> */
-	sub_node = xmlnode_get_child(root_node, "buddys");
-	sub_sub_node = xmlnode_get_child(root_node, "placement");
-	layout->buddy_icon = atoi(xmlnode_get_attrib(sub_sub_node, "status_icon"));
-	layout->text = atoi(xmlnode_get_attrib(sub_sub_node, "name"));
-	layout->buddy_icon = atoi(xmlnode_get_attrib(sub_sub_node, "buddy_icon"));
-	layout->protocol_icon = atoi(xmlnode_get_attrib(sub_sub_node, "protocol_icon"));
-	layout->emblem = atoi(xmlnode_get_attrib(sub_sub_node, "emblem"));
-	layout->show_status = (gboolean) atoi(xmlnode_get_attrib(sub_sub_node, "status_icon"));
+	if ((sucess = sucess && (sub_node = xmlnode_get_child(root_node, "buddys")) != NULL &&
+		     (sub_sub_node = xmlnode_get_child(sub_node, "placement")) != NULL)) { 
+
+		layout->buddy_icon = atoi(xmlnode_get_attrib(sub_sub_node, "status_icon"));
+		layout->text = atoi(xmlnode_get_attrib(sub_sub_node, "name"));
+		layout->buddy_icon = atoi(xmlnode_get_attrib(sub_sub_node, "buddy_icon"));
+		layout->protocol_icon = atoi(xmlnode_get_attrib(sub_sub_node, "protocol_icon"));
+		layout->emblem = atoi(xmlnode_get_attrib(sub_sub_node, "emblem"));
+		layout->show_status = atoi(xmlnode_get_attrib(sub_sub_node, "status_icon")) != 0;
+	}
+
+	if ((sucess = sucess && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "background")) != NULL)) {
 
-	sub_sub_node = xmlnode_get_child(root_node, "background");
-	if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color1"), buddy_bgcolor1))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), buddy_bgcolor1, FALSE, TRUE);
-	if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color2"), buddy_bgcolor2))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), buddy_bgcolor2, FALSE, TRUE);
+		if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color1"), buddy_bgcolor1))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), buddy_bgcolor1, FALSE, TRUE);
+		else {
+			g_free(buddy_bgcolor1);
+			buddy_bgcolor1 = NULL;
+		}
 
-	sub_sub_node = xmlnode_get_child(root_node, "online_text");
-	online->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
-	if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), (online->color)))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), (online->color), FALSE, TRUE);
+		if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color2"), buddy_bgcolor2))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), buddy_bgcolor2, FALSE, TRUE);
+		else {
+			g_free(buddy_bgcolor2);
+			buddy_bgcolor2 = NULL;
+		}
+	}
+
+	if ((sucess = sucess && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "online_text")) != NULL)) {
+		online->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
+		if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), online->color))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), online->color, FALSE, TRUE);
+		else {
+			g_free(online->color);
+			online->color = NULL;
+		}
+	}
 
-	sub_sub_node = xmlnode_get_child(root_node, "away_text");
-	away->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
-	if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), away->color))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), away->color, FALSE, TRUE);
-	
-	sub_sub_node = xmlnode_get_child(root_node, "offline_text");
-	offline->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
-	if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), offline->color))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), offline->color, FALSE, TRUE);
+	if ((sucess = sucess && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "away_text")) != NULL)) {
+		away->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
+		if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), away->color))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), away->color, FALSE, TRUE);
+		else {
+			g_free(away->color);
+			away->color = NULL;
+		}
+	}
+
+	if ((sucess = sucess && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "offline_text")) != NULL)) {
+		offline->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
+		if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), offline->color))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), offline->color, FALSE, TRUE);
+		else {
+			g_free(offline->color);
+			online->color = NULL;
+		}
+	}
 	
-	sub_sub_node = xmlnode_get_child(root_node, "message_text");
-	message->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
-	if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), message->color))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), message->color, FALSE, TRUE);
+	if ((sucess = sucess && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "message_text")) != NULL)) {
+		message->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
+		if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), message->color))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), message->color, FALSE, TRUE);
+		else {
+			g_free(message->color);
+			message->color = NULL;
+		}
+	}
 	
-	sub_sub_node = xmlnode_get_child(root_node, "status_text");
-	status->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
-	if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), status->color))
-		gdk_colormap_alloc_color(gdk_colormap_get_system(), status->color, FALSE, TRUE);
+	if ((sucess = sucess && sub_node != NULL && (sub_sub_node = xmlnode_get_child(sub_node, "status_text")) != NULL)) {
+		status->font = g_strdup(xmlnode_get_attrib(sub_sub_node, "font"));
+		if(gdk_color_parse(xmlnode_get_attrib(sub_sub_node, "color"), status->color))
+			gdk_colormap_alloc_color(gdk_colormap_get_system(), status->color, FALSE, TRUE);
+		else {
+			g_free(status->color);
+			status->color = NULL;
+		}
+	}
+
+	/* name is required for theme manager */
+	sucess = sucess && xmlnode_get_attrib(root_node, "name") != NULL;
 
 	/* the new theme */
 	theme = g_object_new(PIDGIN_TYPE_BLIST_THEME,
@@ -158,8 +245,8 @@
 			    "layout", layout,
 			    "expanded-color", expanded_bgcolor,
 			    "expanded-text", expanded,
-			    "minimized-color", minimized_bgcolor,
-			    "minimized-text", minimized,
+			    "collapsed-color", collapsed_bgcolor,
+			    "collapsed-text", collapsed,
 			    "buddy-bgcolor1", buddy_bgcolor1,
 			    "buddy-bgcolor2", buddy_bgcolor2,
 			    "online", online,
@@ -167,9 +254,14 @@
 			    "offline", offline,
 			    "message", message,
 			    "status", status, NULL);
+
+	/* malformed xml file */
+	if (!sucess) {
+		g_object_unref(theme);
+		theme = NULL;
+	}
 	
 	xmlnode_free(sub_node);
-
 	xmlnode_free(root_node);	
 	g_dir_close(gdir);
 	g_free(filename_full);
--- a/pidgin/gtkblist-theme.c	Tue Jul 15 06:29:46 2008 +0000
+++ b/pidgin/gtkblist-theme.c	Thu Jul 17 19:40:13 2008 +0000
@@ -26,9 +26,6 @@
 #define PIDGIN_BLIST_THEME_GET_PRIVATE(Gobject) \
 	((PidginBlistThemePrivate *) ((PIDGIN_BLIST_THEME(Gobject))->priv))
 
-#define free_font_and_color(font_color_pair) \
-	g_free(font_color_pair->font); \
-	g_free(font_color_pair)
 /******************************************************************************
  * Structs
  *****************************************************************************/
@@ -38,24 +35,24 @@
 	/* Buddy list */
 	GdkColor *bgcolor;
 	gdouble opacity;
-	blist_layout *layout;
+	PidginBlistLayout *layout;
 	
 	/* groups */
 	GdkColor *expanded_color;
-	font_color_pair *expanded;
+	FontColorPair *expanded;
 
 	GdkColor *collapsed_color;
-	font_color_pair *collapsed;
+	FontColorPair *collapsed;
 
 	/* buddy */
 	GdkColor *buddy_bgcolor1;
 	GdkColor *buddy_bgcolor2;
 
-	font_color_pair *online;
-	font_color_pair *away;
-	font_color_pair *offline;
-	font_color_pair *message;
-	font_color_pair *status;
+	FontColorPair *online;
+	FontColorPair *away;
+	FontColorPair *offline;
+	FontColorPair *message;
+	FontColorPair *status;
 
 } PidginBlistThemePrivate;
 
@@ -86,6 +83,20 @@
 	PROP_MESSAGE,
 	PROP_STATUS,
 };
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+
+static void
+free_font_and_color(FontColorPair *pair) 
+{
+	if(pair != NULL){
+		g_free(pair->font); 
+		g_free(pair);
+	}
+}
+
 /******************************************************************************
  * GObject Stuff                                                              
  *****************************************************************************/
@@ -102,53 +113,53 @@
 pidgin_blist_theme_get_property(GObject *obj, guint param_id, GValue *value,
 						 GParamSpec *psec)
 {
-	PidginBlistThemePrivate *priv = PIDGIN_BLIST_THEME_GET_PRIVATE(obj);
+	PidginBlistTheme *theme = PIDGIN_BLIST_THEME(obj);
 
 	switch(param_id) {
 		case PROP_ICON_THEME:
-			g_value_set_string(value, priv->icon_theme);
+			g_value_set_string(value, pidgin_blist_theme_get_icon_theme(theme));
 			break;
 		case PROP_BACKGROUND_COLOR:
-			g_value_set_pointer(value, priv->bgcolor);
+			g_value_set_pointer(value, pidgin_blist_theme_get_background_color(theme));
 			break;
 		case PROP_OPACITY:
-			g_value_set_double(value, priv->opacity);
+			g_value_set_double(value, pidgin_blist_theme_get_opacity(theme));
 			break;
 		case PROP_LAYOUT:
-			g_value_set_pointer(value, priv->layout);
+			g_value_set_pointer(value, pidgin_blist_theme_get_layout(theme));
 			break;
 		case PROP_EXPANDED_COLOR:
-			g_value_set_pointer(value, priv->expanded_color);
+			g_value_set_pointer(value, pidgin_blist_theme_get_expanded_background_color(theme));
 			break;
 		case PROP_EXPANDED_TEXT:
-			g_value_set_pointer(value, priv->expanded);
+			g_value_set_pointer(value, pidgin_blist_theme_get_expanded_text_info(theme));
 			break;
 		case PROP_COLLAPSED_COLOR:
-			g_value_set_pointer(value, priv->collapsed_color);
+			g_value_set_pointer(value, pidgin_blist_theme_get_collapsed_background_color(theme));
 			break;
 		case PROP_COLLAPSED_TEXT:
-			g_value_set_pointer(value, priv->collapsed);
+			g_value_set_pointer(value, pidgin_blist_theme_get_collapsed_text_info(theme));
 			break;
 		case PROP_BGCOLOR1:
-			g_value_set_pointer(value, priv->buddy_bgcolor1);
+			g_value_set_pointer(value, pidgin_blist_theme_get_buddy_color_1(theme));
 			break;
 		case PROP_BGCOLOR2:
-			g_value_set_pointer(value, priv->buddy_bgcolor2);
+			g_value_set_pointer(value, pidgin_blist_theme_get_buddy_color_2(theme));
 			break;
 		case PROP_ONLINE:
-			g_value_set_pointer(value, priv->online);
+			g_value_set_pointer(value, pidgin_blist_theme_get_online_text_info(theme));
 			break;
 		case PROP_AWAY:
-			g_value_set_pointer(value, priv->away);
+			g_value_set_pointer(value, pidgin_blist_theme_get_away_text_info(theme));
 			break;
 		case PROP_OFFLINE:
-			g_value_set_pointer(value, priv->offline);
+			g_value_set_pointer(value, pidgin_blist_theme_get_offline_text_info(theme));
 			break;
 		case PROP_MESSAGE:
-			g_value_set_pointer(value, priv->message);
+			g_value_set_pointer(value, pidgin_blist_theme_get_unread_message_text_info(theme));
 			break;
 		case PROP_STATUS:
-			g_value_set_pointer(value, priv->status);
+			g_value_set_pointer(value, pidgin_blist_theme_get_status_text_info(theme));
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec);
@@ -160,62 +171,53 @@
 pidgin_blist_theme_set_property(GObject *obj, guint param_id, const GValue *value,
 						 GParamSpec *psec)
 {
-	PidginBlistThemePrivate *priv = PIDGIN_BLIST_THEME_GET_PRIVATE(obj);
+	PidginBlistTheme *theme = PIDGIN_BLIST_THEME(obj);
 
 	switch(param_id) {
 		case PROP_ICON_THEME:
-			g_free(priv->icon_theme);
-			priv->icon_theme = g_strdup(g_value_get_string(value));
+			pidgin_blist_theme_set_icon_theme(theme, g_value_get_string(value));
 			break;
 		case PROP_BACKGROUND_COLOR:
-			priv->bgcolor = g_value_get_pointer(value);
+			pidgin_blist_theme_set_background_color(theme, g_value_get_pointer(value));
 			break;
 		case PROP_OPACITY:
-			priv->opacity = g_value_get_double(value);
+			pidgin_blist_theme_set_opacity(theme, g_value_get_double(value));
 			break;
 		case PROP_LAYOUT:
-			g_free(priv->layout);
-			priv->layout = g_value_get_pointer(value);
+			pidgin_blist_theme_set_layout(theme, g_value_get_pointer(value));
 			break;
 		case PROP_EXPANDED_COLOR:
-			priv->expanded_color = g_value_get_pointer(value);
+			pidgin_blist_theme_set_expanded_background_color(theme, g_value_get_pointer(value));
 			break;
 		case PROP_EXPANDED_TEXT:
-			free_font_and_color(priv->expanded);
-			priv->expanded = g_value_get_pointer(value);
+			pidgin_blist_theme_set_expanded_text_info(theme, g_value_get_pointer(value));
 			break;
 		case PROP_COLLAPSED_COLOR:
-			priv->collapsed_color = g_value_get_pointer(value);
+			pidgin_blist_theme_set_collapsed_background_color(theme, g_value_get_pointer(value));
 			break;
 		case PROP_COLLAPSED_TEXT:
-			free_font_and_color(priv->collapsed);
-			priv->collapsed = g_value_get_pointer(value);
+			pidgin_blist_theme_set_collapsed_text_info(theme, g_value_get_pointer(value));
 			break;
 		case PROP_BGCOLOR1:
-			priv->buddy_bgcolor1 = g_value_get_pointer(value);
+			pidgin_blist_theme_set_buddy_color_1(theme, g_value_get_pointer(value));
 			break;
 		case PROP_BGCOLOR2:
-			priv->buddy_bgcolor2 = g_value_get_pointer(value);
+			pidgin_blist_theme_set_buddy_color_2(theme, g_value_get_pointer(value));
 			break;
 		case PROP_ONLINE:
-			free_font_and_color(priv->online);
-			priv->online = g_value_get_pointer(value);
+			pidgin_blist_theme_set_online_text_info(theme, g_value_get_pointer(value));
 			break;
 		case PROP_AWAY:
-			free_font_and_color(priv->away);
-			priv->away = g_value_get_pointer(value);
+			pidgin_blist_theme_set_away_text_info(theme, g_value_get_pointer(value));
 			break;
 		case PROP_OFFLINE:
-			free_font_and_color(priv->offline);
-			priv->offline = g_value_get_pointer(value);
+			pidgin_blist_theme_set_offline_text_info(theme, g_value_get_pointer(value));
 			break;
 		case PROP_MESSAGE:
-			free_font_and_color(priv->message);
-			priv->message = g_value_get_pointer(value);
+			pidgin_blist_theme_set_unread_message_text_info(theme, g_value_get_pointer(value));
 			break;
 		case PROP_STATUS:
-			free_font_and_color(priv->status);
-			priv->status = g_value_get_pointer(value);
+			pidgin_blist_theme_set_status_text_info(theme, g_value_get_pointer(value));
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec);
@@ -374,7 +376,8 @@
  * Public API functions                                                      
  *****************************************************************************/
 
-const gchar *
+/* get methods */
+gchar *
 pidgin_blist_theme_get_icon_theme(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -386,6 +389,18 @@
 	return priv->icon_theme;
 }
 
+GdkColor *
+pidgin_blist_theme_get_background_color(PidginBlistTheme *theme)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL);
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	return priv->bgcolor;
+}
+
 gdouble
 pidgin_blist_theme_get_opacity(PidginBlistTheme *theme)
 {
@@ -398,7 +413,7 @@
 	return priv->opacity;
 }
 
-const blist_layout *
+PidginBlistLayout *
 pidgin_blist_theme_get_layout(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -410,7 +425,7 @@
 	return priv->layout;
 }
 
-const GdkColor *
+GdkColor *
 pidgin_blist_theme_get_expanded_background_color(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -422,7 +437,7 @@
 	return priv->expanded_color;
 }
 
-const font_color_pair *
+FontColorPair *
 pidgin_blist_theme_get_expanded_text_info(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -434,7 +449,7 @@
 	return priv->expanded;
 }
 
-const GdkColor *
+GdkColor *
 pidgin_blist_theme_get_collapsed_background_color(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -446,7 +461,7 @@
 	return priv->collapsed_color;
 }
 
-const font_color_pair *
+FontColorPair *
 pidgin_blist_theme_get_collapsed_text_info(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -458,7 +473,7 @@
 	return priv->collapsed;
 }
 
-const GdkColor *
+GdkColor *
 pidgin_blist_theme_get_buddy_color_1(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -470,7 +485,7 @@
 	return priv->buddy_bgcolor1;
 }
 
-const GdkColor *
+GdkColor *
 pidgin_blist_theme_get_buddy_color_2(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -482,7 +497,7 @@
 	return priv->buddy_bgcolor2;
 }
 
-const font_color_pair *
+FontColorPair *
 pidgin_blist_theme_get_online_text_info(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -494,7 +509,7 @@
 	return priv->online;
 }
 
-const font_color_pair *
+FontColorPair *
 pidgin_blist_theme_get_away_text_info(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -506,7 +521,7 @@
 	return priv->away;
 }
 
-const font_color_pair *
+FontColorPair *
 pidgin_blist_theme_get_offline_text_info(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -518,7 +533,7 @@
 	return priv->offline;
 }
 
-const font_color_pair *
+FontColorPair *
 pidgin_blist_theme_get_unread_message_text_info(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -530,7 +545,7 @@
 	return priv->message;
 }
 
-const font_color_pair *
+FontColorPair *
 pidgin_blist_theme_get_status_text_info(PidginBlistTheme *theme)
 {
 	PidginBlistThemePrivate *priv;
@@ -542,3 +557,197 @@
 	return priv->status;
 }
 
+/* Set Methods */
+void
+pidgin_blist_theme_set_icon_theme(PidginBlistTheme *theme, const gchar *icon_theme)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	g_free(priv->icon_theme);
+	priv->icon_theme = g_strdup(icon_theme);
+}
+
+void
+pidgin_blist_theme_set_background_color(PidginBlistTheme *theme, GdkColor *color)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	g_free(priv->bgcolor);
+	priv->bgcolor = color;
+}
+
+void
+pidgin_blist_theme_set_opacity(PidginBlistTheme *theme, gdouble opacity)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme) || opacity < 0.0 || opacity > 1.0);
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	priv->opacity = opacity;
+}
+
+void
+pidgin_blist_theme_set_layout(PidginBlistTheme *theme, PidginBlistLayout *layout)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	g_free(priv->layout);
+	priv->layout = layout;
+}
+
+void
+pidgin_blist_theme_set_expanded_background_color(PidginBlistTheme *theme, GdkColor *color)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	g_free(priv->expanded_color);
+	priv->expanded_color = color;
+}
+
+void
+pidgin_blist_theme_set_expanded_text_info(PidginBlistTheme *theme, FontColorPair *pair)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	free_font_and_color(priv->expanded); 
+	priv->expanded = pair;
+}
+
+void
+pidgin_blist_theme_set_collapsed_background_color(PidginBlistTheme *theme, GdkColor *color)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	g_free(priv->collapsed_color);
+	priv->collapsed_color = color;
+}
+
+void
+pidgin_blist_theme_set_collapsed_text_info(PidginBlistTheme *theme, FontColorPair *pair)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	free_font_and_color(priv->collapsed); 
+	priv->collapsed = pair;
+}
+
+void
+pidgin_blist_theme_set_buddy_color_1(PidginBlistTheme *theme, GdkColor *color)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	g_free(priv->buddy_bgcolor1);
+	priv->buddy_bgcolor1 = color;
+}
+
+void
+pidgin_blist_theme_set_buddy_color_2(PidginBlistTheme *theme, GdkColor *color)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	g_free(priv->buddy_bgcolor2);
+	priv->buddy_bgcolor2 = color;
+}
+
+void
+pidgin_blist_theme_set_online_text_info(PidginBlistTheme *theme, FontColorPair *pair)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	free_font_and_color(priv->online); 
+	priv->online = pair;
+}
+
+void
+pidgin_blist_theme_set_away_text_info(PidginBlistTheme *theme, FontColorPair *pair)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	free_font_and_color(priv->away); 
+	priv->away = pair;
+}
+
+void
+pidgin_blist_theme_set_offline_text_info(PidginBlistTheme *theme, FontColorPair *pair)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	free_font_and_color(priv->offline); 
+	priv->offline = pair;
+}
+
+void
+pidgin_blist_theme_set_unread_message_text_info(PidginBlistTheme *theme, FontColorPair *pair)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	free_font_and_color(priv->message); 
+	priv->message = pair;
+}
+
+void
+pidgin_blist_theme_set_status_text_info(PidginBlistTheme *theme, FontColorPair *pair)
+{
+	PidginBlistThemePrivate *priv;
+
+	g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme));
+
+	priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme));
+
+	free_font_and_color(priv->status); 
+	priv->status = pair;
+}
--- a/pidgin/gtkblist-theme.h	Tue Jul 15 06:29:46 2008 +0000
+++ b/pidgin/gtkblist-theme.h	Thu Jul 17 19:40:13 2008 +0000
@@ -65,7 +65,7 @@
 	gchar *font;
 	GdkColor *color;
 
-} font_color_pair;
+} FontColorPair;
 
 typedef struct
 {
@@ -76,11 +76,11 @@
 	gint emblem;
 	gboolean show_status; 
 
-} blist_layout;
+} PidginBlistLayout;
 
 
 /**************************************************************************/
-/** @name Purple Sound Theme API                                          */
+/** @name Purple Buddy List Theme API                                     */
 /**************************************************************************/
 G_BEGIN_DECLS
 
@@ -90,12 +90,20 @@
  */
 GType pidgin_blist_theme_get_type(void);
 
+/* get methods */
 /**
  * Returns the icon theme to be used with the buddy list theme
  *
  * @returns 	the icon theme
  */
-const gchar *pidgin_blist_theme_get_icon_theme(PidginBlistTheme *theme);
+gchar *pidgin_blist_theme_get_icon_theme(PidginBlistTheme *theme);
+
+/**
+ * Returns the background color of the buddy list
+ *
+ * @returns 	a gdk color
+ */
+ GdkColor *pidgin_blist_theme_get_background_color(PidginBlistTheme *theme);
 
 /**
  * Returns the opacity of the buddy list window
@@ -110,84 +118,191 @@
  *
  * @returns 	the buddy list layout
  */
-const blist_layout *pidgin_blist_theme_get_layout(PidginBlistTheme *theme);
+ PidginBlistLayout *pidgin_blist_theme_get_layout(PidginBlistTheme *theme);
 
 /**
  * Returns the background color to be used with expanded groups
  *
- * @returns 	a color
+ * @returns 	a gdk color
  */
-const GdkColor *pidgin_blist_theme_get_expanded_background_color(PidginBlistTheme *theme);
+ GdkColor *pidgin_blist_theme_get_expanded_background_color(PidginBlistTheme *theme);
 
 /**
  * Returns the text font and color to be used with expanded groups
  *
  * @returns 	a font and color pair
  */
-const font_color_pair *pidgin_blist_theme_get_expanded_text_info(PidginBlistTheme *theme);
+ FontColorPair *pidgin_blist_theme_get_expanded_text_info(PidginBlistTheme *theme);
 
 /**
  * Returns the background color to be used with collapsed groups
  *
- * @returns 	a color
+ * @returns 	a gdk color
  */
-const GdkColor *pidgin_blist_theme_get_collapsed_background_color(PidginBlistTheme *theme);
+ GdkColor *pidgin_blist_theme_get_collapsed_background_color(PidginBlistTheme *theme);
 
 /**
  * Returns the text font and color to be used with collapsed groups
  *
  * @returns 	a font and color pair
  */
-const font_color_pair *pidgin_blist_theme_get_collapsed_text_info(PidginBlistTheme *theme);
+ FontColorPair *pidgin_blist_theme_get_collapsed_text_info(PidginBlistTheme *theme);
 
 /**
  * Returns the 1st color to be used for buddys
  *
- * @returns 	a color
+ * @returns 	a gdk color
  */
-const GdkColor *pidgin_blist_theme_get_buddy_color_1(PidginBlistTheme *theme);
+ GdkColor *pidgin_blist_theme_get_buddy_color_1(PidginBlistTheme *theme);
 
 /**
  * Returns the 2nd color to be used for buddies
  *
- * @returns 	a color
+ * @returns 	a gdk color
  */
-const GdkColor *pidgin_blist_theme_get_buddy_color_2(PidginBlistTheme *theme);
+ GdkColor *pidgin_blist_theme_get_buddy_color_2(PidginBlistTheme *theme);
 
 /**
  * Returns the text font and color to be used for online buddies
  *
  * @returns 	a font and color pair
  */
-const font_color_pair *pidgin_blist_theme_get_online_text_info(PidginBlistTheme *theme);
+ FontColorPair *pidgin_blist_theme_get_online_text_info(PidginBlistTheme *theme);
 
 /**
  * Returns the text font and color to be used for away and idle buddies
  *
  * @returns 	a font and color pair
  */
-const font_color_pair *pidgin_blist_theme_get_away_text_info(PidginBlistTheme *theme);
+ FontColorPair *pidgin_blist_theme_get_away_text_info(PidginBlistTheme *theme);
 
 /**
  * Returns the text font and color to be used for offline buddies
  *
  * @returns 	a font and color pair
  */
-const font_color_pair *pidgin_blist_theme_get_offline_text_info(PidginBlistTheme *theme);
+ FontColorPair *pidgin_blist_theme_get_offline_text_info(PidginBlistTheme *theme);
 
 /**
  * Returns the text font and color to be used for buddies with unread messages
  *
  * @returns 	a font and color pair
  */
-const font_color_pair *pidgin_blist_theme_get_unread_message_text_info(PidginBlistTheme *theme);
+ FontColorPair *pidgin_blist_theme_get_unread_message_text_info(PidginBlistTheme *theme);
 
 /**
  * Returns the text font and color to be used for a buddy's status message 
  *
  * @returns 	a font and color pair
  */
-const font_color_pair *pidgin_blist_theme_get_status_text_info(PidginBlistTheme *theme);
+ FontColorPair *pidgin_blist_theme_get_status_text_info(PidginBlistTheme *theme);
+
+/* Set Methods */
+
+/**
+ * Sets the icon theme to be used for this buddy list theme
+ *
+ * @param icon_theme	the new icon theme name
+ */
+void pidgin_blist_theme_set_icon_theme(PidginBlistTheme *theme, const gchar *icon_theme);
+
+/**
+ * Sets the background color to be used for this buddy list theme
+ *
+ * @param color		the new background color
+ */
+void pidgin_blist_theme_set_background_color(PidginBlistTheme *theme, GdkColor *color);
+
+/**
+ * Sets the opacity to be used for this buddy list theme
+ *
+ * @param opacity	the new opacity setting
+ */
+void pidgin_blist_theme_set_opacity(PidginBlistTheme *theme, gdouble opacity);
+
+/**
+ * Sets the buddy list layout to be used for this buddy list theme
+ *
+ * @param layout		the new layout
+ */
+void pidgin_blist_theme_set_layout(PidginBlistTheme *theme, PidginBlistLayout *layout);
+
+/**
+ * Sets the background color to be used for expanded groups
+ *
+ * @param color		the new background color
+ */
+void pidgin_blist_theme_set_expanded_background_color(PidginBlistTheme *theme, GdkColor *color);
+
+/**
+ * Sets the text color and font to be used for expanded groups
+ *
+ * @param pair		the new text font at color pair
+ */
+void pidgin_blist_theme_set_expanded_text_info(PidginBlistTheme *theme, FontColorPair *pair);
+
+/**
+ * Sets the background color to be used for collapsed groups
+ *
+ * @param color		the new background color
+ */
+void pidgin_blist_theme_set_collapsed_background_color(PidginBlistTheme *theme, GdkColor *color);
+
+/**
+ * Sets the text color and font to be used for expanded groups
+ *
+ * @param pair		the new text font at color pair
+ */
+void pidgin_blist_theme_set_collapsed_text_info(PidginBlistTheme *theme, FontColorPair *pair);
+
+/**
+ * Sets the background color to be used for the 1st buddy
+ *
+ * @param color		the color for the 1st buddy
+ */
+void pidgin_blist_theme_set_buddy_color_1(PidginBlistTheme *theme, GdkColor *color);
+
+/**
+ * Sets the background color to be used for the 2nd buddy
+ *
+ * @param color		the color for the 2nd buddy
+ */
+void pidgin_blist_theme_set_buddy_color_2(PidginBlistTheme *theme, GdkColor *color);
+
+/**
+ * Sets the text color and font to be used for online buddies
+ *
+ * @param pair		the new text font at color pair
+ */
+void pidgin_blist_theme_set_online_text_info(PidginBlistTheme *theme, FontColorPair *pair);
+
+/**
+ * Sets the text color and font to be used for away and idle buddies
+ *
+ * @param pair		the new text font at color pair
+ */
+void pidgin_blist_theme_set_away_text_info(PidginBlistTheme *theme, FontColorPair *pair);
+
+/**
+ * Sets the text color and font to be used for offline buddies
+ *
+ * @param pair		the new text font at color pair
+ */
+void pidgin_blist_theme_set_offline_text_info(PidginBlistTheme *theme, FontColorPair *pair);
+
+/**
+ * Sets the text color and font to be used for buddies with an unread message
+ *
+ * @param pair		the new text font at color pair
+ */
+void pidgin_blist_theme_set_unread_message_text_info(PidginBlistTheme *theme, FontColorPair *pair);
+
+/**
+ * Sets the text color and font to be used for buddy status messages
+ *
+ * @param pair		the new text font at color pair
+ */
+void pidgin_blist_theme_set_status_text_info(PidginBlistTheme *theme, FontColorPair *pair);
 
 G_END_DECLS
 #endif /* _PIDGIN_BLIST_THEME_H_ */
--- a/pidgin/gtkblist.c	Tue Jul 15 06:29:46 2008 +0000
+++ b/pidgin/gtkblist.c	Thu Jul 17 19:40:13 2008 +0000
@@ -5980,7 +5980,7 @@
 		GtkTreeIter iter;
 		GtkTreePath *path;
 		gboolean expanded;
-		GdkColor *bgcolor;
+		GdkColor bgcolor;
 		GdkPixbuf *avatar = NULL;
 		PidginBlistTheme *theme;
 
@@ -5989,11 +5989,15 @@
 
 		theme = pidgin_blist_get_theme();
 
-		if(theme == NULL)
+		/*if(theme == NULL){
 			bgcolor = &(gtkblist->treeview->style->bg[GTK_STATE_ACTIVE]);
+	
+		}
 		else if(purple_blist_node_get_bool(gnode, "collapsed"))
 			bgcolor = (pidgin_blist_theme_get_collapsed_text_info(theme))->color;
-		else bgcolor = (pidgin_blist_theme_get_expanded_text_info(theme))->color;
+		else bgcolor = (pidgin_blist_theme_get_expanded_text_info(theme))->color;*/
+
+		g_print("\n\n\%s\n\n", gdk_color_to_string(&bgcolor));
 
 		path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter);
 		expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(gtkblist->treeview), path);
@@ -7233,6 +7237,8 @@
 	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/blist/tooltip_delay", 500);
 	purple_prefs_add_string(PIDGIN_PREFS_ROOT "/blist/theme", "");
 
+	purple_theme_manager_register_type(g_object_new(PIDGIN_TYPE_BLIST_THEME_LOADER, "type", "blist", NULL));
+
 	/* Register our signals */
 	purple_signal_register(gtk_blist_handle, "gtkblist-hiding",
 	                     purple_marshal_VOID__POINTER, NULL, 1,