changeset 13860:c1e3f7c75c3f

[gaim-migrate @ 16321] Sean suggested displaying a tooltip in the buddylist (http://gaim.sourceforge.net/sean/gntmock.png). This (http://img157.imageshack.us/img157/1793/q4jb.png) is close. You can press Escape to hide the tooltip. I haven't yet managed to refresh widgets when other widgets covering it are destroyed. So some parts of the border around the buddylist gets erased. I am going to try to fix it. committer: Tailor Script <tailor@pidgin.im>
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Fri, 23 Jun 2006 19:41:31 +0000
parents 60278852c20c
children 55fb5cd9bac9
files console/gntblist.c console/libgnt/gnt-skel.c console/libgnt/gntbox.c console/libgnt/gntbox.h console/libgnt/gntentry.c console/libgnt/gntlabel.c console/libgnt/gntmain.c console/libgnt/gnttree.c console/libgnt/gnttree.h console/libgnt/gntwidget.c console/libgnt/test.c
diffstat 11 files changed, 186 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/console/gntblist.c	Fri Jun 23 16:59:12 2006 +0000
+++ b/console/gntblist.c	Fri Jun 23 19:41:31 2006 +0000
@@ -15,6 +15,9 @@
 	GntWidget *window;
 	GntWidget *tree;
 
+	GntWidget *tooltip;
+	GaimBlistNode *tnode;		/* Who is the tooltip being displayed for? */
+
 	GaimBuddyList *list;
 } GGBlist;
 
@@ -29,6 +32,14 @@
 }
 
 static void
+remove_tooltip(GGBlist *ggblist)
+{
+	gnt_widget_destroy(ggblist->tooltip);
+	ggblist->tooltip = NULL;
+	ggblist->tnode = NULL;
+}
+
+static void
 node_remove(GaimBuddyList *list, GaimBlistNode *node)
 {
 	GGBlist *ggblist = list->ui_data;
@@ -46,6 +57,11 @@
 		if (gaim_blist_get_group_online_count(group) == 0)
 			node_remove(list, (GaimBlistNode*)group);
 	}
+
+	if (ggblist->tnode == node)
+	{
+		remove_tooltip(ggblist);
+	}
 }
 
 static void
@@ -90,9 +106,8 @@
 	GaimBlistNode *node = (GaimBlistNode *)group;
 	if (node->ui_data)
 		return;
-	gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group,
+	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group,
 			group->name, NULL, NULL);
-	node->ui_data = GINT_TO_POINTER(TRUE);
 }
 
 static void
@@ -103,11 +118,11 @@
 	if (node->ui_data)
 		return;
 
-	node->ui_data = GINT_TO_POINTER(TRUE);
 	group = gaim_buddy_get_group(buddy);
 	add_group(group, ggblist);
 
-	gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy, gaim_buddy_get_alias(buddy), group, NULL);
+	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy,
+				gaim_buddy_get_alias(buddy), group, NULL);
 }
 
 static void
@@ -133,14 +148,108 @@
 	gnt_widget_set_focus(widget, FALSE);
 }
 
