changeset 23137:53b3c75c9e26

Separate the custom smileys from the regular smileys, and add a 'Manage' button in the smiley dialog for the custom smileys. This should make it more obvious that custom smileys are supported (do we actually want it to be? ;) )
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Sun, 11 May 2008 04:04:35 +0000
parents 3f39147884ce
children b37b9e53a31b
files libpurple/smiley.c pidgin/gtkimhtmltoolbar.c
diffstat 2 files changed, 85 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/smiley.c	Sat May 10 17:05:25 2008 +0000
+++ b/libpurple/smiley.c	Sun May 11 04:04:35 2008 +0000
@@ -300,6 +300,7 @@
 };
 
 static guint signals[SIG_LAST];
+static GObjectClass *parent_class;
 
 static void
 purple_smiley_init(GTypeInstance *instance, gpointer klass)
@@ -366,7 +367,6 @@
 purple_smiley_finalize(GObject *obj)
 {
 	PurpleSmiley *smiley = PURPLE_SMILEY(obj);
-	g_signal_emit(obj, signals[SIG_DESTROY], 0);
 
 	if (g_hash_table_lookup(smiley_shortcut_index, smiley->shortcut)) {
 		g_hash_table_remove(smiley_shortcut_index, smiley->shortcut);
@@ -383,14 +383,24 @@
 }
 
 static void
+purple_smiley_dispose(GObject *gobj)
+{
+	g_signal_emit(gobj, signals[SIG_DESTROY], 0);
+	parent_class->dispose(gobj);
+}
+
+static void
 purple_smiley_class_init(PurpleSmileyClass *klass)
 {
 	GObjectClass *gobj_class = G_OBJECT_CLASS(klass);
 	GParamSpec *pspec;
 
+	parent_class = g_type_class_peek_parent(klass);
+
 	gobj_class->get_property = purple_smiley_get_property;
 	gobj_class->set_property = purple_smiley_set_property;
 	gobj_class->finalize = purple_smiley_finalize;
+	gobj_class->dispose = purple_smiley_dispose;
 
 	/* Shortcut */
 	pspec = g_param_spec_string(PROP_SHORTCUT_S, _("Shortcut"),
--- a/pidgin/gtkimhtmltoolbar.c	Sat May 10 17:05:25 2008 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Sun May 11 04:04:35 2008 +0000
@@ -580,8 +580,7 @@
 }
 
 static gboolean
-close_smiley_dialog(GtkWidget *widget, GdkEvent *event,
-					GtkIMHtmlToolbar *toolbar)
+close_smiley_dialog(GtkIMHtmlToolbar *toolbar)
 {
 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->smiley), FALSE);
 	return FALSE;
@@ -602,13 +601,14 @@
 
 	g_free(escaped_smiley);
 
-	close_smiley_dialog(NULL, NULL, toolbar);
+	close_smiley_dialog(toolbar);
 }
 
 /* smiley buttons list */
 struct smiley_button_list {
 	int width, height;
 	GtkWidget *button;
+	const GtkIMHtmlSmiley *smiley;
 	struct smiley_button_list *next;
 };
 
@@ -624,6 +624,7 @@
 	struct smiley_button_list *it, *it_last;
 	const gchar *filename = smiley->file;
 	gchar *face = smiley->smile;
+	PurpleSmiley *psmiley = NULL;
 
 	cur = g_new0(struct smiley_button_list, 1);
 	it = ls;
@@ -673,31 +674,26 @@
 	/* these look really weird with borders */
 	gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
 
+	psmiley = purple_smileys_find_by_shortcut(smiley->smile);
 	/* If this is a "non-custom" smiley, check to see if its shortcut is
 	  "shadowed" by any custom smiley. This can only happen if the connection
 	  is custom smiley-enabled */
