[Xfce4-commits] <xfdesktop:master> Use GIcons and add support for emblems on icons

Eric Koegel noreply at xfce.org
Sun Sep 1 16:20:02 CEST 2013


Updating branch refs/heads/master
         to bc48d533bd0dbaaad8d865bd6f26bc9c8f47e042 (commit)
       from e2af8b45c6bb1a7f18cd8ac36c072fd024cfa664 (commit)

commit bc48d533bd0dbaaad8d865bd6f26bc9c8f47e042
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Mon Aug 12 12:24:13 2013 +0300

    Use GIcons and add support for emblems on icons

 common/xfdesktop-common.h         |    3 +-
 src/xfdesktop-file-icon-manager.c |    8 +-
 src/xfdesktop-file-icon.c         |   54 ++++++++++
 src/xfdesktop-file-icon.h         |    5 +
 src/xfdesktop-file-utils.c        |  151 ++++++++++++++++++++--------
 src/xfdesktop-file-utils.h        |    4 +-
 src/xfdesktop-regular-file-icon.c |  196 ++++++++++++++++++-------------------
 src/xfdesktop-special-file-icon.c |   84 +++++++++-------
 src/xfdesktop-volume-icon.c       |   53 +++++-----
 9 files changed, 353 insertions(+), 205 deletions(-)

diff --git a/common/xfdesktop-common.h b/common/xfdesktop-common.h
index b34d7b5..cda8f75 100644
--- a/common/xfdesktop-common.h
+++ b/common/xfdesktop-common.h
@@ -64,7 +64,8 @@
   "time::*," \
   "thumbnail::*," \
   "trash::*," \
-  "unix::*"
+  "unix::*," \
+  "metadata::*"
 
 /**
  * Filesystem information namespaces queried for #GFileInfo * objects.
diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c
index ed4fcde..4ec88b9 100644
--- a/src/xfdesktop-file-icon-manager.c
+++ b/src/xfdesktop-file-icon-manager.c
@@ -1827,12 +1827,16 @@ xfdesktop_file_icon_manager_add_icon(XfdesktopFileIconManager *fmanager,
     gboolean do_add = FALSE;
     const gchar *name;
     GFile *file;
+    gchar *path = NULL;
 
     file = xfdesktop_file_icon_peek_file(icon);
 
-    if(fmanager->priv->show_thumbnails && g_file_get_path(file) != NULL) {
+    if(file != NULL)
+        path = g_file_get_path(file);
+
+    if(fmanager->priv->show_thumbnails && path != NULL) {
         xfdesktop_thumbnailer_queue_thumbnail(fmanager->priv->thumbnailer,
-                                              g_file_get_path(file));
+                                              path);
     }
 
     
diff --git a/src/xfdesktop-file-icon.c b/src/xfdesktop-file-icon.c
index 1088e99..f90bf04 100644
--- a/src/xfdesktop-file-icon.c
+++ b/src/xfdesktop-file-icon.c
@@ -53,11 +53,16 @@ xfdesktop_file_icon_class_init(XfdesktopFileIconClass *klass)
 static void
 xfdesktop_file_icon_init(XfdesktopFileIcon *icon)
 {
+    icon->gicon = NULL;
 }
 
 static void
 xfdesktop_file_icon_finalize(GObject *obj)
 {
+    XfdesktopFileIcon *icon = XFDESKTOP_FILE_ICON(obj);
+
+    xfdesktop_file_icon_invalidate_icon(icon);
+
     G_OBJECT_CLASS(xfdesktop_file_icon_parent_class)->finalize(obj);
 }
 
@@ -178,3 +183,52 @@ xfdesktop_file_icon_can_delete_file(XfdesktopFileIcon *icon)
     else
         return FALSE;
 }
+
+void
+xfdesktop_file_icon_add_emblems(XfdesktopFileIcon *icon)
+{
+    GIcon *emblemed_icon = NULL;
+    gchar **emblem_names;
+
+    TRACE("entering");
+
+    g_return_if_fail(XFDESKTOP_IS_FILE_ICON(icon));
+
+    if(G_IS_ICON(icon->gicon))
+        emblemed_icon = g_emblemed_icon_new(icon->gicon, NULL);
+    else
+        return;
+
+    /* Get the list of emblems */
+    emblem_names = g_file_info_get_attribute_stringv(xfdesktop_file_icon_peek_file_info(icon),
+                                                     "metadata::emblems");
+
+    if(emblem_names != NULL) {
+        /* for each item in the list create an icon, pack it into an emblem,
+         * and attach it to our icon. */
+        for (; *emblem_names != NULL; ++emblem_names) {
+            GIcon *themed_icon = g_themed_icon_new(*emblem_names);
+            GEmblem *emblem = g_emblem_new(themed_icon);
+
+            g_emblemed_icon_add_emblem(G_EMBLEMED_ICON(emblemed_icon), emblem);
+
+            g_object_unref(emblem);
+            g_object_unref(themed_icon);
+        }
+    } else
+
+    /* Clear out the old icon and set the new one */
+    xfdesktop_file_icon_invalidate_icon(icon);
+    icon->gicon = emblemed_icon;
+}
+
+void
+xfdesktop_file_icon_invalidate_icon(XfdesktopFileIcon *icon)
+{
+    g_return_if_fail(XFDESKTOP_IS_FILE_ICON(icon));
+
+    if(G_IS_ICON(icon->gicon)) {
+        g_object_unref(icon->gicon);
+        icon->gicon = NULL;
+    }
+}
diff --git a/src/xfdesktop-file-icon.h b/src/xfdesktop-file-icon.h
index 4ca703f..26cf816 100644
--- a/src/xfdesktop-file-icon.h
+++ b/src/xfdesktop-file-icon.h
@@ -40,6 +40,7 @@ typedef struct _XfdesktopFileIconClass   XfdesktopFileIconClass;
 struct _XfdesktopFileIcon
 {
     XfdesktopIcon parent;
+    GIcon *gicon;
 };
 
 struct _XfdesktopFileIconClass