+static void
+selection_changed(GntWidget *widget, int old, int current, GGBlist *ggblist)
+{
+	GaimBlistNode *node;
+	GntTree *tree = GNT_TREE(widget);
+	int x, y, top, width;
+	GString *str;
+	GaimPlugin *prpl;
+	GaimPluginProtocolInfo *prpl_info;
+	GaimAccount *account;
+	GntWidget *box, *label;
+	char *title;
+
+	if (ggblist->tooltip)
+	{
+		remove_tooltip(ggblist);
+	}
+
+	node = gnt_tree_get_selection_data(tree);
+	if (!node)
+		return;
+
+	str = g_string_new("");
+
+	if (GAIM_BLIST_NODE_IS_BUDDY(node))
+	{
+		GaimBuddy *buddy = (GaimBuddy *)node;
+		account = gaim_buddy_get_account(buddy);
+		
+		g_string_append_printf(str, _("Account: %s"), gaim_account_get_username(account));
+		
+		prpl = gaim_find_prpl(gaim_account_get_protocol_id(account));
+		prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
+		if (prpl_info && prpl_info->tooltip_text)
+		{
+			GString *tip = g_string_new("");
+			char *strip, *br;
+			prpl_info->tooltip_text(buddy, tip, TRUE);
+
+			br = gaim_strreplace(tip->str, "\n", "<br>");
+			strip = gaim_markup_strip_html(br);
+			g_string_append(str, strip);
+			g_string_free(tip, TRUE);
+			g_free(strip);
+			g_free(br);
+		}
+
+		title = g_strdup(gaim_buddy_get_name(buddy));
+	}
+	else
+	{
+		g_string_free(str, TRUE);
+		return;
+	}
+
+	gnt_widget_get_position(widget, &x, &y);
+	gnt_widget_get_size(widget, &width, NULL);
+	top = gnt_tree_get_selection_visible_line(tree);
+
+	x += width;
+	y += top - 1;
+
+	box = gnt_box_new(FALSE, FALSE);
+	gnt_box_set_toplevel(GNT_BOX(box), TRUE);
+	GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW);
+	gnt_box_set_title(GNT_BOX(box), title);
+
+	gnt_box_add_widget(GNT_BOX(box), GNT_WIDGET(gnt_label_new(str->str)));
+
+	gnt_widget_set_position(box, x, y);
+	gnt_widget_draw(box);
+	
+	g_string_free(str, TRUE);
+	ggblist->tooltip = box;
+	ggblist->tnode = node;
+}
+
+static gboolean
+key_pressed(GntWidget *widget, const char *text, GGBlist *ggblist)
+{
+	if (text[0] == 27 && text[1] == 0)
+	{
+		/* Escape was pressed */
+		if (ggblist->tooltip)
+		{
+			gnt_widget_destroy(ggblist->tooltip);
+			ggblist->tooltip = NULL;
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
 void gg_blist_init()
 {
 	ggblist = g_new0(GGBlist, 1);
 
 	gaim_get_blist()->ui_data = ggblist;
+	ggblist->list = gaim_get_blist();
 
 	ggblist->window = gnt_box_new(FALSE, FALSE);
-	GNT_WIDGET_UNSET_FLAGS(ggblist->window, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+	gnt_box_set_toplevel(GNT_BOX(ggblist->window), TRUE);
 	gnt_box_set_title(GNT_BOX(ggblist->window), _("Buddy List"));
 	gnt_box_set_pad(GNT_BOX(ggblist->window), 0);
 
@@ -156,14 +265,19 @@
 	gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-off", gg_blist_get_handle(),
 				GAIM_CALLBACK(buddy_signed_off), ggblist);
 
-	g_signal_connect(G_OBJECT(ggblist->tree), "activate", G_CALLBACK(selection_activate), ggblist);
+#if 0
+	/* These I plan to use to indicate unread-messages etc. */
+	gaim_signal_connect(gaim_conversations_get_handle(), "received-im-msg", gg_blist_get_handle(),
+				GAIM_CALLBACK(received_im_msg), list);
+	gaim_signal_connect(gaim_conversations_get_handle(), "sent-im-msg", gg_blist_get_handle(),
+				GAIM_CALLBACK(sent_im_msg), NULL);
 
-	/*gaim_signal_connect(gaim_conversations_get_handle(), "received-im-msg", gg_blist_get_handle(),*/
-				/*GAIM_CALLBACK(received_im_msg), list);*/
-	/*gaim_signal_connect(gaim_conversations_get_handle(), "sent-im-msg", gg_blist_get_handle(),*/
-				/*GAIM_CALLBACK(sent_im_msg), NULL);*/
+	gaim_signal_connect(gaim_conversations_get_handle(), "received-chat-msg", gg_blist_get_handle(),
+				GAIM_CALLBACK(received_chat_msg), list);
+#endif
 
-	/*gaim_signal_connect(gaim_conversations_get_handle(), "received-chat-msg", gg_blist_get_handle(),*/
-				/*GAIM_CALLBACK(received_chat_msg), list);*/
+	g_signal_connect(G_OBJECT(ggblist->tree), "selection_changed", G_CALLBACK(selection_changed), ggblist);
+	g_signal_connect(G_OBJECT(ggblist->tree), "key_pressed", G_CALLBACK(key_pressed), ggblist);
+	g_signal_connect(G_OBJECT(ggblist->tree), "activate", G_CALLBACK(selection_activate), ggblist);
 }
 
--- a/console/libgnt/gnt-skel.c	Fri Jun 23 16:59:12 2006 +0000
+++ b/console/libgnt/gnt-skel.c	Fri Jun 23 19:41:31 2006 +0000
@@ -39,7 +39,7 @@
 }
 
 static void
-gnt_skel_class_init(GntWidgetClass *klass)
+gnt_skel_class_init(GntSkelClass *klass)
 {
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
--- a/console/libgnt/gntbox.c	Fri Jun 23 16:59:12 2006 +0000
+++ b/console/libgnt/gntbox.c	Fri Jun 23 19:41:31 2006 +0000
@@ -267,7 +267,7 @@
 }
 
 static void
-gnt_box_class_init(GntWidgetClass *klass)
+gnt_box_class_init(GntBoxClass *klass)
 {
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
@@ -351,3 +351,12 @@
 	/* XXX: Perhaps redraw if already showing? */
 }
 
+void gnt_box_set_toplevel(GntBox *box, gboolean set)
+{
+	GntWidget *widget = GNT_WIDGET(box);
+	if (set)
+		GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+	else
+		GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW);
+}
+
--- a/console/libgnt/gntbox.h	Fri Jun 23 16:59:12 2006 +0000
+++ b/console/libgnt/gntbox.h	Fri Jun 23 19:41:31 2006 +0000
@@ -55,6 +55,8 @@
 
 void gnt_box_set_pad(GntBox *box, int pad);
 
+void gnt_box_set_toplevel(GntBox *box, gboolean set);
+
 G_END_DECLS
 
 #endif /* GNT_BOX_H */
--- a/console/libgnt/gntentry.c	Fri Jun 23 16:59:12 2006 +0000
+++ b/console/libgnt/gntentry.c	Fri Jun 23 19:41:31 2006 +0000
@@ -138,7 +138,7 @@
 }
 
 static void
