changeset 30358:c62fac7ada0d

Display the protocol icon for the authorization request dialog instead of a question mark. Refs #5038. The dialog is still pretty unusable, though. There should be either a link to the user profile or a button to start a conversation (or maybe both), but these seemingly trivial things were surprisingly tough to implement. I think I'll return to this ticket at the end of the summer.
author ivan.komarov@soc.pidgin.im
date Wed, 26 May 2010 20:35:02 +0000
parents 674a656893a3
children 8d5b0cbec844
files pidgin/gtkaccount.c pidgin/gtkutils.c pidgin/gtkutils.h pidgin/minidialog.c pidgin/minidialog.h
diffstat 5 files changed, 149 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/pidgin/gtkaccount.c	Sun May 23 18:28:46 2010 +0000
+++ b/pidgin/gtkaccount.c	Wed May 26 20:35:02 2010 +0000
@@ -2418,35 +2418,38 @@
 	g_free(buffer);
 }
 
-struct auth_and_add {
+struct auth_request
+{
 	PurpleAccountRequestAuthorizationCb auth_cb;
 	PurpleAccountRequestAuthorizationCb deny_cb;
 	void *data;
 	char *username;
 	char *alias;
 	PurpleAccount *account;
+	gboolean add_buddy_after_auth;
 };
 
 static void
-free_auth_and_add(struct auth_and_add *aa)
+free_auth_request(struct auth_request *ar)
 {
-	g_free(aa->username);
-	g_free(aa->alias);
-	g_free(aa);
+	g_free(ar->username);
+	g_free(ar->alias);
+	g_free(ar);
 }
 
 static void
-authorize_and_add_cb(struct auth_and_add *aa)
+authorize_and_add_cb(struct auth_request *ar)
 {
-	aa->auth_cb(aa->data);
-	purple_blist_request_add_buddy(aa->account, aa->username,
-	 	                    NULL, aa->alias);
+	ar->auth_cb(ar->data);
+	if (ar->add_buddy_after_auth) {
+		purple_blist_request_add_buddy(ar->account, ar->username, NULL, ar->alias);
+	}
 }
 
 static void
-deny_no_add_cb(struct auth_and_add *aa)
+deny_no_add_cb(struct auth_request *ar)
 {
-	aa->deny_cb(aa->data);
+	ar->deny_cb(ar->data);
 }
 
 static void *
@@ -2463,49 +2466,48 @@
 	char *buffer;
 	PurpleConnection *gc;
 	GtkWidget *alert;
+	GdkPixbuf *prpl_icon;
+	struct auth_request *aa;
 
 	gc = purple_account_get_connection(account);
 	if (message != NULL && *message == '\0')
 		message = NULL;
 
-	buffer = g_strdup_printf(_("%s%s%s%s wants to add %s to his or her buddy list%s%s"),
+	buffer = g_strdup_printf(_("%s%s%s%s wants to add you (%s) to his or her buddy list%s%s"),
 				remote_user,
-	 	                (alias != NULL ? " ("  : ""),
-		                (alias != NULL ? alias : ""),
-		                (alias != NULL ? ")"   : ""),
-		                (id != NULL
-		                ? id
-		                : (purple_connection_get_display_name(gc) != NULL
-		                ? purple_connection_get_display_name(gc)
-		                : purple_account_get_username(account))),
-		                (message != NULL ? ": " : "."),
-		                (message != NULL ? message  : ""));
-
-
-	if (!on_list) {
-		struct auth_and_add *aa = g_new0(struct auth_and_add, 1);
-		aa->auth_cb = auth_cb;
-		aa->deny_cb = deny_cb;
-		aa->data = user_data;
-		aa->username = g_strdup(remote_user);
-		aa->alias = g_strdup(alias);
-		aa->account = account;
-		alert = pidgin_make_mini_dialog(gc, PIDGIN_STOCK_DIALOG_QUESTION,
-						  _("Authorize buddy?"), buffer, aa,
-						  _("Authorize"), authorize_and_add_cb,
-						  _("Deny"), deny_no_add_cb,
-						  NULL);
-		g_signal_connect_swapped(G_OBJECT(alert), "destroy", G_CALLBACK(free_auth_and_add), aa);
-	} else {
-		alert = pidgin_make_mini_dialog(gc, PIDGIN_STOCK_DIALOG_QUESTION,
-						  _("Authorize buddy?"), buffer, user_data,
-						  _("Authorize"), auth_cb,
-						  _("Deny"), deny_cb,
-						  NULL);
-	}
+				(alias != NULL ? " ("  : ""),
+				(alias != NULL ? alias : ""),
+				(alias != NULL ? ")"   : ""),
+				(id != NULL
+				? id
+				: (purple_connection_get_display_name(gc) != NULL
+				? purple_connection_get_display_name(gc)
+				: purple_account_get_username(account))),
+				(message != NULL ? ": " : "."),
+				(message != NULL ? message  : ""));
+
+
+	prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+	
+	aa = g_new0(struct auth_request, 1);
+	aa->auth_cb = auth_cb;
+	aa->deny_cb = deny_cb;
+	aa->data = user_data;
+	aa->username = g_strdup(remote_user);
+	aa->alias = g_strdup(alias);
+	aa->account = account;
+	aa->add_buddy_after_auth = !on_list;
+	
+	alert = pidgin_make_mini_dialog_with_custom_icon(
+		gc, prpl_icon,
+		_("Authorize buddy?"), buffer, aa,
+		_("Authorize"), authorize_and_add_cb,
+		_("Deny"), deny_no_add_cb,
+		NULL);
+	
+	g_signal_connect_swapped(G_OBJECT(alert), "destroy", G_CALLBACK(free_auth_request), aa);
+	g_signal_connect(G_OBJECT(alert), "destroy", G_CALLBACK(purple_account_request_close), NULL);
 	pidgin_blist_add_alert(alert);
-	g_signal_connect(G_OBJECT(alert), "destroy",
-		G_CALLBACK(purple_account_request_close), NULL);
 
 	g_free(buffer);
 
--- a/pidgin/gtkutils.c	Sun May 23 18:28:46 2010 +0000
+++ b/pidgin/gtkutils.c	Wed May 26 20:35:02 2010 +0000
@@ -2611,18 +2611,11 @@
 	}
 }
 