-	if (!(smiley->flags & GTK_IMHTML_SMILEY_CUSTOM)) {
-		/* Perhaps using purple_smileys_find_by_shortcut can be used instead? -- sadrul */
-		for (; custom_smileys ; custom_smileys = g_slist_next(custom_smileys)) {
-			const GtkIMHtmlSmiley *custom_smiley = (GtkIMHtmlSmiley *) custom_smileys->data;
-			const gchar *shortcut = custom_smiley->smile;
-
-			if (strcmp(face, shortcut) == 0) {
-				/* The smiley of the current button has the same shortcut as
-				this custom smiley, grey it out */
-				gtk_tooltips_set_tip(toolbar->tooltips, button,
-						_("This smiley is disabled because a custom smiley exists for this shortcut."),
-						NULL);
-				gtk_widget_set_sensitive(button, FALSE);
-				break;
-			}
-		}
+	if (psmiley && !(smiley->flags & GTK_IMHTML_SMILEY_CUSTOM)) {
+		gtk_tooltips_set_tip(toolbar->tooltips, button,
+				_("This smiley is disabled because a custom smiley exists for this shortcut."),
+				NULL);
+		gtk_widget_set_sensitive(button, FALSE);
+	} else if (psmiley) {
+		/* Remove the button if the smiley is destroyed */
+		g_signal_connect_object(G_OBJECT(psmiley), "destroy", G_CALLBACK(gtk_widget_destroy),
+				button, G_CONNECT_SWAPPED);
 	}
 
 	/* set current element to add */
 	cur->height = size.height;
 	cur->width = size.width;
 	cur->button = button;
+	cur->smiley = smiley;
 	cur->next = ls;
 
 	/* check where to insert by height */
@@ -730,7 +726,7 @@
 	if ((event->type == GDK_KEY_PRESS && event->key.keyval == GDK_Escape) ||
 	    (event->type == GDK_BUTTON_PRESS && event->button.button == 1))
 	{
-		close_smiley_dialog(NULL, NULL, toolbar);
+		close_smiley_dialog(toolbar);
 		return TRUE;
 	}
 
@@ -738,12 +734,41 @@
 }
 
 static void
+add_smiley_list(GtkWidget *container, struct smiley_button_list *list,
+		int max_width, gboolean custom)
+{
+	GtkWidget *line;
+	int line_width = 0;
+
+	if (!list)
+		return;
+
+	line = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(container), line, FALSE, FALSE, 0);
+	for (; list; list = list->next) {
+		if (custom != !!(list->smiley->flags & GTK_IMHTML_SMILEY_CUSTOM))
+			continue;
+		gtk_box_pack_start(GTK_BOX(line), list->button, FALSE, FALSE, 0);
+		gtk_widget_show(list->button);
+		line_width += list->width;
+		if (line_width >= max_width) {
+			if (list->next) {
+				line = gtk_hbox_new(FALSE, 0);
+				gtk_box_pack_start(GTK_BOX(container), line, FALSE, FALSE, 0);
+			}
+			line_width = 0;
+		}
+	}
+}
+
+static void
 insert_smiley_cb(GtkWidget *smiley, GtkIMHtmlToolbar *toolbar)
 {
 	GtkWidget *dialog;
 	GtkWidget *smiley_table = NULL;
 	GSList *smileys, *unique_smileys = NULL;
 	const GSList *custom_smileys = NULL;
+	gboolean supports_custom = FALSE;
 
 	if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(smiley))) {
 		destroy_smiley_dialog(toolbar);
@@ -765,9 +790,8 @@
 		}
 		smileys = smileys->next;
 	}