-gnt_entry_class_init(GntWidgetClass *klass)
+gnt_entry_class_init(GntEntryClass *klass)
 {
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
--- a/console/libgnt/gntlabel.c	Fri Jun 23 16:59:12 2006 +0000
+++ b/console/libgnt/gntlabel.c	Fri Jun 23 19:41:31 2006 +0000
@@ -57,7 +57,7 @@
 }
 
 static void
-gnt_label_class_init(GntWidgetClass *klass)
+gnt_label_class_init(GntLabelClass *klass)
 {
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
--- a/console/libgnt/gntmain.c	Fri Jun 23 16:59:12 2006 +0000
+++ b/console/libgnt/gntmain.c	Fri Jun 23 19:41:31 2006 +0000
@@ -90,7 +90,6 @@
 	setlocale(LC_ALL, "");
 	initscr();
 	start_color();
-	/*use_default_colors();*/
 	gnt_init_colors();
 
 	max_x = getmaxx(stdscr);
--- a/console/libgnt/gnttree.c	Fri Jun 23 16:59:12 2006 +0000
+++ b/console/libgnt/gnttree.c	Fri Jun 23 19:41:31 2006 +0000
@@ -1,8 +1,10 @@
 #include "gnttree.h"
+#include "gntutils.h"
 
 enum
 {
-	SIGS = 1,
+	SIG_SELECTION_CHANGED,
+	SIGS,
 };
 
 #define	TAB_SIZE 3
@@ -113,10 +115,18 @@
 	DEBUG;
 }
 
+static void
+tree_selection_changed(GntTree *tree, int old, int current)
+{
+	g_signal_emit(tree, signals[SIG_SELECTION_CHANGED], 0, old, current);
+}
+
 static gboolean
 gnt_tree_key_pressed(GntWidget *widget, const char *text)
 {
 	GntTree *tree = GNT_TREE(widget);
+	int old = tree->current;
+
 	if (text[0] == 27)
 	{
 		if (strcmp(text+1, GNT_KEY_DOWN) == 0 && tree->current < g_list_length(tree->list) - 1)
@@ -141,6 +151,9 @@
 		gnt_widget_activate(widget);
 	}
 
+	if (old != tree->current)
+		tree_selection_changed(tree, old, tree->current);
+
 	return FALSE;
 }
 
@@ -154,7 +167,7 @@
 }
 
 static void
-gnt_tree_class_init(GntWidgetClass *klass)
+gnt_tree_class_init(GntTreeClass *klass)
 {
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
@@ -165,6 +178,15 @@
 	parent_class->size_request = gnt_tree_size_request;
 	parent_class->key_pressed = gnt_tree_key_pressed;
 
+	signals[SIG_SELECTION_CHANGED] = 
+		g_signal_new("selection-changed",
+					 G_TYPE_FROM_CLASS(klass),
+					 G_SIGNAL_RUN_LAST,
+					 G_STRUCT_OFFSET(GntTreeClass, selection_changed),
+					 NULL, NULL,
+					 gnt_closure_marshal_VOID__INT_INT,
+					 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+
 	DEBUG;
 }
 
@@ -271,7 +293,7 @@
 	return dep;
 }
 
