From ef2750447c344671665bad8f94e9d06980d2432e Mon Sep 17 00:00:00 2001 From: Eric Koegel Date: Tue, 20 Mar 2012 21:01:05 +0300 Subject: [PATCH] Add optional support for custom file icon emblems (Bug 5469) Adds support to display multiple custom emblems for file icons on the desktop. Regular file icons will display whether it's a symlink or the file is read-only in addition to any emblems the user sets in Thunar. This requires an optional dependency on libtdb to read the metadata. --- README | 1 + configure.ac.in | 10 ++ po/POTFILES.in | 1 + src/Makefile.am | 13 ++- src/xfdesktop-file-icon-manager.c | 10 +- src/xfdesktop-file-icon.c | 33 ++++ src/xfdesktop-file-icon.h | 10 ++ src/xfdesktop-file-utils.c | 108 +++++++++++--- src/xfdesktop-file-utils.h | 5 +- src/xfdesktop-metafile.c | 296 +++++++++++++++++++++++++++++++++++++ src/xfdesktop-metafile.h | 62 ++++++++ src/xfdesktop-regular-file-icon.c | 50 ++---- src/xfdesktop-special-file-icon.c | 10 +- src/xfdesktop-volume-icon.c | 10 +- 14 files changed, 554 insertions(+), 65 deletions(-) create mode 100644 src/xfdesktop-metafile.c create mode 100644 src/xfdesktop-metafile.h diff --git a/README b/README index 987d7b1..fe8794c 100644 --- a/README +++ b/README @@ -27,6 +27,7 @@ MINIMUM REQUIREMENTS * thunar 1.2 (optional; required for file icons) * dbus-glib 0.34 (optional; required for file icons) * tumbler 1.6 (optional; enables thumbnail previews for file icons) +* libtdb 1.0 (optional; enables emblems on file icons) HIDDEN CUSTOMISATIONS diff --git a/configure.ac.in b/configure.ac.in index 94463e0..ac11b7d 100644 --- a/configure.ac.in +++ b/configure.ac.in @@ -25,6 +25,7 @@ m4_define([dbus_minimum_version], [0.84]) m4_define([wnck_minimum_version], [2.20]) m4_define([intltool_minimum_version], [0.31]) m4_define([xfconf_minimum_version], [4.8.0]) +m4_define([libtdb_minimum_version], [1.0.0]) dnl init autoconf AC_INIT([xfdesktop], [xfdesktop_version], [http://bugzilla.xfce.org/]) @@ -146,6 +147,10 @@ XDT_CHECK_OPTIONAL_PACKAGE([THUNARX], [thunarx-2], [thunar_minimum_version], [thunarx], [Thunar's extension mechanism, to add external features to the desktop icon implementation]) +XDT_CHECK_OPTIONAL_PACKAGE([LIBTDB], [tdb], [libtdb_minimum_version], + [tdb], + [libtdb - Trivial Database, to add emblems to desktop icons]) + dnl LIBEXO is required if file icons are enabled XDT_CHECK_PACKAGE([LIBEXO], [exo-1], [exo_minimum_version]) @@ -209,6 +214,11 @@ echo "Build Configuration:" echo "* Build desktop menu module: $build_desktop_menu" echo "* Build support for desktop icons: $enable_desktop_icons" echo " Include support for file/launcher icons: $enable_file_icons" +if test x"$LIBTDB_FOUND" = x"yes"; then +echo " Include support for icon emblems: yes" +else +echo " Include support for icon emblems: no" +fi if test x"$GIO_UNIX_FOUND" = x"yes"; then echo "* Special treatment for mount points on UNIX: yes" else diff --git a/po/POTFILES.in b/po/POTFILES.in index 123841e..a3c9c3b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -21,6 +21,7 @@ src/xfdesktop-file-utils.c src/xfdesktop-icon.c src/xfdesktop-icon-view.c src/xfdesktop-icon-view-manager.c +src/xfdesktop-metafile.c src/xfdesktop-notify.c src/xfdesktop-regular-file-icon.c src/xfdesktop-special-file-icon.c diff --git a/src/Makefile.am b/src/Makefile.am index 3adb3d2..e82e982 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,9 +12,16 @@ xfdesktop_notify_sources = \ xfdesktop-notify.h endif +if HAVE_LIBTDB +xfdesktop_tdb_sources = \ + xfdesktop-metafile.c \ + xfdesktop-metafile.h +endif + xfdesktop_SOURCES = \ $(xfdesktop_built_sources) \ $(xfdesktop_notify_sources) \ + $(xfdesktop_tdb_sources) \ main.c \ menu.c \ menu.h \ @@ -79,7 +86,8 @@ xfdesktop_CFLAGS = \ $(LIBXFCE4UI_CFLAGS) \ $(LIBXFCE4SMCLIENT_PRIVATE_CFLAGS) \ $(LIBWNCK_CFLAGS) \ - $(XFCONF_CFLAGS) + $(XFCONF_CFLAGS) \ + $(LIBTDB_CFLAGS) xfdesktop_LDFLAGS = \ -export-dynamic @@ -99,7 +107,8 @@ xfdesktop_LDADD += \ $(LIBXFCE4UI_LIBS) \ $(LIBXFCE4SMCLIENT_PRIVATE_LIBS) \ $(LIBWNCK_LIBS) \ - $(XFCONF_LIBS) + $(XFCONF_LIBS) \ + $(LIBTDB_LIBS) if BUILD_DESKTOP_MENU diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c index 0c6b244..b6e015a 100644 --- a/src/xfdesktop-file-icon-manager.c +++ b/src/xfdesktop-file-icon-manager.c @@ -1927,13 +1927,15 @@ 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) { - xfdesktop_thumbnailer_queue_thumbnail(fmanager->priv->thumbnailer, - g_file_get_path(file)); - } + if(file != NULL) + path = g_file_get_path(file); + + if(fmanager->priv->show_thumbnails && path != NULL) + xfdesktop_thumbnailer_queue_thumbnail(fmanager->priv->thumbnailer, path); name = xfdesktop_icon_peek_label(XFDESKTOP_ICON(icon)); diff --git a/src/xfdesktop-file-icon.c b/src/xfdesktop-file-icon.c index 1088e99..f764470 100644 --- a/src/xfdesktop-file-icon.c +++ b/src/xfdesktop-file-icon.c @@ -53,6 +53,9 @@ xfdesktop_file_icon_class_init(XfdesktopFileIconClass *klass) static void xfdesktop_file_icon_init(XfdesktopFileIcon *icon) { +#ifdef HAVE_LIBTDB + icon->metafile = xfdesktop_metafile_get_default(); +#endif } static void @@ -178,3 +181,33 @@ xfdesktop_file_icon_can_delete_file(XfdesktopFileIcon *icon) else return FALSE; } + +GList* +xfdesktop_file_icon_get_emblem_list(XfdesktopFileIcon *icon) +{ +#ifdef HAVE_LIBTDB + const gchar *emblem_string; + gchar **emblem_names = NULL; + GList *emblems = NULL; + + g_return_val_if_fail(XFDESKTOP_IS_FILE_ICON(icon), NULL); + g_return_val_if_fail(XFDESKTOP_IS_METAFILE(icon->metafile), NULL); + + emblem_string = xfdesktop_metafile_fetch(icon->metafile, + xfdesktop_file_icon_peek_file(icon), + XFDESKTOP_METAFILE_KEY_EMBLEMS, + ""); + + if(emblem_string != NULL && *emblem_string != '\0') + emblem_names = g_strsplit(emblem_string, ";", -1); + + if(emblem_names != NULL) { + for(; *emblem_names != NULL; ++emblem_names) { + emblems = g_list_append(emblems, *emblem_names); + } + } + + return emblems; +#endif + return NULL; +} diff --git a/src/xfdesktop-file-icon.h b/src/xfdesktop-file-icon.h index 4ca703f..5215182 100644 --- a/src/xfdesktop-file-icon.h +++ b/src/xfdesktop-file-icon.h @@ -27,6 +27,10 @@ #include "xfdesktop-icon.h" +#ifdef HAVE_LIBTDB +#include +#endif + G_BEGIN_DECLS #define XFDESKTOP_TYPE_FILE_ICON (xfdesktop_file_icon_get_type()) @@ -40,6 +44,10 @@ typedef struct _XfdesktopFileIconClass XfdesktopFileIconClass; struct _XfdesktopFileIcon { XfdesktopIcon parent; + +#ifdef HAVE_LIBTDB + XfdesktopMetafile *metafile; +#endif }; struct _XfdesktopFileIconClass @@ -68,6 +76,8 @@ gboolean xfdesktop_file_icon_can_rename_file(XfdesktopFileIcon *icon); gboolean xfdesktop_file_icon_can_delete_file(XfdesktopFileIcon *icon); +GList *xfdesktop_file_icon_get_emblem_list(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 5b015fd..1a3cd90 100644 --- a/src/xfdesktop-file-utils.c +++ b/src/xfdesktop-file-utils.c @@ -491,7 +491,7 @@ GdkPixbuf * xfdesktop_file_utils_get_icon(const gchar *custom_icon_name, GIcon *icon, gint size, - const GdkPixbuf *emblem, + GList *emblems, guint opacity) { GtkIconTheme *itheme = gtk_icon_theme_get_default(); @@ -540,10 +540,7 @@ 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(emblems != NULL) { /* 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)) { @@ -552,22 +549,7 @@ xfdesktop_file_utils_get_icon(const gchar *custom_icon_name, 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); - } + xfdesktop_file_utils_add_emblems(pix, emblems); } if(opacity != 100) { @@ -580,6 +562,90 @@ xfdesktop_file_utils_get_icon(const gchar *custom_icon_name, } 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) { + emblem_pix = gtk_icon_theme_load_icon(itheme, iter->data, + emblem_size, ITHEME_FLAGS, NULL); + + 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, %.1f, %.1f, %.1f, %.1f, %d, %d) pixbuf w: %d h: %d", + emblem_pix, pix, + dest_x, dest_y, + emblem_size, emblem_size, + 0.0, 0.0, + 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..0cca5d8 100644 --- a/src/xfdesktop-file-utils.h +++ b/src/xfdesktop-file-utils.h @@ -53,9 +53,12 @@ GdkPixbuf *xfdesktop_file_utils_get_fallback_icon(gint size); GdkPixbuf *xfdesktop_file_utils_get_icon(const gchar *custom_icon_name, GIcon *icon, gint size, - const GdkPixbuf *emblem, + GList *emblems, guint opacity); +void xfdesktop_file_utils_add_emblems(GdkPixbuf *pix, + GList *emblems); + void xfdesktop_file_utils_set_window_cursor(GtkWindow *window, GdkCursorType cursor_type); diff --git a/src/xfdesktop-metafile.c b/src/xfdesktop-metafile.c new file mode 100644 index 0000000..630aeb0 --- /dev/null +++ b/src/xfdesktop-metafile.c @@ -0,0 +1,296 @@ +/* + * Xfdesktop - xfce4's desktop manager + * + * Copyright(c) 2006 Brian Tarricone, + * Copyright(c) 2010-2011 Jannis Pohlmann, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * xfdesktop-metafile is based on thunar-metafile code from Thunar + * Copyright (c) 2005-2006 Benedikt Meurer + * Copyright (c) 2009-2011 Jannis Pohlmann + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_MEMORY_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include + +#include + +#include + +#include + +static void xfdesktop_metafile_class_init(XfdesktopMetafileClass *klass); + +static void xfdesktop_metafile_init(XfdesktopMetafile *metafile); + +static void xfdesktop_metafile_finalize(GObject *object); + +static TDB_DATA xfdesktop_metafile_read(XfdesktopMetafile *metafile, + TDB_DATA data); + +struct _XfdesktopMetafileClass +{ + GObjectClass __parent__; +}; + +struct _XfdesktopMetafile +{ + GObject __parent__; + + TDB_CONTEXT *context; + TDB_DATA data; +}; + +static GObjectClass *xfdesktop_metafile_parent_class; + +GType +xfdesktop_metafile_get_type(void) +{ + static GType type = G_TYPE_INVALID; + + if(type == G_TYPE_INVALID) + { + static const GTypeInfo info = + { + sizeof (XfdesktopMetafileClass), + NULL, + NULL, + (GClassInitFunc) xfdesktop_metafile_class_init, + NULL, + NULL, + sizeof (XfdesktopMetafile), + 0, + (GInstanceInitFunc) xfdesktop_metafile_init, + NULL, + }; + + type = g_type_register_static (G_TYPE_OBJECT, I_("XfdesktopMetafile"), &info, 0); + } + + return type; +} + +static void +xfdesktop_metafile_class_init(XfdesktopMetafileClass *klass) +{ + GObjectClass *gobject_class; + + xfdesktop_metafile_parent_class = g_type_class_peek_parent(klass); + + gobject_class = G_OBJECT_CLASS(klass); + gobject_class->finalize = xfdesktop_metafile_finalize; +} + +static void +xfdesktop_metafile_init(XfdesktopMetafile *metafile) +{ + gchar *path; + + /* determine the path to the metafile database */ + path = xfce_resource_lookup(XFCE_RESOURCE_CACHE, "Thunar/metafile.tdb"); + if(path == NULL) { + metafile->context = NULL; + return; + } + + /* try to open the metafile database file */ + metafile->context = tdb_open(path, 0, TDB_DEFAULT, O_RDONLY, 0); + if(metafile->context == NULL) + g_warning("Failed to open metafile database in %s: %s.", path, g_strerror(errno)); + + g_free(path); +} + +static void +xfdesktop_metafile_finalize(GObject *object) +{ + XfdesktopMetafile *metafile = XFDESKTOP_METAFILE(object); + + if(metafile->context != NULL) + tdb_close(metafile->context); + + if(metafile->data.dptr != NULL) + free(metafile->data.dptr); + + (*G_OBJECT_CLASS(xfdesktop_metafile_parent_class)->finalize) (object); +} + +static TDB_DATA +xfdesktop_metafile_read(XfdesktopMetafile *metafile, + TDB_DATA data) +{ + /* perform the fetch operation on the database */ + data = tdb_fetch(metafile->context, data); + if(data.dptr != NULL) { + /* validate the result */ + if(data.dsize < sizeof(guint32) + || (data.dsize % sizeof(guint32)) != 0 + || data.dptr[data.dsize - 1] != '\0') + { + free(data.dptr); + data.dptr = NULL; + data.dsize = 0; + } + } + + return data; +} + +/** + * xfdesktop_metafile_get_default: + * + * Returns a reference to the default #XfdesktopMetafile + * instance. There can be only one #XfdesktopMetafile + * instance at any time. + * + * The caller is responsible to free the returned + * object using g_object_unref() when no longer + * needed. + * + * Return value: a reference to the default #XfdesktopMetafile + * instance. + **/ +XfdesktopMetafile* +xfdesktop_metafile_get_default(void) +{ + static XfdesktopMetafile *metafile = NULL; + + if(metafile == NULL) { + /* allocate a new metafile instance. */ + metafile = g_object_new(XFDESKTOP_TYPE_METAFILE, NULL); + g_object_add_weak_pointer(G_OBJECT(metafile), (gpointer)&metafile); + } else { + /* take a reference for the caller */ + g_object_ref(G_OBJECT(metafile)); + } + + return metafile; +} + +/** + * xfdesktop_metafile_fetch: + * @metafile : a #XfdesktopMetafile. + * @file : a #Gfile. + * @key : a #XfdesktopMetafileKey. + * @default_value : the default value for @key, + * which may be %NULL. + * + * Fetches the value for @key on @path in + * @metafile. Returns a pointer to the + * value if found, or the default value + * if the @key is explicitly not set for + * @path in @metafile, as specified in + * @default_value. + * + * The returned string is owned by @metafile + * and is only valid until the next call to + * xfdesktop_metafile_fetch(), so you might need + * to take a copy of the value if you need to + * keep for a longer period. + * + * Return value: the value for @key on @path + * in @metafile or the default + * value for @key, as specified + * by @default_value. + **/ +const gchar* +xfdesktop_metafile_fetch(XfdesktopMetafile *metafile, + GFile *file, + XfdesktopMetafileKey key, + const gchar *default_value) +{ + const guchar *dend; + const guchar *dp; + TDB_DATA key_data; + gssize key_size; + gchar *key_path = NULL; + + if(file == NULL) + return NULL; + + g_return_val_if_fail(XFDESKTOP_IS_METAFILE(metafile), NULL); + g_return_val_if_fail(G_IS_FILE(file), NULL); + g_return_val_if_fail(key < XFDESKTOP_METAFILE_N_KEYS, NULL); + + /* check if the database handle is available */ + if(metafile->context == NULL) + goto use_default_value; + + /* determine the string representation of the path (using the URI for non-local paths) */ + key_path = g_file_get_uri(file); + key_size = strlen(key_path); + + if(key_size <= 0) + goto use_default_value; + + /* generate the key data */ + key_data.dptr = (unsigned char*)key_path; + key_data.dsize = key_size; + + /* release any earlier result data */ + if(metafile->data.dptr != NULL) + free(metafile->data.dptr); + + /* perform the fetch operation on the database */ + metafile->data = xfdesktop_metafile_read (metafile, key_data); + if(metafile->data.dptr == NULL) + goto use_default_value; + + /* lookup the value for the given key */ + dp = (const guchar *)metafile->data.dptr; + dend = dp + metafile->data.dsize; + for(;;) + { + /* check if we have a match */ + if(*dp == (guint)key) { + g_free(key_path); + return (const gchar *)(dp + 1); + } + + /* lookup the next entry */ + do { + /* skip another 4 bytes */ + dp += sizeof(guint32); + if(dp == dend) + goto use_default_value; + } + while(*(dp - 1) != '\0'); + } + + /* use the default value */ + use_default_value: + g_free(key_path); + return default_value; +} diff --git a/src/xfdesktop-metafile.h b/src/xfdesktop-metafile.h new file mode 100644 index 0000000..6f7eac7 --- /dev/null +++ b/src/xfdesktop-metafile.h @@ -0,0 +1,62 @@ +/* + * xfdesktop - xfce4's desktop manager + * + * Copyright(c) 2006 Brian Tarricone, + * Copyright(c) 2010-2011 Jannis Pohlmann, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * xfdesktop-metafile is based on thunar-metafile code from Thunar + * Copyright (c) 2005-2006 Benedikt Meurer + * Copyright (c) 2009-2011 Jannis Pohlmann + */ + +#ifndef __XFDESKTOP_METAFILE_H__ +#define __XFDESKTOP_METAFILE_H__ + +#include + +G_BEGIN_DECLS; + +#define XFDESKTOP_TYPE_METAFILE (xfdesktop_metafile_get_type()) +#define XFDESKTOP_METAFILE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XFDESKTOP_TYPE_METAFILE, XfdesktopMetafile)) +#define XFDESKTOP_IS_METAFILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XFDESKTOP_TYPE_METAFILE)) +#define XFDESKTOP_METAFILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XFDESKTOP_TYPE_METAFILE, XfdesktopMetafileClass)) + +typedef struct _XfdesktopMetafile XfdesktopMetafile; +typedef struct _XfdesktopMetafileClass XfdesktopMetafileClass; + +/** + * XfdesktopMetafileKey: + * @XFDESKTOP_METAFILE_KEY_EMBLEMS : + **/ +typedef enum +{ + XFDESKTOP_METAFILE_KEY_EMBLEMS, + XFDESKTOP_METAFILE_N_KEYS, +} XfdesktopMetafileKey; + +GType xfdesktop_metafile_get_type(void) G_GNUC_CONST; + +XfdesktopMetafile *xfdesktop_metafile_get_default(void); + +const gchar *xfdesktop_metafile_fetch(XfdesktopMetafile *metafile, + GFile *file, + XfdesktopMetafileKey key, + const gchar *default_value); + +G_END_DECLS; + +#endif /* __XFDESKTOP_METAFILE_H__ */ diff --git a/src/xfdesktop-regular-file-icon.c b/src/xfdesktop-regular-file-icon.c index f42f6d6..3f059c0 100644 --- a/src/xfdesktop-regular-file-icon.c +++ b/src/xfdesktop-regular-file-icon.c @@ -55,6 +55,8 @@ #include "xfdesktop-regular-file-icon.h" #define EMBLEM_SYMLINK "emblem-symbolic-link" +#define EMBLEM_READONLY "emblem-readonly" + struct _XfdesktopRegularFileIconPrivate { @@ -252,7 +254,7 @@ xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon, { XfdesktopRegularFileIcon *file_icon = XFDESKTOP_REGULAR_FILE_ICON(icon); gchar *icon_name = NULL; - GdkPixbuf *emblem_pix = NULL; + GList *emblem_list = NULL; if(size != file_icon->priv->cur_pix_size) xfdesktop_regular_file_icon_invalidate_pixbuf(file_icon); @@ -306,55 +308,37 @@ xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon, } } + emblem_list = xfdesktop_file_icon_get_emblem_list(XFDESKTOP_FILE_ICON(file_icon)); + + /* load the read only emblem if necessary */ + if(!g_file_info_get_attribute_boolean(file_icon->priv->file_info, + G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) + { + emblem_list = g_list_prepend(emblem_list, EMBLEM_READONLY); + } + /* 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; - } - } + emblem_list = g_list_prepend(emblem_list, EMBLEM_SYMLINK); } if(file_icon->priv->file_info) gicon = g_file_info_get_icon(file_icon->priv->file_info); 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; - - /* 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); - } + xfdesktop_file_utils_add_emblems(file_icon->priv->pix, emblem_list); } else { file_icon->priv->pix = xfdesktop_file_utils_get_icon(icon_name, gicon, - size, emblem_pix, + size, NULL, file_icon->priv->pix_opacity); } file_icon->priv->cur_pix_size = size; - if(emblem_pix) - g_object_unref(emblem_pix); + if(emblem_list) + g_list_free(emblem_list); g_free(icon_name); } diff --git a/src/xfdesktop-special-file-icon.c b/src/xfdesktop-special-file-icon.c index fa0bc0b..cfe4d5a 100644 --- a/src/xfdesktop-special-file-icon.c +++ b/src/xfdesktop-special-file-icon.c @@ -223,6 +223,7 @@ xfdesktop_special_file_icon_peek_pixbuf(XfdesktopIcon *icon, GIcon *gicon = NULL; const gchar *custom_icon_name = NULL; GFile *parent = NULL; + GList *emblem_list = NULL; if(size != file_icon->priv->cur_pix_size) xfdesktop_special_file_icon_invalidate_pixbuf(file_icon); @@ -250,14 +251,19 @@ xfdesktop_special_file_icon_peek_pixbuf(XfdesktopIcon *icon, if(file_icon->priv->file_info) gicon = g_file_info_get_icon(file_icon->priv->file_info); + emblem_list = xfdesktop_file_icon_get_emblem_list(XFDESKTOP_FILE_ICON(file_icon)); + file_icon->priv->pix = xfdesktop_file_utils_get_icon(custom_icon_name, gicon, size, - NULL, + emblem_list, 100); file_icon->priv->cur_pix_size = size; - + + if(emblem_list) + g_list_free(emblem_list); + return file_icon->priv->pix; } diff --git a/src/xfdesktop-volume-icon.c b/src/xfdesktop-volume-icon.c index c0cae93..55b557a 100644 --- a/src/xfdesktop-volume-icon.c +++ b/src/xfdesktop-volume-icon.c @@ -256,6 +256,7 @@ xfdesktop_volume_icon_peek_pixbuf(XfdesktopIcon *icon, gint size) { XfdesktopVolumeIcon *file_icon = XFDESKTOP_VOLUME_ICON(icon); + GList *emblem_list = NULL; g_return_val_if_fail(XFDESKTOP_IS_VOLUME_ICON(icon), NULL); @@ -268,8 +269,10 @@ xfdesktop_volume_icon_peek_pixbuf(XfdesktopIcon *icon, if(file_icon->priv->volume) gicon = g_volume_get_icon(file_icon->priv->volume); + emblem_list = xfdesktop_file_icon_get_emblem_list(XFDESKTOP_FILE_ICON(file_icon)); + file_icon->priv->pix = xfdesktop_file_utils_get_icon(NULL, gicon, size, - NULL, 100); + emblem_list, 100); /* If the volume isn't mounted show it as semi-transparent */ if(!xfdesktop_volume_icon_is_mounted(icon)) { @@ -284,7 +287,10 @@ xfdesktop_volume_icon_peek_pixbuf(XfdesktopIcon *icon, file_icon->priv->cur_pix_size = size; } - + + if(emblem_list) + g_list_free(emblem_list); + return file_icon->priv->pix; } -- 1.7.5.4