diff pidgin/gtkutils.c @ 32712:7df79e0d1150

propagate from branch 'im.pidgin.pidgin' (head 874feebb31b13ceb4c6789225711244d51bc8e88) to branch 'im.pidgin.cpw.qulogic.gtk3' (head f99236669b6c0ab1a6de4735d03893bec91f4abe)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Fri, 06 Jan 2012 04:53:52 +0000
parents 126420f99f6f e7441440bed5
children
line wrap: on
line diff
--- a/pidgin/gtkutils.c	Fri Jan 06 02:37:42 2012 +0000
+++ b/pidgin/gtkutils.c	Fri Jan 06 04:53:52 2012 +0000
@@ -71,8 +71,20 @@
 #include "gtkwebviewtoolbar.h"
 #include "pidgin/minidialog.h"
 
+#if !GTK_CHECK_VERSION(2,18,0)
+#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x)
+#define gtk_widget_is_sensitive(x) GTK_WIDGET_IS_SENSITIVE(x)
+#endif
+
+enum {
+	AOP_ICON_COLUMN,
+	AOP_NAME_COLUMN,
+	AOP_DATA_COLUMN,
+	AOP_COLUMN_COUNT
+};
+
 typedef struct {
-	GtkWidget *menu;
+	GtkTreeModel *model;
 	gint default_item;
 } AopMenu;
 
@@ -381,7 +393,7 @@
 	if (to_toggle == NULL)
 		return;
 
-	sensitivity = GTK_WIDGET_IS_SENSITIVE(to_toggle);
+	sensitivity = gtk_widget_is_sensitive(to_toggle);
 
 	gtk_widget_set_sensitive(to_toggle, !sensitivity);
 }
@@ -398,7 +410,7 @@
 		if (element == NULL)
 			continue;
 
-		sensitivity = GTK_WIDGET_IS_SENSITIVE(element);
+		sensitivity = gtk_widget_is_sensitive(element);
 
 		gtk_widget_set_sensitive(element, !sensitivity);
 	}
@@ -410,7 +422,7 @@
 	if (to_toggle == NULL)
 		return;
 
-	if (GTK_WIDGET_VISIBLE(to_toggle))
+	if (gtk_widget_get_visible(to_toggle))
 		gtk_widget_hide(to_toggle);
 	else
 		gtk_widget_show(to_toggle);
@@ -611,68 +623,36 @@
 }
 
 static gpointer
-aop_option_menu_get_selected(GtkWidget *optmenu, GtkWidget **p_item)
+aop_option_menu_get_selected(GtkWidget *optmenu)
 {
-	GtkWidget *menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu));
-	GtkWidget *item = gtk_menu_get_active(GTK_MENU(menu));
-	if (p_item)
-		(*p_item) = item;
-	return item ? g_object_get_data(G_OBJECT(item), "aop_per_item_data") : NULL;
+	gpointer data = NULL;
+	GtkTreeIter iter;
+
+	g_return_val_if_fail(optmenu != NULL, NULL);
+
+	if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(optmenu), &iter))
+		gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(optmenu)),
+		                   &iter, AOP_DATA_COLUMN, &data, -1);
+
+	return data;
 }
 
 static void
 aop_menu_cb(GtkWidget *optmenu, GCallback cb)
 {
-	GtkWidget *item;
-	gpointer per_item_data;
-
-	per_item_data = aop_option_menu_get_selected(optmenu, &item);
-
 	if (cb != NULL) {
-		((void (*)(GtkWidget *, gpointer, gpointer))cb)(item, per_item_data, g_object_get_data(G_OBJECT(optmenu), "user_data"));
+		((void (*)(GtkWidget *, gpointer, gpointer))cb)(optmenu,
+			aop_option_menu_get_selected(optmenu),
+			g_object_get_data(G_OBJECT(optmenu), "user_data"));
 	}
 }
 
