From e31ab7b930c33f13d9f123e17032ba37b7bbbdcf Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 1 Jul 2013 11:11:26 -0500 Subject: if a user's avatar icon file doesn't exist or isn't readable, fall back to the default avatar --- src/idousermenuitem.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/idousermenuitem.c b/src/idousermenuitem.c index 07aeade..d0fdb09 100644 --- a/src/idousermenuitem.c +++ b/src/idousermenuitem.c @@ -285,6 +285,48 @@ ido_user_menu_item_primitive_draw_cb_gtk_3 (GtkWidget * widget, return FALSE; } +/* Tests for basic icon errors such as missing or unreadable icon files. */ +static gboolean +icon_is_loadable (GtkWidget * self, GIcon * icon, GError ** error) +{ + gint width; + gint height; + GtkIconInfo * info; + GdkPixbuf * pixbuf; + GtkStyleContext * style_context; + gboolean is_loadable; + + style_context = gtk_widget_get_style_context (self); + + if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_default(), + GTK_ICON_SIZE_MENU, + &width, + &height)) + { + /* arbitrary default size in case _size_lookup fails */ + width = 12; + height = 12; + } + + info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default(), + icon, + MIN (width, height), + GTK_ICON_LOOKUP_USE_BUILTIN | + GTK_ICON_LOOKUP_GENERIC_FALLBACK | + GTK_ICON_LOOKUP_FORCE_SIZE); + + pixbuf = gtk_icon_info_load_symbolic_for_context (info, + style_context, + NULL, + error); + + is_loadable = pixbuf != NULL; + + g_clear_object (&pixbuf); + g_clear_object (&info); + return is_loadable; +} + /*** **** PUBLIC API ***/ @@ -294,8 +336,14 @@ ido_user_menu_item_set_icon (IdoUserMenuItem * self, GIcon * icon) { IdoUserMenuItemPrivate * p = self->priv; GtkImage * image = GTK_IMAGE (p->user_image); + GError * error = NULL; - g_clear_object (&p->icon); + if (icon && !icon_is_loadable (GTK_WIDGET(self), icon, &error)) + { + g_warning ("Can't load user avatar icon: %s", error->message); + g_error_free (error); + icon = NULL; + } if (icon != NULL) g_object_ref (icon); -- cgit v1.2.3 From 059926df08da8b54e2fcee256a2ab977f4dfc307 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 1 Jul 2013 11:56:15 -0500 Subject: don't load the icon twice --- src/idousermenuitem.c | 161 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 107 insertions(+), 54 deletions(-) diff --git a/src/idousermenuitem.c b/src/idousermenuitem.c index d0fdb09..8ceb4ef 100644 --- a/src/idousermenuitem.c +++ b/src/idousermenuitem.c @@ -61,6 +61,103 @@ static gboolean ido_user_menu_item_primitive_draw_cb_gtk_3 (GtkWidget * image, cairo_t * cr, gpointer gself); +/*** +**** Avatar +***/ + +static GdkPixbuf * +load_gicon (GtkWidget * self, GIcon * icon, GError ** error) +{ + GtkSettings * settings; + gint width; + gint height; + GdkScreen * screen; + GtkIconTheme * icon_theme; + GtkIconInfo * info; + GtkStyleContext * style_context; + GdkPixbuf * pixbuf; + + settings = gtk_widget_get_settings (self); + if (settings == NULL) /* not attached to a toplevel yet */ + settings = gtk_settings_get_default (); + + if (!gtk_icon_size_lookup_for_settings (settings, + GTK_ICON_SIZE_MENU, + &width, + &height)) + { + /* arbitrary default size in case _size_lookup fails */ + width = 12; + height = 12; + } + + if ((screen = gtk_widget_get_screen (self))) + icon_theme = gtk_icon_theme_get_for_screen (screen); + else + icon_theme = gtk_icon_theme_get_default (); + + + info = gtk_icon_theme_lookup_by_gicon (icon_theme, + icon, + MIN (width, height), + GTK_ICON_LOOKUP_USE_BUILTIN | + GTK_ICON_LOOKUP_GENERIC_FALLBACK | + GTK_ICON_LOOKUP_FORCE_SIZE); + + style_context = gtk_widget_get_style_context (self); + + pixbuf = gtk_icon_info_load_symbolic_for_context (info, + style_context, + NULL, + error); + + g_clear_object (&info); + return pixbuf; +} + +static void +update_avatar (IdoUserMenuItem * self) +{ + IdoUserMenuItemPrivate * p = self->priv; + GdkPixbuf * pixbuf; + GtkImage * image; + + if (p->icon == NULL) + { + pixbuf = NULL; + } + else + { + GError * error = NULL; + + pixbuf = load_gicon (GTK_WIDGET(self), p->icon, &error); + + if (error != NULL) + { + g_warning ("Can't load user avatar icon: %s", error->message); + g_error_free (error); + } + } + + image = GTK_IMAGE (p->user_image); + + if (pixbuf != NULL) + { + gtk_image_set_from_pixbuf (image, pixbuf); + g_object_unref (G_OBJECT (pixbuf)); + } + else + { + GIcon * icon; + icon = g_themed_icon_new_with_default_fallbacks (FALLBACK_ICON_NAME); + gtk_image_set_from_gicon (image, icon, GTK_ICON_SIZE_MENU); + g_object_unref (icon); + } +} + +/*** +**** GObject virtual functions +***/ static void my_get_property (GObject * o, @@ -241,6 +338,11 @@ ido_user_menu_item_init (IdoUserMenuItem *self) g_signal_connect_after (GTK_WIDGET(self), "draw", G_CALLBACK(ido_user_menu_item_primitive_draw_cb_gtk_3), GTK_WIDGET(self)); + + /* load_gicon()'s behavior depends on the current screen/toplevel/etc, + so reload the avatar whenever the widget is realized */ + g_signal_connect_swapped (self, "realize", + G_CALLBACK(update_avatar), self); } @@ -285,48 +387,6 @@ ido_user_menu_item_primitive_draw_cb_gtk_3 (GtkWidget * widget, return FALSE; } -/* Tests for basic icon errors such as missing or unreadable icon files. */ -static gboolean -icon_is_loadable (GtkWidget * self, GIcon * icon, GError ** error) -{ - gint width; - gint height; - GtkIconInfo * info; - GdkPixbuf * pixbuf; - GtkStyleContext * style_context; - gboolean is_loadable; - - style_context = gtk_widget_get_style_context (self); - - if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_default(), - GTK_ICON_SIZE_MENU, - &width, - &height)) - { - /* arbitrary default size in case _size_lookup fails */ - width = 12; - height = 12; - } - - info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default(), - icon, - MIN (width, height), - GTK_ICON_LOOKUP_USE_BUILTIN | - GTK_ICON_LOOKUP_GENERIC_FALLBACK | - GTK_ICON_LOOKUP_FORCE_SIZE); - - pixbuf = gtk_icon_info_load_symbolic_for_context (info, - style_context, - NULL, - error); - - is_loadable = pixbuf != NULL; - - g_clear_object (&pixbuf); - g_clear_object (&info); - return is_loadable; -} - /*** **** PUBLIC API ***/ @@ -335,22 +395,15 @@ void ido_user_menu_item_set_icon (IdoUserMenuItem * self, GIcon * icon) { IdoUserMenuItemPrivate * p = self->priv; - GtkImage * image = GTK_IMAGE (p->user_image); - GError * error = NULL; - if (icon && !icon_is_loadable (GTK_WIDGET(self), icon, &error)) + if (p->icon != icon) { - g_warning ("Can't load user avatar icon: %s", error->message); - g_error_free (error); - icon = NULL; - } + g_clear_object (&p->icon); - if (icon != NULL) - g_object_ref (icon); - else - icon = g_themed_icon_new_with_default_fallbacks (FALLBACK_ICON_NAME); + p->icon = g_object_ref (icon); - gtk_image_set_from_gicon (image, icon, GTK_ICON_SIZE_MENU); + update_avatar (self); + } } void -- cgit v1.2.3 From 14e5eeb2a91994d5ed14f786aca9494c45bbf464 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 1 Jul 2013 12:23:13 -0500 Subject: in ido_user_menu_item_set_icon(), remove a g_warning iff icon is NULL --- src/idousermenuitem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/idousermenuitem.c b/src/idousermenuitem.c index 8ceb4ef..03522c7 100644 --- a/src/idousermenuitem.c +++ b/src/idousermenuitem.c @@ -400,7 +400,8 @@ ido_user_menu_item_set_icon (IdoUserMenuItem * self, GIcon * icon) { g_clear_object (&p->icon); - p->icon = g_object_ref (icon); + if (icon != NULL) + p->icon = g_object_ref (icon); update_avatar (self); } -- cgit v1.2.3