changeset 21691:3ed9b027479d

Add support for colour in gnttreerows, and colourise the blist. Fixes #1490
author Richard Nelson <wabz@pidgin.im>
date Fri, 30 Nov 2007 03:17:07 +0000
parents 33285f8f68ba
children ef03d2f7a5a7
files doc/finch.1.in finch/gntblist.c finch/libgnt/gntcolors.c finch/libgnt/gntcolors.h finch/libgnt/gntstyle.c finch/libgnt/gntstyle.h finch/libgnt/gnttree.c finch/libgnt/gnttree.h
diffstat 8 files changed, 180 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/doc/finch.1.in	Thu Nov 29 23:21:14 2007 +0000
+++ b/doc/finch.1.in	Fri Nov 30 03:17:07 2007 +0000
@@ -135,6 +135,18 @@
 .TP
 A sample file looks like:
 .br
+[Finch]
+.br
+online-color: green; black
+.br
+away-color: blue; black
+.br
+idle-color: gray; black
+.br
+offline-color: red; black
+.br
+#See below for details on color
+.br
 [general]
 .br
 shadow = 0
--- a/finch/gntblist.c	Thu Nov 29 23:21:14 2007 +0000
+++ b/finch/gntblist.c	Fri Nov 30 03:17:07 2007 +0000
@@ -27,6 +27,7 @@
 
 #include <account.h>
 #include <blist.h>
+#include <curses.h>
 #include <notify.h>
 #include <request.h>
 #include <savedstatuses.h>
@@ -37,6 +38,7 @@
 #include "debug.h"
 
 #include "gntbox.h"
+#include "gntcolors.h"
 #include "gntcombobox.h"
 #include "gntentry.h"
 #include "gntft.h"
@@ -46,6 +48,7 @@
 #include "gntmenuitem.h"
 #include "gntmenuitemcheck.h"
 #include "gntpounce.h"
+#include "gntstyle.h"
 #include "gnttree.h"
 #include "gntutils.h"
 #include "gntwindow.h"
@@ -124,6 +127,11 @@
 static int blist_node_compare_status(PurpleBlistNode *n1, PurpleBlistNode *n2);
 static int blist_node_compare_log(PurpleBlistNode *n1, PurpleBlistNode *n2);
 
+static int color_available;
+static int color_away;
+static int color_offline;
+static int color_idle;
+
 static gboolean
 is_contact_online(PurpleContact *contact)
 {
@@ -615,12 +623,20 @@
 	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy,
 				gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)),
 				contact, NULL);
+
 	if (purple_presence_is_idle(purple_buddy_get_presence(buddy))) {
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, GNT_TEXT_FLAG_DIM);
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, GNT_TEXT_FLAG_DIM);
-	} else {
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, 0);
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, 0);
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), buddy, color_idle);
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_idle);
+	} else if (purple_presence_is_available(purple_buddy_get_presence(buddy)) && color_available) {
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), buddy, color_available);
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_available);
+	} else if (purple_presence_is_online(purple_buddy_get_presence(buddy)) &&
+			!purple_presence_is_available(purple_buddy_get_presence(buddy)) && color_away) {
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), buddy, color_away);
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_away);
+	} else if (!purple_presence_is_online(purple_buddy_get_presence(buddy)) && color_offline) {
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), buddy, color_offline);
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_offline);
 	}
 }
 
@@ -1557,18 +1573,33 @@
 		draw_tooltip(ggblist);
 
 	if (purple_presence_is_idle(purple_buddy_get_presence(buddy))) {
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, bflag | GNT_TEXT_FLAG_DIM);
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), buddy, color_idle);
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_idle);
+		if (buddy == purple_contact_get_priority_buddy(contact))
+			gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_idle);
+	} else if (purple_presence_is_available(purple_buddy_get_presence(buddy)) && color_available) {
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), buddy, color_available);
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_available);
 		if (buddy == purple_contact_get_priority_buddy(contact))
-			gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, cflag | GNT_TEXT_FLAG_DIM);
-		else
+			gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_available);
+	} else if (purple_presence_is_online(purple_buddy_get_presence(buddy)) &&
+			!purple_presence_is_available(purple_buddy_get_presence(buddy)) && color_away) {
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), buddy, color_away);
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_away);
+		if (buddy == purple_contact_get_priority_buddy(contact))
+			gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_away);
+	} else if (!purple_presence_is_online(purple_buddy_get_presence(buddy)) && color_offline) {
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), buddy, color_offline);
+		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_offline);
+		if (buddy == purple_contact_get_priority_buddy(contact))
+			gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color_offline);
+	}
+	gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, bflag);
+	if (buddy == purple_contact_get_priority_buddy(contact))
+		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, cflag);
+
+	if (buddy != purple_contact_get_priority_buddy(contact))
 			update_buddy_display(purple_contact_get_priority_buddy(contact), ggblist);