-GtkWidget *
-pidgin_make_mini_dialog(PurpleConnection *gc,
-                        const char *icon_name,
-                        const char *primary,
-                        const char *secondary,
-                        void *user_data,
-                        ...)
+static void
+mini_dialog_init(PidginMiniDialog *mini_dialog, PurpleConnection *gc, void *user_data, va_list args)
 {
-	PidginMiniDialog *mini_dialog;
 	const char *button_text;
 	GList *cb_datas = NULL;
-	va_list args;
 	static gboolean first_call = TRUE;
 
 	if (first_call) {
@@ -2632,12 +2625,10 @@
 		                      PURPLE_CALLBACK(connection_signed_off_cb), NULL);
 	}
 
-	mini_dialog = pidgin_mini_dialog_new(primary, secondary, icon_name);
 	g_object_set_data(G_OBJECT(mini_dialog), "gc" ,gc);
 	g_signal_connect(G_OBJECT(mini_dialog), "destroy",
 		G_CALLBACK(alert_killed_cb), NULL);
 
-	va_start(args, user_data);
 	while ((button_text = va_arg(args, char*))) {
 		struct _old_button_clicked_cb_data *data = NULL;
 		PidginMiniDialogCallback wrapper_cb = NULL;
@@ -2654,12 +2645,40 @@
 			wrapper_cb, data);
 		cb_datas = g_list_append(cb_datas, data);
 	}
-	va_end(args);
 
 	g_signal_connect(G_OBJECT(mini_dialog), "destroy",
 		G_CALLBACK(old_mini_dialog_destroy_cb), cb_datas);
-
+}
+
+#define INIT_AND_RETURN_MINI_DIALOG(mini_dialog) \
+	va_list args; \
+	va_start(args, user_data); \
+	mini_dialog_init(mini_dialog, gc, user_data, args); \
+	va_end(args); \
 	return GTK_WIDGET(mini_dialog);