-void gnt_tree_add_row_after(GntTree *tree, void *key, const char *text, void *parent, void *bigbro)
+GntTreeRow *gnt_tree_add_row_after(GntTree *tree, void *key, const char *text, void *parent, void *bigbro)
 {
 	GntTreeRow *row = g_new0(GntTreeRow, 1), *pr = NULL;
 
@@ -335,11 +357,13 @@
 
 	if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_MAPPED))
 		redraw_tree(tree);
+
+	return row;
 }
 
 gpointer gnt_tree_get_selection_data(GntTree *tree)
 {
-	return g_list_nth(tree->list, tree->current);
+	return g_list_nth_data(tree->list, tree->current);
 }
 
 int gnt_tree_get_selection_index(GntTree *tree)
@@ -355,9 +379,6 @@
 	{
 		int len, pos;
 
-		g_free(row->text);
-		g_free(row);
-
 		pos = g_list_index(tree->list, key);
 
 		g_hash_table_remove(tree->hash, key);
@@ -367,6 +388,13 @@
 		{
 			redraw_tree(tree);
 		}
+		g_hash_table_replace(tree->hash, key, NULL);
 	}
 }
 
+int gnt_tree_get_selection_visible_line(GntTree *tree)
+{
+	return (tree->current - tree->top) +
+			!!(GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER));
+}
+
--- a/console/libgnt/gnttree.h	Fri Jun 23 16:59:12 2006 +0000
+++ b/console/libgnt/gnttree.h	Fri Jun 23 19:41:31 2006 +0000
@@ -42,6 +42,8 @@
 {
 	GntWidgetClass parent;
 
+	void (*selection_changed)(int old, int current);
+
 	void (*gnt_reserved1)(void);
 	void (*gnt_reserved2)(void);
 	void (*gnt_reserved3)(void);
@@ -60,7 +62,7 @@
 
 void gnt_tree_scroll(GntTree *tree, int count);
 
-void gnt_tree_add_row_after(GntTree *tree, void *key, const char *text, void *parent, void *bigbro);
+GntTreeRow *gnt_tree_add_row_after(GntTree *tree, void *key, const char *text, void *parent, void *bigbro);
 
 gpointer gnt_tree_get_selection_data(GntTree *tree);
 
@@ -68,6 +70,9 @@
 
 void gnt_tree_remove(GntTree *tree, gpointer key);
 
+/* Returns the visible line number of the selected row */
+int gnt_tree_get_selection_visible_line(GntTree *tree);
+
 G_END_DECLS
 
 #endif /* GNT_TREE_H */
--- a/console/libgnt/gntwidget.c	Fri Jun 23 16:59:12 2006 +0000
+++ b/console/libgnt/gntwidget.c	Fri Jun 23 19:41:31 2006 +0000
@@ -221,11 +221,12 @@
 {
 	g_return_if_fail(GNT_IS_WIDGET(obj));
 
+	gnt_widget_hide(obj);
 	delwin(obj->window);
 	if(!(GNT_WIDGET_FLAGS(obj) & GNT_WIDGET_DESTROYING))
 		g_object_run_dispose(G_OBJECT(obj));
 	/* XXX: This may be the wrong place */
-	gnt_screen_remove_widget(obj);
+	/*gnt_screen_remove_widget(obj);*/
 	DEBUG;
 }
 
@@ -309,6 +310,7 @@
 	 * those windows to redraw themselves by emitting the approrpiate
 	 * expose signal. */
 
+	wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL));
 	werase(widget->window);
 	wrefresh(widget->window);
 }
--- a/console/libgnt/test.c	Fri Jun 23 16:59:12 2006 +0000
+++ b/console/libgnt/test.c	Fri Jun 23 19:41:31 2006 +0000
@@ -112,7 +112,7 @@
 
 	gnt_widget_show(hbox);
 
-	/*g_signal_connect(hbox, "key_pressed", G_CALLBACK(key_pressed), widget);*/
+	g_signal_connect(hbox, "key_pressed", G_CALLBACK(key_pressed), tree);
 	g_signal_connect(widget, "activate", G_CALLBACK(button1), hbox);
 	g_signal_connect(widget2, "activate", G_CALLBACK(button2), hbox);