-	} else {
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, bflag);
-		if (buddy == purple_contact_get_priority_buddy(contact))
-			gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, cflag);
-		else
-			update_buddy_display(purple_contact_get_priority_buddy(contact), ggblist);
-	}
 }
 
 static void
@@ -1736,8 +1767,43 @@
 	draw_tooltip(ggblist);
 }
 
+static int
+get_color(char *key)
+{
+#if GLIB_CHECK_VERSION(2,6,0)
+	int fg = 0, bg = 0;
+	gsize n;
+	char **vals;
+	vals = gnt_style_get_string_list(NULL, key, &n);
+	if (vals && n == 2) {
+		fg = gnt_colors_get_color(vals[0]);
+		bg = gnt_colors_get_color(vals[1]);
+		return gnt_color_add_pair(fg, bg);
+	}
+	return 0;
+#else
+	return 0;
+#endif
+}
+
 void finch_blist_init()
 {
+	short fg, bg;
+	if (has_colors()) {
+		pair_content(GNT_COLOR_NORMAL, &fg, &bg);
+		color_available = get_color("color-available");
+		if (!color_available)
+			color_available = gnt_color_add_pair(COLOR_GREEN, bg);
+		color_away = get_color("color-away");
+		if (!color_away)
+			color_away = gnt_color_add_pair(COLOR_BLUE, bg);
+		color_idle = get_color("color-idle");
+		if (!color_idle)
+			color_idle = gnt_color_add_pair(COLOR_CYAN, bg);
+		color_offline = get_color("color-offline");
+		if (!color_offline)
+			color_offline = gnt_color_add_pair(COLOR_RED, bg);
+	}
 	purple_prefs_add_none(PREF_ROOT);
 	purple_prefs_add_none(PREF_ROOT "/size");
 	purple_prefs_add_int(PREF_ROOT "/size/width", 20);
@@ -2550,4 +2616,3 @@
 {
 	gnt_widget_set_size(ggblist->window, width, height);
 }
-
--- a/finch/libgnt/gntcolors.c	Thu Nov 29 23:21:14 2007 +0000
+++ b/finch/libgnt/gntcolors.c	Fri Nov 30 03:17:07 2007 +0000
@@ -33,6 +33,7 @@
 #include <string.h>
 
 static gboolean hascolors;
+static int custom_type = GNT_COLORS;
 static struct
 {
 	short r, g, b;
@@ -137,8 +138,8 @@
 }
 
 #if GLIB_CHECK_VERSION(2,6,0)
-static int
-get_color(char *key)
+int
+gnt_colors_get_color(char *key)
 {
 	int color;
 	gboolean custom = can_use_custom_color();
@@ -196,7 +197,7 @@
 				int color = -1;
 
 				key = g_ascii_strdown(key, -1);
-				color = get_color(key);
+				color = gnt_colors_get_color(key);
 				g_free(key);
 				if (color == -1)
 					continue;
@@ -237,8 +238,8 @@
 			GntColorType type = 0;
 			gchar *fgc = g_ascii_strdown(list[0], -1);
 			gchar *bgc = g_ascii_strdown(list[1], -1);
-			int fg = get_color(fgc);
-			int bg = get_color(bgc);
+			int fg = gnt_colors_get_color(fgc);
+			int bg = gnt_colors_get_color(bgc);
 			g_free(fgc);
 			g_free(bgc);
 			if (fg == -1 || bg == -1)
@@ -287,3 +288,8 @@
 		  pair == GNT_COLOR_TITLE_D || pair == GNT_COLOR_DISABLED) ? 0 : A_STANDOUT));
 }
 
+int gnt_color_add_pair(int fg, int bg)
+{
+	init_pair(custom_type, fg, bg);
+	return custom_type++;
+}
--- a/finch/libgnt/gntcolors.h	Thu Nov 29 23:21:14 2007 +0000
+++ b/finch/libgnt/gntcolors.h	Fri Nov 30 03:17:07 2007 +0000
@@ -86,6 +86,16 @@
  */
 void gnt_color_pairs_parse(GKeyFile *kfile);
 
+/**
+ * Parse a string color
+ *
+ * @param kfile The string value
+ *
+ * @return A color
+ *
+ * @since 2.3.1 (gnt), 2.3.1 (pidgin)
+ */
+int gnt_colors_get_color(char *key);
 #endif
 
 /**
@@ -101,4 +111,15 @@
  */
 int gnt_color_pair(int color);
 
