diff pidgin/plugins/themeedit-icon.c @ 26664:5d71de58452c

Make it possible to load non-status icons using a PidginStockIconTheme. For now, just chat-room emblems can be set, but adding other icons should be trivial. WISHLIST (Crazy/Driveby Patch Writers step forward please!): * Move the theme-editor plugin to a subdirectory under plugins/. * Make the 'Save' buttons work, possibly ask for some details when saving (e.g. Author's name etc.)
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Mon, 20 Apr 2009 03:20:15 +0000
parents 7519de6ea00f
children df0915055560
line wrap: on
line diff
--- a/pidgin/plugins/themeedit-icon.c	Sun Apr 19 19:45:53 2009 +0000
+++ b/pidgin/plugins/themeedit-icon.c	Mon Apr 20 03:20:15 2009 +0000
@@ -43,7 +43,7 @@
 	PIDGIN_ICON_SIZE_TANGO_HUGE, /* We don't have huge status icons, it seems! */
 };
 
-static const struct {
+static const struct options {
 	const char *stockid;
 	const char *text;
 } statuses[] = {
@@ -52,50 +52,69 @@
 	{PIDGIN_STOCK_STATUS_BUSY, N_("Busy")},
 	{PIDGIN_STOCK_STATUS_OFFLINE, N_("Offline")},
 	{NULL, NULL}
+}, chatemblems[] = {
+	{PIDGIN_STOCK_STATUS_IGNORED, N_("Ignored")},
+	{PIDGIN_STOCK_STATUS_FOUNDER, N_("Founder")},
+	{PIDGIN_STOCK_STATUS_OPERATOR, N_("Operator")},
+	{PIDGIN_STOCK_STATUS_HALFOP, N_("Half Operator")},
+	{PIDGIN_STOCK_STATUS_VOICE, N_("Voice")},
+	{NULL, NULL}
+};
+
+static const struct {
+	const char *heading;
+	const struct options *options;
+} sections[] = {
+	{N_("Status Icons"), statuses},
+	{N_("Chatroom Embems"), chatemblems},
+	{NULL, NULL}
 };
 
 static PidginStatusIconTheme *
 create_icon_theme(GtkWidget *window)
 {
-	int i, j;
+	int s, i, j;
 	char *dirname = "/tmp";   /* FIXME */
 	PidginStatusIconTheme *theme = g_object_new(PIDGIN_TYPE_STATUS_ICON_THEME, "type", "status-icon",
 				"author", getlogin(),
 				"directory", dirname,
 				NULL);
 
-	for (i = 0; statuses[i].stockid; i++) {
-		GtkWidget *image = g_object_get_data(G_OBJECT(window), statuses[i].stockid);
-		GdkPixbuf *pixbuf = g_object_get_data(G_OBJECT(image), "pixbuf");
-		if (!pixbuf)
-			continue;
-		pidgin_icon_theme_set_icon(PIDGIN_ICON_THEME(theme), statuses[i].stockid,
-				statuses[i].stockid);
-		for (j = 0; stocksizes[j]; j++) {
-			int width, height;
-			GtkIconSize iconsize;
-			char size[8];
-			char *name;
-			GdkPixbuf *scale;
-			GError *error = NULL;
+	for (s = 0; sections[s].heading; s++) {
+		GtkWidget *vbox = g_object_get_data(G_OBJECT(window), sections[s].heading);
+		for (i = 0; sections[s].options[i].stockid; i++) {
+			GtkWidget *image = g_object_get_data(G_OBJECT(vbox), sections[s].options[i].stockid);
+			GdkPixbuf *pixbuf = g_object_get_data(G_OBJECT(image), "pixbuf");
+			if (!pixbuf)
+				continue;
+			pidgin_icon_theme_set_icon(PIDGIN_ICON_THEME(theme), sections[s].options[i].stockid,
+					sections[s].options[i].stockid);
+			for (j = 0; stocksizes[j]; j++) {
+				int width, height;
+				GtkIconSize iconsize;
+				char size[8];
+				char *name;
+				GdkPixbuf *scale;
+				GError *error = NULL;
 
-			iconsize = gtk_icon_size_from_name(stocksizes[j]);
-			gtk_icon_size_lookup(iconsize, &width, &height);
-			g_snprintf(size, sizeof(size), "%d", width);
+				iconsize = gtk_icon_size_from_name(stocksizes[j]);
+				gtk_icon_size_lookup(iconsize, &width, &height);
+				g_snprintf(size, sizeof(size), "%d", width);
 
-			if (i == 0) {
-				name = g_build_filename(dirname, size, NULL);
-				purple_build_dir(name, S_IRUSR | S_IWUSR | S_IXUSR);
+				if (i == 0) {
+					name = g_build_filename(dirname, size, NULL);
+					purple_build_dir(name, S_IRUSR | S_IWUSR | S_IXUSR);
+					g_free(name);
+				}
+
+				name = g_build_filename(dirname, size, sections[s].options[i].stockid, NULL);
+				scale = gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR);
+				gdk_pixbuf_save(scale, name, "png", &error, "compression", "9", NULL);
 				g_free(name);
+				g_object_unref(G_OBJECT(scale));
+				if (error)
+					g_error_free(error);
 			}
-
-			name = g_build_filename(dirname, size, statuses[i].stockid, NULL);
-			scale = gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR);
-			gdk_pixbuf_save(scale, name, "png", &error, "compression", "9", NULL);
-			g_free(name);
-			g_object_unref(G_OBJECT(scale));
-			if (error)
-				g_error_free(error);
 		}
 	}
 	return theme;
@@ -104,8 +123,21 @@
 static void
 use_icon_theme(GtkWidget *w, GtkWidget *window)
 {
+	/* I don't quite understand the icon-theme stuff. For example, I don't
+	 * know why PidginIconTheme needs to be abstract, or how PidginStatusIconTheme
+	 * would be different from other PidginIconTheme's (e.g. PidginStockIconTheme)
+	 * etc., but anyway, this works for now.
+	 *
+	 * Here's an interesting note: A PidginStatusIconTheme can be used for both
+	 * stock and status icons. Like I said, I don't quite know how they could be
+	 * different. So I am going to just keep it as it is, for now anyway, until I
+	 * have the time to dig through this, or someone explains this stuff to me
+	 * clearly.
+	 *		-- Sad
+	 */
 	PidginStatusIconTheme *theme = create_icon_theme(window);
 	pidgin_stock_load_status_icon_theme(PIDGIN_STATUS_ICON_THEME(theme));
+	pidgin_stock_load_stock_icon_theme((PidginStockIconTheme *)theme);
 	pidgin_blist_refresh(purple_get_blist());
 	g_object_unref(theme);
 }
@@ -123,8 +155,12 @@
 	GError *error = NULL;
 	GdkPixbuf *scale;
 	int i;
-	GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename, &error);
+	GdkPixbuf *pixbuf;
 
+	if (!filename)
+		return;
+
+	pixbuf = gdk_pixbuf_new_from_file(filename, &error);
 	if (error || !pixbuf) {
 		purple_debug_error("theme-editor-icon", "Unable to load icon file '%s' (%s)\n",
 				filename, error ? error->message : "Reason unknown");
@@ -171,41 +207,47 @@
 	GtkWidget *dialog;
 	GtkWidget *box, *vbox;
 	GtkSizeGroup *sizegroup;
-	int i, j;
+	int s, i, j;
 	dialog = pidgin_create_dialog(_("Pidgin Icon Theme Editor"), 0, "theme-editor-icon", FALSE);
 	box = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(dialog), FALSE, PIDGIN_HIG_BOX_SPACE);
 
-	vbox = pidgin_make_frame(box, _("Status Icons"));
 	sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 
-	for (i = 0; statuses[i].stockid; i++) {
-		const char *id = statuses[i].stockid;
-		const char *text = _(statuses[i].text);
+	for (s = 0; sections[s].heading; s++) {
+		const char *heading = sections[s].heading;
+
+		vbox = pidgin_make_frame(box, heading);
+		g_object_set_data(G_OBJECT(dialog), heading, vbox);
 
-		GtkWidget *hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_CAT_SPACE);
-		GtkWidget *label = gtk_label_new(text);
-		GtkWidget *image = gtk_image_new_from_stock(id,
-				gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL));
-		GtkWidget *ebox = gtk_event_box_new();
-		gtk_container_add(GTK_CONTAINER(ebox), image);
-		gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+		for (i = 0; sections[s].options[i].stockid; i++) {
+			const char *id = sections[s].options[i].stockid;
+			const char *text = _(sections[s].options[i].text);
+
+			GtkWidget *hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_CAT_SPACE);
+			GtkWidget *label = gtk_label_new(text);
+			GtkWidget *image = gtk_image_new_from_stock(id,
+					gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL));
+			GtkWidget *ebox = gtk_event_box_new();
+			gtk_container_add(GTK_CONTAINER(ebox), image);
+			gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 
-		g_signal_connect(G_OBJECT(ebox), "button-press-event", G_CALLBACK(change_stock_image), image);
-		g_object_set_data(G_OBJECT(image), "property-name", (gpointer)id);
+			g_signal_connect(G_OBJECT(ebox), "button-press-event", G_CALLBACK(change_stock_image), image);
+			g_object_set_data(G_OBJECT(image), "property-name", (gpointer)id);
 
-		gtk_size_group_add_widget(sizegroup, label);
-		gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-		gtk_box_pack_start(GTK_BOX(hbox), ebox, FALSE, FALSE, 0);
+			gtk_size_group_add_widget(sizegroup, label);
+			gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+			gtk_box_pack_start(GTK_BOX(hbox), ebox, FALSE, FALSE, 0);
 
-		for (j = 0; stocksizes[j]; j++) {
-			GtkWidget *sh = gtk_image_new_from_stock(id, gtk_icon_size_from_name(stocksizes[j]));
-			gtk_box_pack_start(GTK_BOX(hbox), sh, FALSE, FALSE, 0);
-			g_object_set_data(G_OBJECT(image), stocksizes[j], sh);
+			for (j = 0; stocksizes[j]; j++) {
+				GtkWidget *sh = gtk_image_new_from_stock(id, gtk_icon_size_from_name(stocksizes[j]));
+				gtk_box_pack_start(GTK_BOX(hbox), sh, FALSE, FALSE, 0);
+				g_object_set_data(G_OBJECT(image), stocksizes[j], sh);
+			}
+
+			gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+			g_object_set_data(G_OBJECT(vbox), id, image);
 		}
-
-		gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-
-		g_object_set_data(G_OBJECT(dialog), id, image);
 	}
 
 	gtk_dialog_set_has_separator(GTK_DIALOG(dialog), TRUE);