@@ -68,6 +69,10 @@ gboolean xfdesktop_file_icon_can_rename_file(XfdesktopFileIcon *icon);
 
 gboolean xfdesktop_file_icon_can_delete_file(XfdesktopFileIcon *icon);
 
+void xfdesktop_file_icon_add_emblems(XfdesktopFileIcon *icon);
+
+void xfdesktop_file_icon_invalidate_icon(XfdesktopFileIcon *icon);
+
 G_END_DECLS
 
 #endif  /* __XFDESKTOP_FILE_ICON_H__ */
diff --git a/src/xfdesktop-file-utils.c b/src/xfdesktop-file-utils.c
index ed721d9..1a29b69 100644
--- a/src/xfdesktop-file-utils.c
+++ b/src/xfdesktop-file-utils.c
@@ -63,6 +63,8 @@
 #include "xfdesktop-file-utils.h"
 #include "xfdesktop-trash-proxy.h"
 
+static void xfdesktop_file_utils_add_emblems(GdkPixbuf *pix, GList *emblems);
+
 gboolean
 xfdesktop_file_utils_is_desktop_file(GFileInfo *info)
 {
@@ -488,33 +490,31 @@ xfdesktop_file_utils_get_fallback_icon(gint size)
 }
 
 GdkPixbuf *