-static GtkWidget *
-aop_menu_item_new(GtkSizeGroup *sg, GdkPixbuf *pixbuf, const char *lbl, gpointer per_item_data, const char *data)
+static void
+aop_option_menu_replace_menu(GtkWidget *optmenu, AopMenu *new_aop_menu)
 {
-	GtkWidget *item;
-	GtkWidget *hbox;
-	GtkWidget *image;
-	GtkWidget *label;
-
-	item = gtk_menu_item_new();
-	gtk_widget_show(item);
-
-	hbox = gtk_hbox_new(FALSE, 4);
-	gtk_widget_show(hbox);
-
-	/* Create the image */
-	if (pixbuf == NULL)
-		image = gtk_image_new();
-	else
-		image = gtk_image_new_from_pixbuf(pixbuf);
-	gtk_widget_show(image);
-
-	if (sg)
-		gtk_size_group_add_widget(sg, image);
-
-	/* Create the label */
-	label = gtk_label_new (lbl);
-	gtk_widget_show (label);
-	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
-	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-
-	gtk_container_add(GTK_CONTAINER(item), hbox);
-	gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
-
-	g_object_set_data(G_OBJECT (item), data, per_item_data);
-	g_object_set_data(G_OBJECT (item), "aop_per_item_data", per_item_data);
-
-	pidgin_set_accessible_label(item, label);
-
-	return item;
+	gtk_combo_box_set_model(GTK_COMBO_BOX(optmenu), new_aop_menu->model);
+	gtk_combo_box_set_active(GTK_COMBO_BOX(optmenu), new_aop_menu->default_item);
+	g_free(new_aop_menu);
 }
 
 static GdkPixbuf *
@@ -713,16 +693,17 @@
 static GtkWidget *
 aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data)
 {
-	GtkWidget *optmenu;
-
-	optmenu = gtk_option_menu_new();
+	GtkWidget *optmenu = NULL;
+	GtkCellRenderer *cr = NULL;
+
+	optmenu = gtk_combo_box_new();
 	gtk_widget_show(optmenu);
-	gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), aop_menu->menu);
-
-	if (aop_menu->default_item != -1)
-		gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), aop_menu->default_item);
-
-	g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", aop_menu, (GDestroyNotify)g_free);
+	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(optmenu), cr = gtk_cell_renderer_pixbuf_new(), FALSE);
+	gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(optmenu), cr, "pixbuf", AOP_ICON_COLUMN);
+	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(optmenu), cr = gtk_cell_renderer_text_new(), TRUE);
+	gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(optmenu), cr, "text", AOP_NAME_COLUMN);
+
+	aop_option_menu_replace_menu(optmenu, aop_menu);
 	g_object_set_data(G_OBJECT(optmenu), "user_data", user_data);
 
 	g_signal_connect(G_OBJECT(optmenu), "changed", G_CALLBACK(aop_menu_cb), cb);
@@ -731,32 +712,20 @@
 }
 
 static void
-aop_option_menu_replace_menu(GtkWidget *optmenu, AopMenu *new_aop_menu)
-{
-	if (gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)))
-		gtk_option_menu_remove_menu(GTK_OPTION_MENU(optmenu));
-
-	gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), new_aop_menu->menu);
-
-	if (new_aop_menu->default_item != -1)
-		gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), new_aop_menu->default_item);
-
-	g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", new_aop_menu, (GDestroyNotify)g_free);
-}
-
-static void
 aop_option_menu_select_by_data(GtkWidget *optmenu, gpointer data)
 {
-	guint idx;
-	GList *llItr = NULL;
-
-	for (idx = 0, llItr = GTK_MENU_SHELL(gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)))->children;
-	     llItr != NULL;
-	     llItr = llItr->next, idx++) {
-		if (data == g_object_get_data(G_OBJECT(llItr->data), "aop_per_item_data")) {
-			gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), idx);
-			break;
-		}
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gpointer iter_data;
+	model = gtk_combo_box_get_model(GTK_COMBO_BOX(optmenu));
+	if (gtk_tree_model_get_iter_first(model, &iter)) {
+		do {
+			gtk_tree_model_get(model, &iter, AOP_DATA_COLUMN, &iter_data, -1);
+			if (iter_data == data) {
+				gtk_combo_box_set_active_iter(GTK_COMBO_BOX(optmenu), &iter);
+				return;
+			}
+		} while (gtk_tree_model_iter_next(model, &iter));
 	}
 }
 