-
-	if (toolbar->imhtml &&
-			(gtk_imhtml_get_format_functions(GTK_IMHTML(toolbar->imhtml)) & GTK_IMHTML_CUSTOM_SMILEY)) {
+	supports_custom = (gtk_imhtml_get_format_functions(GTK_IMHTML(toolbar->imhtml)) & GTK_IMHTML_CUSTOM_SMILEY);
+	if (toolbar->imhtml && supports_custom) {
 		const GSList *iterator = NULL;
 		custom_smileys = pidgin_smileys_get_all();
 
@@ -783,20 +807,27 @@
 	gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
 
 	if (unique_smileys != NULL) {
-		struct smiley_button_list *ls, *it, *it_tmp;
-		GtkWidget *line;
-		int line_width = 0;
-		int max_line_width, num_lines;
-		int col=0;
+		struct smiley_button_list *ls;
+		int max_line_width, num_lines, button_width = 0;
 
 		/* We use hboxes packed in a vbox */
 		ls = NULL;
-		line = gtk_hbox_new(FALSE, 0);
-		line_width = 0;
 		max_line_width = 0;
 		num_lines = floor(sqrt(g_slist_length(unique_smileys)));
 		smiley_table = gtk_vbox_new(FALSE, 0);
 
+		if (supports_custom) {
+			GtkWidget *manage = gtk_button_new_with_mnemonic(_("_Manage custom smileys"));
+			GtkRequisition req;
+			g_signal_connect(G_OBJECT(manage), "clicked",
+					G_CALLBACK(pidgin_smiley_manager_show), NULL);
+			g_signal_connect_swapped(G_OBJECT(manage), "clicked",
+					G_CALLBACK(gtk_widget_destroy), dialog);
+			gtk_box_pack_end(GTK_BOX(smiley_table), manage, TRUE, FALSE, 0);
+			gtk_widget_size_request(manage, &req);
+			button_width = req.width;
+		}
+
 		/* create list of smileys sorted by height */
 		while (unique_smileys) {
 			GtkIMHtmlSmiley *smiley = (GtkIMHtmlSmiley *) unique_smileys->data;
@@ -805,26 +836,20 @@
 			}
 			unique_smileys = g_slist_delete_link(unique_smileys, unique_smileys);
 		}
+		/* The window will be at least as wide as the 'Manage ..' button */
+		max_line_width = MAX(button_width, max_line_width / num_lines);
+
 		/* pack buttons of the list */
-		max_line_width = max_line_width / num_lines;
-		it = ls;
-		while (it != NULL)
-		{
-			it_tmp = it;
-			gtk_box_pack_start(GTK_BOX(line), it->button, FALSE, FALSE, 0);
-			gtk_widget_show(it->button);
-			line_width += it->width;
-			if (line_width >= max_line_width) {
-				gtk_box_pack_start(GTK_BOX(smiley_table), line, FALSE, FALSE, 0);
-				line = gtk_hbox_new(FALSE, 0);
-				line_width = 0;
-				col = 0;
-			}
-			col++;
-			it = it->next;
-			g_free(it_tmp);
+		add_smiley_list(smiley_table, ls, max_line_width, FALSE);
+		if (supports_custom) {
+			gtk_box_pack_start(GTK_BOX(smiley_table), gtk_hseparator_new(), TRUE, FALSE, 0);
+			add_smiley_list(smiley_table, ls, max_line_width, TRUE);
 		}
-		gtk_box_pack_start(GTK_BOX(smiley_table), line, FALSE, TRUE, 0);
+		while (ls) {
+			struct smiley_button_list *tmp = ls->next;
+			g_free(ls);
+			ls = tmp;
+		}
 
 		gtk_widget_add_events(dialog, GDK_KEY_PRESS_MASK);
 	}
@@ -840,8 +865,7 @@
 	gtk_widget_show(smiley_table);
 
 	/* connect signals */
-	g_signal_connect(G_OBJECT(dialog), "delete_event",
-					 G_CALLBACK(close_smiley_dialog), toolbar);
+	g_signal_connect_swapped(G_OBJECT(dialog), "destroy", G_CALLBACK(close_smiley_dialog), toolbar);
 
 	/* show everything */
 	gtk_widget_show_all(dialog);