+/**
+ * Adds a color definition
+ *
+ * @param fg   Foreground
+ * @param bg   Background
+ *
+ * @return  A color pair
+ *
+ * @since 2.3.1
+ */
+int gnt_color_add_pair(int fg, int bg);
 #endif
--- a/finch/libgnt/gntstyle.c	Thu Nov 29 23:21:14 2007 +0000
+++ b/finch/libgnt/gntstyle.c	Fri Nov 30 03:17:07 2007 +0000
@@ -59,6 +59,21 @@
 #endif
 }
 
+char **gnt_style_get_string_list(const char *group, const char *key, gsize *length)
+{
+#if GLIB_CHECK_VERSION(2,6,0)
+	const char *prg = g_get_prgname();
+	if ((group == NULL || *group == '\0') && prg &&
+			g_key_file_has_group(gkfile, prg))
+		group = prg;
+	if (!group)
+		group = "general";
+	return g_key_file_get_string_list(gkfile, group, key, length, NULL);
+#else
+	return NULL;
+#endif
+}
+
 gboolean gnt_style_get_bool(GntStyle style, gboolean def)
 {
 	const char * str;
--- a/finch/libgnt/gntstyle.h	Thu Nov 29 23:21:14 2007 +0000
+++ b/finch/libgnt/gntstyle.h	Fri Nov 30 03:17:07 2007 +0000
@@ -65,6 +65,20 @@
 char *gnt_style_get_from_name(const char *group, const char *key);
 
 /**
+ * Get the value of a preference in ~/.gntrc.
+ *
+ * @param group   The name of the group in the keyfile. If @c NULL, the prgname
+ *                will be used first, if available. Otherwise, "general" will be used.
+ * @param key     The key
+ * @param length  Return location for the number of strings returned, or NULL
+ *
+ * @return        NULL terminated string array. The array should be freed with g_strfreev().
+ *
+ * @since 2.3.1 (gnt), 2.3.1 (pidgin)
+ */
+char **gnt_style_get_string_list(const char *group, const char *key, gsize *length);
+
+/**
  * Parse a boolean preference. For example, if 'value' is "false" (ignoring case)
  * or "0", the return value will be @c FALSE, otherwise @c TRUE.
  *
--- a/finch/libgnt/gnttree.c	Thu Nov 29 23:21:14 2007 +0000
+++ b/finch/libgnt/gnttree.c	Fri Nov 30 03:17:07 2007 +0000
@@ -75,6 +75,7 @@
 	                               If choice is true, then child will be NULL */
 	gboolean isselected;
 	GntTextFormatFlags flags;
+	int color;
 
 	GntTreeRow *parent;
 	GntTreeRow *child;
@@ -522,9 +523,14 @@
 		else
 		{
 			if (flags & GNT_TEXT_FLAG_DIM)
-				attr |= (A_DIM | gnt_color_pair(GNT_COLOR_DISABLED));
+				if (row->color)
+					attr |= (A_DIM | gnt_color_pair(row->color));
+				else
+					attr |= (A_DIM | gnt_color_pair(GNT_COLOR_DISABLED));
 			else if (flags & GNT_TEXT_FLAG_HIGHLIGHT)
 				attr |= (A_DIM | gnt_color_pair(GNT_COLOR_HIGHLIGHT));
+			else if (row->color)
+				attr |= gnt_color_pair(row->color);
 			else
 				attr |= gnt_color_pair(GNT_COLOR_NORMAL);
 		}
@@ -1559,6 +1565,16 @@
 	redraw_tree(tree);	/* XXX: It shouldn't be necessary to redraw the whole darned tree */
 }
 
+void gnt_tree_set_row_color(GntTree *tree, void *key, int color)
+{
+	GntTreeRow *row = g_hash_table_lookup(tree->hash, key);
+	if (!row || row->color == color)
+		return;
+
+	row->color = color;
+	redraw_tree(tree);
+}
+
 void gnt_tree_set_selected(GntTree *tree , void *key)
 {
 	int dist;
--- a/finch/libgnt/gnttree.h	Thu Nov 29 23:21:14 2007 +0000
+++ b/finch/libgnt/gnttree.h	Fri Nov 30 03:17:07 2007 +0000
@@ -325,6 +325,15 @@
 void gnt_tree_set_row_flags(GntTree *tree, void *key, GntTextFormatFlags flags);
 
 /**
+ * Set color for the text in a row in the tree.
+ *
+ * @param tree   The tree
+ * @param key    The key for the row
+ * @param color  The color
+ */
+void gnt_tree_set_row_color(GntTree *, void *, int);
+
+/**
  * Select a row.
  *
  * @param tree  The tree