@@ -766,21 +735,16 @@
 	AopMenu *aop_menu = NULL;
 	PurplePlugin *plugin;
 	GdkPixbuf *pixbuf = NULL;
-	GtkSizeGroup *sg;
+	GtkTreeIter iter;
+	GtkListStore *ls;
 	GList *p;
-	const char *gtalk_name = NULL, *facebook_name = NULL;
 	int i;
 
+	ls = gtk_list_store_new(AOP_COLUMN_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
+
 	aop_menu = g_malloc0(sizeof(AopMenu));
-	aop_menu->default_item = -1;
-	aop_menu->menu = gtk_menu_new();
-	gtk_widget_show(aop_menu->menu);
-	sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
-	if (purple_find_prpl("prpl-jabber")) {
-		gtalk_name = _("Google Talk");
-		facebook_name = _("Facebook (XMPP)");
-	}
+	aop_menu->default_item = 0;
+	aop_menu->model = GTK_TREE_MODEL(ls);
 
 	for (p = purple_plugins_get_protocols(), i = 0;
 		 p != NULL;
@@ -788,48 +752,14 @@
 
 		plugin = (PurplePlugin *)p->data;
 
-		if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) {
-			char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
-			                                  "16", "google-talk.png", NULL);
-			GtkWidget *item;
-
-			pixbuf = pidgin_pixbuf_new_from_file(filename);
-			g_free(filename);
-
-			gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
-				item = aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber", "protocol"));
-			g_object_set_data(G_OBJECT(item), "fakegoogle", GINT_TO_POINTER(1));
-
-			if (pixbuf)
-				g_object_unref(pixbuf);
-
-			gtalk_name = NULL;
-			i++;
-		}
-
-		if (facebook_name && strcmp(facebook_name, plugin->info->name) < 0) {
-			char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
-			                                  "16", "facebook.png", NULL);
-			GtkWidget *item;
-
-			pixbuf = pidgin_pixbuf_new_from_file(filename);
-			g_free(filename);
-
-			gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
-				item = aop_menu_item_new(sg, pixbuf, facebook_name, "prpl-jabber", "protocol"));
-			g_object_set_data(G_OBJECT(item), "fakefacebook", GINT_TO_POINTER(1));
-
-			if (pixbuf)
-				g_object_unref(pixbuf);
-
-			facebook_name = NULL;
-			i++;
-		}
-
 		pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL);
 
-		gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
-			aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id, "protocol"));
+		gtk_list_store_append(ls, &iter);
+		gtk_list_store_set(ls, &iter,
+		                   AOP_ICON_COLUMN, pixbuf,
+		                   AOP_NAME_COLUMN, plugin->info->name,
+		                   AOP_DATA_COLUMN, plugin->info->id,
+		                   -1);
 
 		if (pixbuf)
 			g_object_unref(pixbuf);
@@ -838,8 +768,6 @@
 			aop_menu->default_item = i;
 	}
 
-	g_object_unref(sg);
-
 	return aop_menu;
 }
 
@@ -853,13 +781,13 @@
 const char *
 pidgin_protocol_option_menu_get_selected(GtkWidget *optmenu)
 {
-	return (const char *)aop_option_menu_get_selected(optmenu, NULL);
+	return (const char *)aop_option_menu_get_selected(optmenu);
 }
 
 PurpleAccount *
 pidgin_account_option_menu_get_selected(GtkWidget *optmenu)
 {
-	return (PurpleAccount *)aop_option_menu_get_selected(optmenu, NULL);
+	return (PurpleAccount *)aop_option_menu_get_selected(optmenu);
 }
 
 static AopMenu *
@@ -871,7 +799,8 @@
 	GdkPixbuf *pixbuf = NULL;
 	GList *list;
 	GList *p;
-	GtkSizeGroup *sg;
+	GtkListStore *ls;
+	GtkTreeIter iter;
 	int i;
 	char buf[256];
 
@@ -880,11 +809,11 @@
 	else
 		list = purple_connections_get_all();
 