+
+GtkWidget *
+pidgin_make_mini_dialog(PurpleConnection *gc,
+                        const char *icon_name,
+                        const char *primary,
+                        const char *secondary,
+                        void *user_data,
+                        ...)
+{
+	PidginMiniDialog *mini_dialog = pidgin_mini_dialog_new(primary, secondary, icon_name);
+	INIT_AND_RETURN_MINI_DIALOG(mini_dialog);
+}
+
+GtkWidget *
+pidgin_make_mini_dialog_with_custom_icon(PurpleConnection *gc,
+					GdkPixbuf *custom_icon,
+					const char *primary,
+					const char *secondary,
+					void *user_data,
+					...)
+{
+	PidginMiniDialog *mini_dialog = pidgin_mini_dialog_new_with_custom_icon(primary, secondary, custom_icon);
+	INIT_AND_RETURN_MINI_DIALOG(mini_dialog);
 }
 
 /*
--- a/pidgin/gtkutils.h	Sun May 23 18:28:46 2010 +0000
+++ b/pidgin/gtkutils.h	Wed May 26 20:35:02 2010 +0000
@@ -715,6 +715,17 @@
 	void *user_data, ...) G_GNUC_NULL_TERMINATED;
 
 /**
+ * Does exactly what pidgin_make_mini_dialog() does, except you can specify
+ * a custom icon for the dialog.
+ */
+GtkWidget *pidgin_make_mini_dialog_with_custom_icon(PurpleConnection *gc,
+	GdkPixbuf *custom_icon,
+	const char *primary,
+	const char *secondary,
+	void *user_data,
+	...) G_GNUC_NULL_TERMINATED;
+
+/**
  * This is a callback function to be used for Ctrl+F searching in treeviews.
  * Sample Use:
  * 		gtk_tree_view_set_search_equal_func(treeview,
--- a/pidgin/minidialog.c	Sun May 23 18:28:46 2010 +0000
+++ b/pidgin/minidialog.c	Wed May 26 20:35:02 2010 +0000
@@ -75,6 +75,7 @@
 	PROP_TITLE = 1,
 	PROP_DESCRIPTION,
 	PROP_ICON_NAME,
+	PROP_CUSTOM_ICON,
 
 	LAST_PROPERTY
 } HazeConnectionProperties;
@@ -93,17 +94,32 @@
 #define PIDGIN_MINI_DIALOG_GET_PRIVATE(dialog) \
 	((PidginMiniDialogPrivate *) ((dialog)->priv))
 
+static PidginMiniDialog *
+mini_dialog_new(const gchar *title, const gchar *description)
+{
+	return g_object_new(PIDGIN_TYPE_MINI_DIALOG,
+		"title", title,
+		"description", description,
+		NULL);
+}
+
 PidginMiniDialog *
 pidgin_mini_dialog_new(const gchar *title,
                        const gchar *description,
                        const gchar *icon_name)
 {
-	PidginMiniDialog *mini_dialog = g_object_new(PIDGIN_TYPE_MINI_DIALOG,
-		"title", title,
-		"description", description,
-		"icon-name", icon_name,
-		NULL);
+	PidginMiniDialog *mini_dialog = mini_dialog_new(title, description);
+	pidgin_mini_dialog_set_icon_name(mini_dialog, icon_name);
+	return mini_dialog;
+}
 
+PidginMiniDialog *
+pidgin_mini_dialog_new_with_custom_icon(const gchar *title,
+					const gchar *description,
+					GdkPixbuf *custom_icon)
+{
+	PidginMiniDialog *mini_dialog = mini_dialog_new(title, description);
+	pidgin_mini_dialog_set_custom_icon(mini_dialog, custom_icon);
 	return mini_dialog;
 }
 
@@ -125,7 +141,13 @@
 pidgin_mini_dialog_set_icon_name(PidginMiniDialog *mini_dialog,
                                  const char *icon_name)
 {
-	g_object_set(G_OBJECT(mini_dialog), "icon_name", icon_name, NULL);
+	g_object_set(G_OBJECT(mini_dialog), "icon-name", icon_name, NULL);
+}
+
+void
+pidgin_mini_dialog_set_custom_icon(PidginMiniDialog *mini_dialog, GdkPixbuf *custom_icon)
+{
+	g_object_set(G_OBJECT(mini_dialog), "custom-icon", custom_icon, NULL);
 }
 
 struct _mini_dialog_button_clicked_cb_data
@@ -233,6 +255,9 @@
 			g_value_set_string(value, icon_name);
 			break;
 		}
+		case PROP_CUSTOM_ICON:
+			g_value_set_object(value, gtk_image_get_pixbuf(priv->icon));
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 	}
@@ -305,6 +330,8 @@
 			gtk_image_set_from_stock(priv->icon, g_value_get_string(value),
 				gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL));
 			break;
+		case PROP_CUSTOM_ICON:
+			gtk_image_set_from_pixbuf(priv->icon, g_value_get_object(value));
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 	}
@@ -355,6 +382,13 @@
 		G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB |
 		G_PARAM_READWRITE);
 	g_object_class_install_property (object_class, PROP_ICON_NAME, param_spec);
+	
+	param_spec = g_param_spec_object("custom-icon", "custom-icon",
+		"Pixbuf to use as the dialog's icon",
+		GDK_TYPE_PIXBUF,
+		G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB |
+		G_PARAM_READWRITE);
+	g_object_class_install_property (object_class, PROP_CUSTOM_ICON, param_spec);
 }
 
 /* 16 is the width of the icon, due to PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL */
--- a/pidgin/minidialog.h	Sun May 23 18:28:46 2010 +0000
+++ b/pidgin/minidialog.h	Wed May 26 20:35:02 2010 +0000
@@ -73,6 +73,8 @@
  *   <dd>The Gtk stock id of an icon for the dialog, or @c NULL for no icon.
  *       @see pidginstock.h
  *   </dd>
+ *   <dt><tt>"custom-icon"</tt> (<tt>GdkPixbuf *</tt>)</dt>
+ *   <dd>The custom icon to use instead of a stock one (overrides the "icon-name" property).</dd>
  * </dl>
  */
 typedef struct {
@@ -108,13 +110,20 @@
 /** Get the GType of #PidginMiniDialog. */
 GType pidgin_mini_dialog_get_type (void);
 
-/** Creates a new #PidginMiniDialog.  This is a shortcut for creating the dialog
+/** Creates a new #PidginMiniDialog with a stock icon. This is a shortcut for creating the dialog
  *  with @c g_object_new() then setting each property yourself.
  *  @return a new #PidginMiniDialog.
  */
 PidginMiniDialog *pidgin_mini_dialog_new(const gchar *title,
 	const gchar *description, const gchar *icon_name);
 
+/** Creates a new #PidginMiniDialog with a custom icon. This is a shortcut for creating the dialog
+ *  with @c g_object_new() then setting each property yourself.
+ *  @return a new #PidginMiniDialog.
+ */
+PidginMiniDialog *pidgin_mini_dialog_new_with_custom_icon(const gchar *title,
+	const gchar *description, GdkPixbuf *custom_icon);
+
 /** Shortcut for setting a mini-dialog's title via GObject properties.
  *  @param mini_dialog a mini-dialog
  *  @param title       the new title for @a mini_dialog
@@ -137,6 +146,13 @@
 void pidgin_mini_dialog_set_icon_name(PidginMiniDialog *mini_dialog,
 	const char *icon_name);
 
+/** Shortcut for setting a mini-dialog's custom icon via GObject properties.
+ *  @param mini_dialog a mini-dialog
+ *  @param icon_name   the pixbuf to use as a custom icon
+ */
+void pidgin_mini_dialog_set_custom_icon(PidginMiniDialog *mini_dialog,
+	GdkPixbuf *custom_icon);
+
 /** Adds a new button to a mini-dialog, and attaches the supplied callback to
  *  its <tt>clicked</tt> signal.  After a button is clicked, the dialog is
  *  destroyed.