-xfdesktop_file_utils_get_icon(const gchar *custom_icon_name,
-                              GIcon *icon,
+xfdesktop_file_utils_get_icon(GIcon *icon,
                               gint size,
-                              const GdkPixbuf *emblem,
                               guint opacity)
 {
     GtkIconTheme *itheme = gtk_icon_theme_get_default();
     GdkPixbuf *pix_theme = NULL, *pix = NULL;
+    GIcon *base_icon = NULL;
 
-    if(custom_icon_name) {
-        pix_theme = gtk_icon_theme_load_icon(itheme, custom_icon_name, size,
-                                             ITHEME_FLAGS, NULL);
-        if(!pix_theme && *custom_icon_name == '/' && g_file_test(custom_icon_name, G_FILE_TEST_IS_REGULAR))
-            pix_theme = gdk_pixbuf_new_from_file_at_size(custom_icon_name, size, size, NULL);
-    }
+    /* Extract the base icon if available */
+    if(G_IS_EMBLEMED_ICON(icon))
+        base_icon = g_emblemed_icon_get_icon(G_EMBLEMED_ICON(icon));
+    else
+        base_icon = icon;
 
-    if(!pix_theme && icon) {
-        if(G_IS_THEMED_ICON(icon)) {
+    if(!pix_theme && base_icon) {
+        if(G_IS_THEMED_ICON(base_icon) || G_IS_FILE_ICON(base_icon)) {
           GtkIconInfo *icon_info = gtk_icon_theme_lookup_by_gicon(itheme,
-                                                                  icon, size,
+                                                                  base_icon, size,
                                                                   ITHEME_FLAGS);
           if(icon_info) {
               pix_theme = gtk_icon_info_load_icon(icon_info, NULL);
               gtk_icon_info_free(icon_info);
           }
-        } else if(G_IS_LOADABLE_ICON(icon)) {
-            GInputStream *stream = g_loadable_icon_load(G_LOADABLE_ICON(icon),
+        } else if(G_IS_LOADABLE_ICON(base_icon)) {
+            GInputStream *stream = g_loadable_icon_load(G_LOADABLE_ICON(base_icon),
                                                         size, NULL, NULL, NULL);
             if(stream) {
                 pix = gdk_pixbuf_new_from_stream(stream, NULL, NULL);
@@ -540,35 +540,9 @@ xfdesktop_file_utils_get_icon(const gchar *custom_icon_name,
         return NULL;
     }
 
-    if(emblem) {
-        gint emblem_pix_size = gdk_pixbuf_get_width(emblem);
-        gint dest_size = size - emblem_pix_size;
-
-        /* if we're using the fallback icon, we don't want to draw an emblem on
-         * it, since other icons might use it without the emblem */
-        if(G_UNLIKELY(pix == xfdesktop_fallback_icon)) {
-            GdkPixbuf *tmp = gdk_pixbuf_copy(pix);
-            g_object_unref(G_OBJECT(pix));
-            pix = tmp;
-        }
-
-        if(dest_size < 0)
-            g_critical("xfdesktop_file_utils_get_file_icon(): (dest_size > 0) failed");
-        else {
-            DBG("calling gdk_pixbuf_composite(%p, %p, %d, %d, %d, %d, %.1f, %.1f, %.1f, %.1f, %d, %d)",
-                emblem, pix,
-                dest_size, dest_size,
-                emblem_pix_size, emblem_pix_size,
-                (gdouble)dest_size, (gdouble)dest_size,
-                1.0, 1.0, GDK_INTERP_BILINEAR, 255);
-
-            gdk_pixbuf_composite(emblem, pix,
-                                 dest_size, dest_size,
-                                 emblem_pix_size, emblem_pix_size,
-                                 dest_size, dest_size,
-                                 1.0, 1.0, GDK_INTERP_BILINEAR, 255);
-        }
-    }
+    /* Add the emblems */
+    if(G_IS_EMBLEMED_ICON(icon))
+        xfdesktop_file_utils_add_emblems(pix, g_emblemed_icon_get_emblems(G_EMBLEMED_ICON(icon)));
 
     if(opacity != 100) {
         GdkPixbuf *tmp = exo_gdk_pixbuf_lucent(pix, opacity);
@@ -579,6 +553,97 @@ xfdesktop_file_utils_get_icon(const gchar *custom_icon_name,
     return pix;
 }
 
+static void
+xfdesktop_file_utils_add_emblems(GdkPixbuf *pix, GList *emblems)
+{
+    GdkPixbuf *emblem_pix;
+    gint max_emblems;
+    gint pix_width, pix_height;
+    gint emblem_size;
+    gint dest_x, dest_y, dest_width, dest_height;
+    gint position;
+    GList *iter;
+    GtkIconTheme *itheme = gtk_icon_theme_get_default();
+
+    g_return_if_fail(pix != NULL);
+
+    pix_width = gdk_pixbuf_get_width(pix);
+    pix_height = gdk_pixbuf_get_height(pix);
+
+    emblem_size = MIN(pix_width, pix_height) / 3;
+
+    /* render up to four emblems for sizes from 48 onwards, else up to 2 emblems */
+    max_emblems = (pix_height < 48 && pix_width < 48) ? 2 : 4;
+
+    for(iter = emblems, position = 0; iter != NULL && position < max_emblems; iter = iter->next) {
+        /* extract the icon from the emblem and load it */
+        GIcon *emblem = g_emblem_get_icon(iter->data);
+        GtkIconInfo *icon_info = gtk_icon_theme_lookup_by_gicon(itheme,
+                                                                emblem,
+                                                                emblem_size,
+                                                                ITHEME_FLAGS);
+        if(icon_info) {
+            emblem_pix = gtk_icon_info_load_icon(icon_info, NULL);
+            gtk_icon_info_free(icon_info);
+        }
+
+        if(emblem_pix) {
+            if(gdk_pixbuf_get_width(emblem_pix) != emblem_size
+               || gdk_pixbuf_get_height(emblem_pix) != emblem_size)
+            {
+                GdkPixbuf *tmp = gdk_pixbuf_scale_simple(emblem_pix,
+                                                         emblem_size,
+                                                         emblem_size,
+                                                         GDK_INTERP_BILINEAR);
+                g_object_unref(emblem_pix);
+                emblem_pix = tmp;
+            }
+
+            dest_width = pix_width - emblem_size;
+            dest_height = pix_height - emblem_size;
+
+            switch(position) {
+                case 0: /* bottom right */
+                    dest_x = dest_width;
+                    dest_y = dest_height;
+                    break;
+                case 1: /* bottom left */
+                    dest_x = 0;
+                    dest_y = dest_height;
+                    break;
+                case 2: /* upper right */
+                    dest_x = dest_width;
+                    dest_y = 0;
+                    break;
+                case 3: /* upper left */
+                    dest_x = dest_y = 0;
+                    break;
+                default:
+                    g_warning("Invalid emblem position in xfdesktop_file_utils_add_emblems");
+            }
+
+            DBG("calling gdk_pixbuf_composite(%p, %p, %d, %d, %d, %d, %d, %d, %.1f, %.1f, %d, %d) pixbuf w: %d h: %d",
+                emblem_pix, pix,
+                dest_x, dest_y,
+                emblem_size, emblem_size,
+                dest_x, dest_y,
+                1.0, 1.0, GDK_INTERP_BILINEAR, 255, pix_width, pix_height);
+
+            /* Add the emblem */
+            gdk_pixbuf_composite(emblem_pix, pix,
+                                 dest_x, dest_y,
+                                 emblem_size, emblem_size,
+                                 dest_x, dest_y,
+                                 1.0, 1.0, GDK_INTERP_BILINEAR, 255);
+
+            g_object_unref(emblem_pix);
+            emblem_pix = NULL;
+
+            position++;
+        }
+    }
+}
+
 void
 xfdesktop_file_utils_set_window_cursor(GtkWindow *window,
                                        GdkCursorType cursor_type)
diff --git a/src/xfdesktop-file-utils.h b/src/xfdesktop-file-utils.h
index a44e53f..3a80e0c 100644
--- a/src/xfdesktop-file-utils.h
+++ b/src/xfdesktop-file-utils.h
@@ -50,10 +50,8 @@ void xfdesktop_file_utils_file_list_free(GList *file_list);
 
 GdkPixbuf *xfdesktop_file_utils_get_fallback_icon(gint size);
 
-GdkPixbuf *xfdesktop_file_utils_get_icon(const gchar *custom_icon_name,
-                                         GIcon *icon,
+GdkPixbuf *xfdesktop_file_utils_get_icon(GIcon *icon,
                                          gint size,
-                                         const GdkPixbuf *emblem,
                                          guint opacity);
 
 void xfdesktop_file_utils_set_window_cursor(GtkWindow *window,
diff --git a/src/xfdesktop-regular-file-icon.c b/src/xfdesktop-regular-file-icon.c
index a247a43..0d51a18 100644
--- a/src/xfdesktop-regular-file-icon.c
+++ b/src/xfdesktop-regular-file-icon.c
@@ -55,6 +55,7 @@
 #include "xfdesktop-regular-file-icon.h"
 
 #define EMBLEM_SYMLINK  "emblem-symbolic-link"
+#define EMBLEM_READONLY "emblem-readonly"
 
 struct _XfdesktopRegularFileIconPrivate
 {
@@ -224,6 +225,8 @@ xfdesktop_regular_file_icon_delete_thumbnail_file(XfdesktopIcon *icon)
         file_icon->priv->thumbnail_file = NULL;
     }
 
+    xfdesktop_file_icon_invalidate_icon(XFDESKTOP_FILE_ICON(icon));
+
     xfdesktop_regular_file_icon_invalidate_pixbuf(file_icon);
     xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon));
 }
@@ -243,124 +246,118 @@ xfdesktop_regular_file_icon_set_thumbnail_file(XfdesktopIcon *icon, GFile *file)
 
     file_icon->priv->thumbnail_file = file;
 
+    xfdesktop_file_icon_invalidate_icon(XFDESKTOP_FILE_ICON(icon));
+
     xfdesktop_regular_file_icon_invalidate_pixbuf(file_icon);
     xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon));
 }
 
+static GIcon *
+xfdesktop_load_icon_from_desktop_file(XfdesktopRegularFileIcon *regular_icon)
+{
+    gchar *contents;
+    gsize length;
+    GIcon *gicon = NULL;
+
+    /* try to load the file into memory */
+    if(g_file_load_contents(regular_icon->priv->file, NULL, &contents, &length,
+                            NULL, NULL))
+    {
+        /* allocate a new key file */
+        GKeyFile *key_file = g_key_file_new();
+
+        /* try to parse the key file from the contents of the file */
+        if (g_key_file_load_from_data(key_file, contents, length, 0, NULL)) {
+            gchar *icon_name;
+            /* try to determine the custom icon name */
+            icon_name = g_key_file_get_string(key_file,
+                                              G_KEY_FILE_DESKTOP_GROUP,
+                                              G_KEY_FILE_DESKTOP_KEY_ICON,
+                                              NULL);
+
+            /* Create the themed icon for it */
+            if(icon_name) {
+                gicon = g_themed_icon_new(icon_name);
+                g_free(icon_name);
+            }
+        }
+
+        /* free key file and in-memory data */
+        g_key_file_free(key_file);
+        g_free(contents);
+    }
+
+    return gicon;
+}
+
 static GdkPixbuf *
 xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon,
                                         gint size)
 {
-    XfdesktopRegularFileIcon *file_icon = XFDESKTOP_REGULAR_FILE_ICON(icon);
-    gchar *icon_name = NULL;
-    GdkPixbuf *emblem_pix = NULL;
-
-    if(size != file_icon->priv->cur_pix_size)
-        xfdesktop_regular_file_icon_invalidate_pixbuf(file_icon);
-
-    if(!file_icon->priv->pix) {
-        GIcon *gicon = NULL;
-
-        /* create a GFile for the $HOME/.thumbnails/ directory */
-        gchar *thumbnail_dir_path = g_build_filename(xfce_get_homedir(), 
-                                                     ".thumbnails", NULL);
-        GFile *thumbnail_dir = g_file_new_for_path(thumbnail_dir_path);
-
-        if(g_file_has_prefix(file_icon->priv->file, thumbnail_dir)) {
-            /* use the filename as custom icon name for thumbnails */
-            icon_name = g_file_get_path(file_icon->priv->file);
-
-            /* release thumbnail path */
-            g_object_unref(thumbnail_dir);
-            g_free(thumbnail_dir_path);
-        } else if(xfdesktop_file_utils_is_desktop_file(file_icon->priv->file_info)) {
-            gchar *contents;
-            gsize length;
-
-            /* try to load the file into memory */
-            if(g_file_load_contents(file_icon->priv->file, NULL, &contents, &length, 
-                                    NULL, NULL)) 
-            {
-                /* allocate a new key file */
-                GKeyFile *key_file = g_key_file_new();
-
-                /* try to parse the key file from the contents of the file */
-                if (g_key_file_load_from_data(key_file, contents, length, 0, NULL)) {
-                    /* try to determine the custom icon name */
-                    icon_name = g_key_file_get_string(key_file,
-                                                      G_KEY_FILE_DESKTOP_GROUP,
-                                                      G_KEY_FILE_DESKTOP_KEY_ICON,
-                                                      NULL);
-                }
-
-                /* free key file and in-memory data */
-                g_key_file_free(key_file);
-                g_free(contents);
-            }
+    XfdesktopRegularFileIcon *regular_icon = XFDESKTOP_REGULAR_FILE_ICON(icon);
+    XfdesktopFileIcon *file_icon = XFDESKTOP_FILE_ICON(icon);
+
+    if(size != regular_icon->priv->cur_pix_size)
+        xfdesktop_regular_file_icon_invalidate_pixbuf(regular_icon);
+
+        /* Still valid */
+    if(regular_icon->priv->pix != NULL)
+        return regular_icon->priv->pix;
+
+    if(!G_IS_ICON(file_icon->gicon)) {
+        /* Try to load the icon referenced in the .desktop file */
+        if(xfdesktop_file_utils_is_desktop_file(regular_icon->priv->file_info)) {
+            file_icon->gicon = xfdesktop_load_icon_from_desktop_file(regular_icon);
         } else {
             /* If we have a thumbnail then they are enabled, use it. */
-            if(file_icon->priv->thumbnail_file)
-            {
-                file_icon->priv->pix = gdk_pixbuf_new_from_file_at_size(g_file_get_path(file_icon->priv->thumbnail_file),
-                                                                        size, size,
-                                                                        NULL);
-            }
+            if(regular_icon->priv->thumbnail_file)
+                file_icon->gicon = g_file_icon_new(regular_icon->priv->thumbnail_file);
         }
 
-        /* load the symlink emblem if necessary */
-        if(g_file_info_get_attribute_boolean(file_icon->priv->file_info, 
-                                             G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK)) 
-        {
-            GtkIconTheme *itheme = gtk_icon_theme_get_default();
-            gint sym_pix_size = size * 2 / 3;
-            
-            emblem_pix = gtk_icon_theme_load_icon(itheme, EMBLEM_SYMLINK,
-                                                  sym_pix_size, ITHEME_FLAGS,
-                                                  NULL);
-            if(emblem_pix) {
-                if(gdk_pixbuf_get_width(emblem_pix) != sym_pix_size
-                   || gdk_pixbuf_get_height(emblem_pix) != sym_pix_size)
-                {
-                    GdkPixbuf *tmp = gdk_pixbuf_scale_simple(emblem_pix,
-                                                             sym_pix_size,
-                                                             sym_pix_size,
-                                                             GDK_INTERP_BILINEAR);
-                    g_object_unref(emblem_pix);
-                    emblem_pix = tmp;
-                }
-            }
+        /* If we still don't have an icon, use the default */
+        if(!G_IS_ICON(file_icon->gicon)) {
+            file_icon->gicon = g_file_info_get_icon(regular_icon->priv->file_info);
+            if(G_IS_ICON(file_icon->gicon))
+                g_object_ref(file_icon->gicon);
         }
 
-        if(file_icon->priv->file_info)
-            gicon = g_file_info_get_icon(file_icon->priv->file_info);
+        /* Add any user set emblems */
+        xfdesktop_file_icon_add_emblems(file_icon);
+
+        /* load the read only emblem if necessary */
+        if(!g_file_info_get_attribute_boolean(regular_icon->priv->file_info,
+                                              G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
+        {
+            GIcon *themed_icon = g_themed_icon_new(EMBLEM_READONLY);
+            GEmblem *emblem = g_emblem_new(themed_icon);
 
-        if(file_icon->priv->pix) {
-            if(emblem_pix) {
-                gint emblem_pix_size = gdk_pixbuf_get_width(emblem_pix);
-                gint dest_size = size - emblem_pix_size;
+            g_emblemed_icon_add_emblem(G_EMBLEMED_ICON(file_icon->gicon), emblem);
 
-                /* We have to add the emblem */
-                gdk_pixbuf_composite(emblem_pix, file_icon->priv->pix,
-                                     dest_size, dest_size,
-                                     emblem_pix_size, emblem_pix_size,
-                                     dest_size, dest_size,
-                                     1.0, 1.0, GDK_INTERP_BILINEAR, 255);
-            }
-        } else {
-            file_icon->priv->pix = xfdesktop_file_utils_get_icon(icon_name, gicon,
-                                                                 size, emblem_pix,
-                                                                 file_icon->priv->pix_opacity);
+            g_object_unref(emblem);
+            g_object_unref(themed_icon);
         }
-        
-        file_icon->priv->cur_pix_size = size;
 
-        if(emblem_pix)
-             g_object_unref(emblem_pix);
-        
-        g_free(icon_name);
+        /* load the symlink emblem if necessary */
+        if(g_file_info_get_attribute_boolean(regular_icon->priv->file_info,
+                                             G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK))
+        {
+            GIcon *themed_icon = g_themed_icon_new(EMBLEM_SYMLINK);
+            GEmblem *emblem = g_emblem_new(themed_icon);
+
+            g_emblemed_icon_add_emblem(G_EMBLEMED_ICON(file_icon->gicon), emblem);
+
+            g_object_unref(emblem);
+            g_object_unref(themed_icon);
+        }
     }
-    
-    return file_icon->priv->pix;
+
+    regular_icon->priv->pix = xfdesktop_file_utils_get_icon(file_icon->gicon,
+                                                            size,
+                                                            regular_icon->priv->pix_opacity);
+
+    regular_icon->priv->cur_pix_size = size;
+
+    return regular_icon->priv->pix;
 }
 
 static G_CONST_RETURN gchar *
@@ -702,6 +699,7 @@ xfdesktop_regular_file_icon_update_file_info(XfdesktopFileIcon *icon,
     regular_file_icon->priv->tooltip = NULL;
     
     /* not really easy to check if this changed or not, so just invalidate it */
+    xfdesktop_file_icon_invalidate_icon(XFDESKTOP_FILE_ICON(icon));
     xfdesktop_regular_file_icon_invalidate_pixbuf(regular_file_icon);
     xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon));
 }
diff --git a/src/xfdesktop-special-file-icon.c b/src/xfdesktop-special-file-icon.c
index 955263c..cda392e 100644
--- a/src/xfdesktop-special-file-icon.c
+++ b/src/xfdesktop-special-file-icon.c
@@ -220,46 +220,61 @@ static GdkPixbuf *
 xfdesktop_special_file_icon_peek_pixbuf(XfdesktopIcon *icon,
                                         gint size)
 {
-    XfdesktopSpecialFileIcon *file_icon = XFDESKTOP_SPECIAL_FILE_ICON(icon);
-    GIcon *gicon = NULL;
-    const gchar *custom_icon_name = NULL;
+    XfdesktopSpecialFileIcon *special_icon = XFDESKTOP_SPECIAL_FILE_ICON(icon);
+    XfdesktopFileIcon *file_icon = XFDESKTOP_FILE_ICON(icon);
     GFile *parent = NULL;
 
-    if(size != file_icon->priv->cur_pix_size)
-        xfdesktop_special_file_icon_invalidate_pixbuf(file_icon);
-
-    /* Already have a good icon */
-    if(file_icon->priv->pix != NULL)
-        return file_icon->priv->pix;
-
-    /* use a custom icon name for the local filesystem root */
-    parent = g_file_get_parent(file_icon->priv->file);
-    if(!parent && g_file_has_uri_scheme(file_icon->priv->file, "file"))
-        custom_icon_name = "drive-harddisk";
-    if(parent)
-        g_object_unref(parent);
-
-    /* use a custom icon for the trash, based on it having files
-     * the user can delete */
-    if(file_icon->priv->type == XFDESKTOP_SPECIAL_FILE_ICON_TRASH) {
-        if(file_icon->priv->trash_item_count == 0)
-            custom_icon_name = "user-trash";
-        else
-            custom_icon_name = "user-trash-full";
+    if(size != special_icon->priv->cur_pix_size)
+        xfdesktop_special_file_icon_invalidate_pixbuf(special_icon);
+
+    /* Still valid */
+    if(special_icon->priv->pix != NULL)
+        return special_icon->priv->pix;
+
+    if(!G_IS_ICON(file_icon->gicon)) {
+        gchar *icon_name = NULL;
+
+        /* use a custom icon name for the local filesystem root */
+        parent = g_file_get_parent(special_icon->priv->file);
+        if(!parent && g_file_has_uri_scheme(special_icon->priv->file, "file"))
+            icon_name = g_strdup("drive-harddisk");
+
+        if(parent)
+            g_object_unref(parent);
+
+        /* use a custom icon for the trash, based on it having files
+         * the user can delete */
+        if(special_icon->priv->type == XFDESKTOP_SPECIAL_FILE_ICON_TRASH) {
+            if(special_icon->priv->trash_item_count == 0)
+                icon_name = g_strdup("user-trash");
+            else
+                icon_name = g_strdup("user-trash-full");
+        }
+
+        /* Create the themed icon for it */
+        if(icon_name) {
+            file_icon->gicon = g_themed_icon_new(icon_name);
+            g_free(icon_name);
+        }
+
+        /* If we still don't have an icon, use the default */
+        if(!G_IS_ICON(file_icon->gicon)) {
+            file_icon->gicon = g_file_info_get_icon(special_icon->priv->file_info);
+            if(G_IS_ICON(file_icon->gicon))
+                g_object_ref(file_icon->gicon);
+        }
+
+        /* Add any user set emblems */
+        xfdesktop_file_icon_add_emblems(file_icon);
     }
 
-    if(file_icon->priv->file_info)
-        gicon = g_file_info_get_icon(file_icon->priv->file_info);
+    special_icon->priv->pix = xfdesktop_file_utils_get_icon(file_icon->gicon,
+                                                            size,
+                                                            100);
 
-    file_icon->priv->pix = xfdesktop_file_utils_get_icon(custom_icon_name,
-                                                         gicon,
-                                                         size,
-                                                         NULL,
-                                                         100);
+    special_icon->priv->cur_pix_size = size;
 
-    file_icon->priv->cur_pix_size = size;
-    
-    return file_icon->priv->pix;
+    return special_icon->priv->pix;
 }
 
 static G_CONST_RETURN gchar *
@@ -607,6 +622,7 @@ xfdesktop_special_file_icon_changed(GFileMonitor *monitor,
     special_file_icon->priv->tooltip = NULL;
 
     /* update the icon */
+    xfdesktop_file_icon_invalidate_icon(XFDESKTOP_FILE_ICON(special_file_icon));
     xfdesktop_special_file_icon_invalidate_pixbuf(special_file_icon);
     xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(special_file_icon));
 }
diff --git a/src/xfdesktop-volume-icon.c b/src/xfdesktop-volume-icon.c
index d642f89..47301e5 100644
--- a/src/xfdesktop-volume-icon.c
+++ b/src/xfdesktop-volume-icon.c
@@ -256,37 +256,43 @@ static GdkPixbuf *
 xfdesktop_volume_icon_peek_pixbuf(XfdesktopIcon *icon,
                                   gint size)
 {
-    XfdesktopVolumeIcon *file_icon = XFDESKTOP_VOLUME_ICON(icon);
+    XfdesktopVolumeIcon *volume_icon = XFDESKTOP_VOLUME_ICON(icon);
+    XfdesktopFileIcon *file_icon = XFDESKTOP_FILE_ICON(icon);
+    gint opacity = 100;
     
     g_return_val_if_fail(XFDESKTOP_IS_VOLUME_ICON(icon), NULL);
     
-    if(size != file_icon->priv->cur_pix_size)
-        xfdesktop_volume_icon_invalidate_pixbuf(file_icon);
-
-    if(!file_icon->priv->pix) {
-        GIcon *gicon = NULL;
+    if(size != volume_icon->priv->cur_pix_size)
+        xfdesktop_volume_icon_invalidate_pixbuf(volume_icon);
 
-        if(file_icon->priv->volume)
-            gicon = g_volume_get_icon(file_icon->priv->volume);
+    /* Still valid */
+    if(volume_icon->priv->pix != NULL)
+        return volume_icon->priv->pix;
 
-        file_icon->priv->pix = xfdesktop_file_utils_get_icon(NULL, gicon, size, 
-                                                             NULL, 100);
+    if(!G_IS_ICON(file_icon->gicon)) {
+        /* icon changed, get a new one and keep a ref to it */
+        if(volume_icon->priv->volume) {
+            file_icon->gicon = g_volume_get_icon(volume_icon->priv->volume);
 
-        /* If the volume isn't mounted show it as semi-transparent */
-        if(!xfdesktop_volume_icon_is_mounted(icon)) {
-            GdkPixbuf *temp;
-            temp = exo_gdk_pixbuf_lucent(file_icon->priv->pix, 50);
+            if(G_IS_ICON(file_icon->gicon))
+                g_object_ref(file_icon->gicon);
 
-            if(temp != NULL) {
-                g_object_unref(G_OBJECT(file_icon->priv->pix));
-                file_icon->priv->pix = temp;
-            }
-        }
-        
-        file_icon->priv->cur_pix_size = size;
+            /* Add any user set emblems */
+            xfdesktop_file_icon_add_emblems(file_icon);
+         }
     }
-    
-    return file_icon->priv->pix;
+
+    /* If the volume isn't mounted show it as semi-transparent */
+    if(!xfdesktop_volume_icon_is_mounted(icon))
+        opacity = 50;
+
+    volume_icon->priv->pix = xfdesktop_file_utils_get_icon(file_icon->gicon,
+                                                           size,
+                                                           opacity);
+
+    volume_icon->priv->cur_pix_size = size;
+
+    return volume_icon->priv->pix;
 }
 
 G_CONST_RETURN gchar *
@@ -891,6 +897,7 @@ xfdesktop_volume_icon_update_file_info(XfdesktopFileIcon *icon,
     }
 
     /* not really easy to check if this changed or not, so just invalidate it */
+    xfdesktop_file_icon_invalidate_icon(XFDESKTOP_FILE_ICON(icon));
     xfdesktop_volume_icon_invalidate_pixbuf(volume_icon);
     xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon));
 }


More information about the Xfce4-commits mailing list