+	ls = gtk_list_store_new(AOP_COLUMN_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
+
 	aop_menu = g_malloc0(sizeof(AopMenu));
-	aop_menu->default_item = -1;
-	aop_menu->menu = gtk_menu_new();
-	gtk_widget_show(aop_menu->menu);
-	sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+	aop_menu->default_item = 0;
+	aop_menu->model = GTK_TREE_MODEL(ls);
 
 	for (p = list, i = 0; p != NULL; p = p->next, i++) {
 		if (show_all)
@@ -919,8 +848,12 @@
 					   purple_account_get_protocol_name(account));
 		}
 
-		gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
-			aop_menu_item_new(sg, pixbuf, buf, account, "account"));
+		gtk_list_store_append(ls, &iter);
+		gtk_list_store_set(ls, &iter, 
+		                   AOP_ICON_COLUMN, pixbuf,
+		                   AOP_NAME_COLUMN, buf,
+		                   AOP_DATA_COLUMN, account,
+		                   -1);
 
 		if (pixbuf)
 			g_object_unref(pixbuf);
@@ -929,8 +862,6 @@
 			aop_menu->default_item = i;
 	}
 
-	g_object_unref(sg);
-
 	return aop_menu;
 }
 
@@ -941,7 +872,7 @@
 	PurpleAccount *account;
 	PurpleFilterAccountFunc filter_func;
 
-	account = (PurpleAccount *)aop_option_menu_get_selected(optmenu, NULL);
+	account = (PurpleAccount *)aop_option_menu_get_selected(optmenu);
 	show_all = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(optmenu), "show_all"));
 	filter_func = g_object_get_data(G_OBJECT(optmenu), "filter_func");
 
@@ -1965,6 +1896,15 @@
 	return menuitem;
 }
 
