# HG changeset patch # User ivan.komarov@soc.pidgin.im # Date 1274906102 0 # Node ID c62fac7ada0d4462911c83b4b87814bc7872d6f0 # Parent 674a656893a3b7824658f5804a4fdbf44d39c6ea 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. diff -r 674a656893a3 -r c62fac7ada0d pidgin/gtkaccount.c --- 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); diff -r 674a656893a3 -r c62fac7ada0d pidgin/gtkutils.c --- 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); } /* diff -r 674a656893a3 -r c62fac7ada0d pidgin/gtkutils.h --- 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, diff -r 674a656893a3 -r c62fac7ada0d pidgin/minidialog.c --- 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 */ diff -r 674a656893a3 -r c62fac7ada0d pidgin/minidialog.h --- 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 @@ *
The Gtk stock id of an icon for the dialog, or @c NULL for no icon. * @see pidginstock.h *
+ *
"custom-icon" (GdkPixbuf *)
+ *
The custom icon to use instead of a stock one (overrides the "icon-name" property).
* */ 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 clicked signal. After a button is clicked, the dialog is * destroyed.