+enum {
+	COMPLETION_DISPLAYED_COLUMN,  /* displayed completion value */
+	COMPLETION_BUDDY_COLUMN,      /* buddy name */
+	COMPLETION_NORMALIZED_COLUMN, /* UTF-8 normalized & casefolded buddy name */
+	COMPLETION_COMPARISON_COLUMN, /* UTF-8 normalized & casefolded value for comparison */
+	COMPLETION_ACCOUNT_COLUMN,    /* account */
+	COMPLETION_COLUMN_COUNT
+};
+
 typedef struct
 {
 	GtkWidget *entry;
@@ -1984,10 +1924,10 @@
 	GValue val2;
 	const char *tmp;
 
-	model = gtk_entry_completion_get_model (completion);
+	model = gtk_entry_completion_get_model(completion);
 
 	val1.g_type = 0;
-	gtk_tree_model_get_value(model, iter, 2, &val1);
+	gtk_tree_model_get_value(model, iter, COMPLETION_NORMALIZED_COLUMN, &val1);
 	tmp = g_value_get_string(&val1);
 	if (tmp != NULL && purple_str_has_prefix(tmp, key))
 	{
@@ -1997,7 +1937,7 @@
 	g_value_unset(&val1);
 
 	val2.g_type = 0;
-	gtk_tree_model_get_value(model, iter, 3, &val2);
+	gtk_tree_model_get_value(model, iter, COMPLETION_COMPARISON_COLUMN, &val2);
 	tmp = g_value_get_string(&val2);
 	if (tmp != NULL && purple_str_has_prefix(tmp, key))
 	{
@@ -2017,11 +1957,11 @@
 	PurpleAccount *account;
 
 	val.g_type = 0;
-	gtk_tree_model_get_value(model, iter, 1, &val);
+	gtk_tree_model_get_value(model, iter, COMPLETION_BUDDY_COLUMN, &val);
 	gtk_entry_set_text(GTK_ENTRY(data->entry), g_value_get_string(&val));
 	g_value_unset(&val);
 
-	gtk_tree_model_get_value(model, iter, 4, &val);
+	gtk_tree_model_get_value(model, iter, COMPLETION_ACCOUNT_COLUMN, &val);
 	account = g_value_get_pointer(&val);
 	g_value_unset(&val);
 
@@ -2058,11 +1998,11 @@
 
 		gtk_list_store_append(store, &iter);
 		gtk_list_store_set(store, &iter,
-				0, completion_entry,
-				1, buddyname,
-				2, normalized_buddyname,
-				3, tmp,
-				4, account,
+				COMPLETION_DISPLAYED_COLUMN, completion_entry,
+				COMPLETION_BUDDY_COLUMN, buddyname,
+				COMPLETION_NORMALIZED_COLUMN, normalized_buddyname,
+				COMPLETION_COMPARISON_COLUMN, tmp,
+				COMPLETION_ACCOUNT_COLUMN, account,
 				-1);
 		g_free(completion_entry);
 		g_free(tmp);
@@ -2083,11 +2023,11 @@
 
 			gtk_list_store_append(store, &iter);
 			gtk_list_store_set(store, &iter,
-					0, completion_entry,
-					1, buddyname,
-					2, normalized_buddyname,
-					3, tmp,
-					4, account,
+					COMPLETION_DISPLAYED_COLUMN, completion_entry,
+					COMPLETION_BUDDY_COLUMN, buddyname,
+					COMPLETION_NORMALIZED_COLUMN, normalized_buddyname,
+					COMPLETION_COMPARISON_COLUMN, tmp,
+					COMPLETION_ACCOUNT_COLUMN, account,
 					-1);
 			g_free(completion_entry);
 			g_free(tmp);
@@ -2099,11 +2039,11 @@
 		/* Add the buddy's name. */
 		gtk_list_store_append(store, &iter);
 		gtk_list_store_set(store, &iter,
-				0, buddyname,
-				1, buddyname,
-				2, normalized_buddyname,
-				3, NULL,
-				4, account,
+				COMPLETION_DISPLAYED_COLUMN, buddyname,
+				COMPLETION_BUDDY_COLUMN, buddyname,
+				COMPLETION_NORMALIZED_COLUMN, normalized_buddyname,
+				COMPLETION_COMPARISON_COLUMN, NULL,
+				COMPLETION_ACCOUNT_COLUMN, account,
 				-1);
 	}
 
@@ -2201,7 +2141,9 @@
 	GtkEntryCompletion *completion;
 
 	data = g_new0(PidginCompletionData, 1);
-	store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
+	store = gtk_list_store_new(COMPLETION_COLUMN_COUNT, G_TYPE_STRING,
+	                           G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+	                           G_TYPE_POINTER);
 
 	data->entry = entry;
 	data->accountopt = accountopt;
@@ -2218,7 +2160,8 @@
 
 	/* Sort the completion list by buddy name */
 	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store),
-	                                     1, GTK_SORT_ASCENDING);
+	                                     COMPLETION_BUDDY_COLUMN,
+	                                     GTK_SORT_ASCENDING);
 
 	completion = gtk_entry_completion_new();
 	gtk_entry_completion_set_match_func(completion, buddyname_completion_match_func, NULL, NULL);
@@ -2232,7 +2175,7 @@
 	gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store));
 	g_object_unref(store);
 
-	gtk_entry_completion_set_text_column(completion, 0);
+	gtk_entry_completion_set_text_column(completion, COMPLETION_DISPLAYED_COLUMN);
 
 	purple_signal_connect(purple_connections_get_handle(), "signed-on", entry,
 						PURPLE_CALLBACK(repopulate_autocomplete), data);
@@ -3067,7 +3010,7 @@
 		windows = g_list_delete_link(windows, windows);
 
 		if (window == widget ||
-				!GTK_WIDGET_VISIBLE(window))
+				!gtk_widget_get_visible(window))
 			continue;
 
 		if (!gdk_property_get(window->window, _WindowTime, _Cardinal, 0, sizeof(time_t), FALSE,
@@ -3121,7 +3064,7 @@
 		windows = g_list_delete_link(windows, windows);
 
 		if (window == widget ||
-				!GTK_WIDGET_VISIBLE(window)) {
+				!gtk_widget_get_visible(window)) {
 			continue;
 		}
 
@@ -3762,4 +3705,3 @@
 	gtk_imhtml_class_register_protocol("mailto:", NULL, NULL);
 	gtk_imhtml_class_register_protocol("gopher://", NULL, NULL);
 }
-