[Xfce4-commits] <xfdesktop:eric/bugzilla-patches> Thumbnail desktop icon previews using tumblerd
Eric Koegel
noreply at xfce.org
Sun Feb 12 14:32:04 CET 2012
Updating branch refs/heads/eric/bugzilla-patches
to d5e4dbea733153b74caba0e7a9c2bccc2ea5bf9c (commit)
from 803ea66061417317df2b2968a81a4cfdfd052e8d (commit)
commit d5e4dbea733153b74caba0e7a9c2bccc2ea5bf9c
Author: Eric Koegel <eric.koegel at gmail.com>
Date: Fri Feb 10 19:56:59 2012 +0300
Thumbnail desktop icon previews using tumblerd
Adds support for drawing thumbnails from the dbus thumbnail
service. Adds a show-thumbnails xfconf property to toggle showing
thumbnails. Moves the marshal.list into the common folder. Creates
a checkbox option on the xfdesktop-settings app to toggle
thumbnails. Adds a tooltip-size gtk style property to change the
tooltip image size, ranges from 0 (not shown) to 512, with 128
as the default. Added a timer when the icon size spinner changed
value in the settings app to prevent the icons redrawing on every
value change. Removed xfdesktop_icon_mark_extents_dirty so that
size changes to the pixbuf are properly rendered. Bug 4344.
README | 8 +-
common/Makefile.am | 37 ++-
common/xfdesktop-marshal.list | 4 +
common/xfdesktop-thumbnailer.c | 606 ++++++++++++++++++++++++++++++++++
common/xfdesktop-thumbnailer.h | 76 +++++
doc/README.xfconf | 1 +
settings/main.c | 60 +++-
settings/xfdesktop-settings-ui.glade | 11 +
src/Makefile.am | 16 +-
src/xfdesktop-file-icon-manager.c | 130 +++++++-
src/xfdesktop-file-icon-manager.h | 4 +
src/xfdesktop-icon-view.c | 54 ++--
src/xfdesktop-icon.c | 51 ++--
src/xfdesktop-icon.h | 7 +-
src/xfdesktop-marshal.list | 2 -
src/xfdesktop-regular-file-icon.c | 84 +++++-
16 files changed, 1070 insertions(+), 81 deletions(-)
diff --git a/README b/README
index e8aad4b..ad68c54 100644
--- a/README
+++ b/README
@@ -41,6 +41,7 @@ style "xfdesktop-icon-view" {
XfdesktopIconView::label-alpha = 75
XfdesktopIconView::selected-label-alpha = 100
XfdesktopIconVIew::ellipsize-icon-labels = 1
+ XfdesktopIconView::tooltip-size = 128
XfdesktopIconView::shadow-x-offset = 1
XfdesktopIconView::shadow-y-offset = 1
@@ -63,11 +64,14 @@ style "xfdesktop-icon-view" {
}
widget_class "*XfdesktopIconView*" style "xfdesktop-icon-view"
-The first three entries set the opacity of the rounded text background
+The first four entries set the opacity of the rounded text background
(allowed values are from 0 (totally transparent) to 255 (totally opaque),
and whether or not unselected icons get their labels ellipsized
(truncated) to fit on one line. (The 'selected-' version controls the
-opacity of icons that have been selected with the mouse.)
+opacity of icons that have been selected with the mouse.) The tooltip-size
+determines how large the image preview will be when the mouse is hovered
+over an icon (allowed values are from 0 (not shown) to 512, values larger
+than 256 may cause poor image quality however.)
The second six entries can be used to enable a text shadow to be painted
with the icon labels. The offsets are in pixels. Setting them to 0 (the
diff --git a/common/Makefile.am b/common/Makefile.am
index b6145ba..1af6ac8 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -2,9 +2,44 @@ noinst_LTLIBRARIES = libxfdesktop.la
libxfdesktop_la_SOURCES = \
xfdesktop-common.c \
- xfdesktop-common.h
+ xfdesktop-common.h \
+ xfdesktop-marshal.c \
+ xfdesktop-marshal.h
libxfdesktop_la_CFLAGS = \
-I$(top_srcdir)/src \
$(LIBXFCE4UTIL_CFLAGS) \
$(GTK_CFLAGS)
+
+if ENABLE_DESKTOP_ICONS
+if ENABLE_FILE_ICONS
+
+libxfdesktop_la_SOURCES += \
+ xfdesktop-thumbnailer.c \
+ xfdesktop-thumbnailer.h
+
+libxfdesktop_la_CFLAGS += \
+ -DDBUS_API_SUBJECT_TO_CHANGE \
+ $(DBUS_CFLAGS)
+
+endif
+endif
+
+DISTCLEANFILES = \
+ $(xfdesktop_built_sources) \
+ stamp-xfdesktop-marshal.h \
+ xfdesktop-marshal.c \
+ xfdesktop-marshal.h
+
+xfdesktop-marshal.h: stamp-xfdesktop-marshal.h
+ @true
+stamp-xfdesktop-marshal.h: xfdesktop-marshal.list Makefile
+ $(AM_V_GEN) glib-genmarshal --prefix=xfdesktop_marshal xfdesktop-marshal.list --header > xfdesktop-marshal.h && \
+ echo timestamp > $(@F)
+xfdesktop-marshal.c: xfdesktop-marshal.list Makefile
+ $(AM_V_GEN) echo '#include "xfdesktop-marshal.h"' > xfdesktop-marshal.c && \
+ glib-genmarshal --prefix=xfdesktop_marshal xfdesktop-marshal.list --body >> xfdesktop-marshal.c && \
+ glib-genmarshal --prefix=xfdesktop_marshal xfdesktop-marshal.list --header > xfdesktop-marshal.h
+
+EXTRA_DIST = \
+ xfdesktop-marshal.list
diff --git a/common/xfdesktop-marshal.list b/common/xfdesktop-marshal.list
new file mode 100644
index 0000000..8fe4148
--- /dev/null
+++ b/common/xfdesktop-marshal.list
@@ -0,0 +1,4 @@
+BOOLEAN:VOID
+BOOLEAN:ENUM,INT
+VOID:UINT,BOXED
+VOID:STRING,STRING
diff --git a/common/xfdesktop-thumbnailer.c b/common/xfdesktop-thumbnailer.c
new file mode 100644
index 0000000..3cc157b
--- /dev/null
+++ b/common/xfdesktop-thumbnailer.c
@@ -0,0 +1,606 @@
+/*
+ * xfdesktop - xfce4's desktop manager
+ *
+ * Copyright(c) 2006 Brian Tarricone, <bjt23 at cornell.edu>
+ * Copyright(c) 2006 Benedikt Meurer, <benny at xfce.org>
+ * Copyright(c) 2010-2011 Jannis Pohlmann, <jannis at xfce.org>
+ *
+ * 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-thumbnailer is based on thumbnailer code from Ristretto
+ * Copyright (c) Stephan Arts 2009-2011 <stephan at xfce.org>
+ *
+ * Thumbnailer Spec
+ * http://live.gnome.org/ThumbnailerSpec
+ * Thumbnail Managing Standard
+ * http://people.freedesktop.org/~vuntz/thumbnail-spec-cache/creation.html
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+
+#include <dbus/dbus-glib.h>
+
+#include "xfdesktop-thumbnailer.h"
+#include "xfdesktop-marshal.h"
+
+static void xfdesktop_thumbnailer_init(GObject *);
+static void xfdesktop_thumbnailer_class_init(GObjectClass *);
+
+static void xfdesktop_thumbnailer_dispose(GObject *object);
+static void xfdesktop_thumbnailer_finalize(GObject *object);
+
+static void xfdesktop_thumbnailer_request_finished_dbus(DBusGProxy *proxy,
+ gint handle,
+ gpointer data);
+
+static void xfdesktop_thumbnailer_thumbnail_ready_dbus(DBusGProxy *proxy,
+ gint handle,
+ const gchar **uri,
+ gpointer data);
+
+static gboolean xfdesktop_thumbnailer_queue_request_timer(XfdesktopThumbnailer *thumbnailer);
+
+static GObjectClass *parent_class = NULL;
+static XfdesktopThumbnailer *thumbnailer_object = NULL;
+
+enum
+{
+ THUMBNAIL_READY,
+ LAST_SIGNAL,
+};
+
+static guint thumbnailer_signals[LAST_SIGNAL] = { 0, };
+
+GType
+xfdesktop_thumbnailer_get_type(void)
+{
+ static GType xfdesktop_thumbnailer_type = 0;
+
+ if(!xfdesktop_thumbnailer_type) {
+ static const GTypeInfo xfdesktop_thumbnailer_info =
+ {
+ sizeof (XfdesktopThumbnailerClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) xfdesktop_thumbnailer_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL,
+ sizeof (XfdesktopThumbnailer),
+ 0,
+ (GInstanceInitFunc) xfdesktop_thumbnailer_init,
+ NULL
+ };
+
+ xfdesktop_thumbnailer_type = g_type_register_static(
+ G_TYPE_OBJECT,
+ "XfdesktopThumbnailer",
+ &xfdesktop_thumbnailer_info,
+ 0);
+ }
+ return xfdesktop_thumbnailer_type;
+}
+
+struct _XfdesktopThumbnailerPriv
+{
+ DBusGProxy *proxy;
+
+ GSList *queue;
+ gchar **supported_mimetypes;
+ gboolean big_thumbnails;
+ gint handle;
+
+ gint request_timer_id;
+};
+
+static void
+xfdesktop_thumbnailer_init(GObject *object)
+{
+ XfdesktopThumbnailer *thumbnailer;
+ DBusGConnection *connection;
+
+ thumbnailer = XFDESKTOP_THUMBNAILER(object);
+
+ thumbnailer->priv = g_new0(XfdesktopThumbnailerPriv, 1);
+
+ connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+
+ if(connection) {
+ thumbnailer->priv->proxy = dbus_g_proxy_new_for_name(
+ connection,
+ "org.freedesktop.thumbnails.Thumbnailer1",
+ "/org/freedesktop/thumbnails/Thumbnailer1",
+ "org.freedesktop.thumbnails.Thumbnailer1");
+
+ if(thumbnailer->priv->proxy) {
+ gchar **supported_uris;
+ gchar **supported_flavors;
+
+ dbus_g_object_register_marshaller(
+ (GClosureMarshal) xfdesktop_marshal_VOID__UINT_BOXED,
+ G_TYPE_NONE, G_TYPE_UINT,
+ G_TYPE_STRV, G_TYPE_INVALID);
+
+ dbus_g_proxy_add_signal(
+ thumbnailer->priv->proxy,
+ "Finished", G_TYPE_UINT, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(
+ thumbnailer->priv->proxy,
+ "Ready", G_TYPE_UINT, G_TYPE_STRV, G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal(
+ thumbnailer->priv->proxy,
+ "Finished", G_CALLBACK (xfdesktop_thumbnailer_request_finished_dbus),
+ thumbnailer, NULL);
+ dbus_g_proxy_connect_signal(
+ thumbnailer->priv->proxy,
+ "Ready", G_CALLBACK(xfdesktop_thumbnailer_thumbnail_ready_dbus),
+ thumbnailer, NULL);
+
+ dbus_g_proxy_call(thumbnailer->priv->proxy, "GetSupported", NULL, G_TYPE_INVALID,
+ G_TYPE_STRV, &supported_uris,
+ G_TYPE_STRV, &thumbnailer->priv->supported_mimetypes,
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_call(thumbnailer->priv->proxy, "GetFlavors", NULL, G_TYPE_INVALID,
+ G_TYPE_STRV, &supported_flavors,
+ G_TYPE_INVALID);
+
+ if(supported_flavors != NULL) {
+ gint n;
+ for(n = 0; supported_flavors[n] != NULL; ++n) {
+ g_debug("flavor: %s", supported_flavors[n]);
+ if(g_strcmp0(supported_flavors[n], "large")) {
+ thumbnailer->priv->big_thumbnails = TRUE;
+ }
+ }
+ } else {
+ thumbnailer->priv->big_thumbnails = FALSE;
+ g_debug("Thumbnailer failed to Get Flavors");
+ }
+
+ g_strfreev(supported_flavors);
+ g_strfreev(supported_uris);
+ }
+
+ dbus_g_connection_unref(connection);
+ }
+}
+
+static void
+xfdesktop_thumbnailer_class_init (GObjectClass *object_class)
+{
+ XfdesktopThumbnailerClass *thumbnailer_class = XFDESKTOP_THUMBNAILER_CLASS(object_class);
+
+ parent_class = g_type_class_peek_parent(thumbnailer_class);
+
+ object_class->dispose = xfdesktop_thumbnailer_dispose;
+ object_class->finalize = xfdesktop_thumbnailer_finalize;
+
+ thumbnailer_signals[THUMBNAIL_READY] = g_signal_new (
+ "thumbnail-ready",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(XfdesktopThumbnailerClass, thumbnail_ready),
+ NULL, NULL,
+ xfdesktop_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING, G_TYPE_STRING);
+}
+
+/**
+ * xfdesktop_thumbnailer_dispose:
+ * @object:
+ *
+ */
+static void
+xfdesktop_thumbnailer_dispose(GObject *object)
+{
+ XfdesktopThumbnailer *thumbnailer = XFDESKTOP_THUMBNAILER(object);
+
+ if(thumbnailer->priv->proxy)
+ g_object_unref(thumbnailer->priv->proxy);
+
+ if(thumbnailer->priv->supported_mimetypes)
+ g_free(thumbnailer->priv->supported_mimetypes);
+
+ if(thumbnailer->priv) {
+ g_free(thumbnailer->priv);
+ thumbnailer->priv = NULL;
+ }
+
+ thumbnailer_object = NULL;
+}
+
+/**
+ * xfdesktop_thumbnailer_finalize:
+ * @object:
+ *
+ */
+static void
+xfdesktop_thumbnailer_finalize(GObject *object)
+{
+}
+
+/**
+ * xfdesktop_thumbnailer_new:
+ *
+ *
+ * Singleton
+ */
+XfdesktopThumbnailer *
+xfdesktop_thumbnailer_new(void)
+{
+ if(thumbnailer_object == NULL) {
+ thumbnailer_object = g_object_new(XFDESKTOP_TYPE_THUMBNAILER, NULL);
+ } else {
+ g_object_ref(thumbnailer_object);
+ }
+
+ return thumbnailer_object;
+}
+
+static gchar *
+xfdesktop_get_file_mimetype(gchar *file)
+{
+ GFile *temp_file;
+ GFileInfo *file_info;
+ gchar *mime_type = NULL;
+
+ g_return_val_if_fail(file != NULL, NULL);
+
+ temp_file = g_file_new_for_path(file);
+
+ g_return_val_if_fail(temp_file != NULL, NULL);
+
+ file_info = g_file_query_info(temp_file,
+ "standard::content-type",
+ 0,
+ NULL,
+ NULL);
+
+ if(file_info != NULL) {
+ mime_type = g_strdup(g_file_info_get_content_type(file_info));
+
+ g_object_unref(file_info);
+ }
+
+ g_object_unref(temp_file);
+
+ return mime_type;
+}
+
+gboolean
+xfdesktop_thumbnailer_is_supported(XfdesktopThumbnailer *thumbnailer,
+ gchar *file)
+{
+ guint n;
+ gchar *mime_type = NULL;
+
+ g_return_val_if_fail(XFDESKTOP_IS_THUMBNAILER(thumbnailer), FALSE);
+ g_return_val_if_fail(file != NULL, FALSE);
+
+ mime_type = xfdesktop_get_file_mimetype(file);
+
+ if(mime_type == NULL) {
+ g_warning("File has no mime type");
+ return FALSE;
+ }
+
+ if(thumbnailer->priv->supported_mimetypes != NULL) {
+ for(n = 0; thumbnailer->priv->supported_mimetypes[n] != NULL; ++n) {
+ if(g_content_type_is_a (mime_type, thumbnailer->priv->supported_mimetypes[n])) {
+ g_free(mime_type);
+ return TRUE;
+ }
+ }
+ }
+
+ g_free(mime_type);
+ return FALSE;
+}
+
+/**
+ * xfdesktop_thumbnailer_queue_thumbnail:
+ *
+ * Queues a file for thumbnail creation.
+ * A "thumbnail-ready" signal will be emitted when the thumbnail is ready.
+ * The signal will pass 2 parameters: a gchar *file which will be file
+ * that's passed in here and a gchar *thumbnail_file which will be the
+ * location of the thumbnail.
+ */
+gboolean
+xfdesktop_thumbnailer_queue_thumbnail(XfdesktopThumbnailer *thumbnailer,
+ gchar *file)
+{
+ g_return_val_if_fail(XFDESKTOP_IS_THUMBNAILER(thumbnailer), FALSE);
+ g_return_val_if_fail(file != NULL, FALSE);
+
+ if(!xfdesktop_thumbnailer_is_supported(thumbnailer, file)) {
+ g_debug("file: %s not supported", file);
+ return FALSE;
+ }
+ if(thumbnailer->priv->request_timer_id) {
+ g_source_remove(thumbnailer->priv->request_timer_id);
+
+ if(thumbnailer->priv->handle && thumbnailer->priv->proxy != NULL) {
+ if(dbus_g_proxy_call(thumbnailer->priv->proxy,
+ "Dequeue",
+ NULL,
+ G_TYPE_UINT, thumbnailer->priv->handle,
+ G_TYPE_INVALID) == FALSE)
+ {
+ g_warning("Dequeue of thumbnailer->priv->handle: %d failed",
+ thumbnailer->priv->handle);
+ }
+
+ thumbnailer->priv->handle = 0;
+ }
+ }
+
+ if(g_slist_find(thumbnailer->priv->queue, file) == NULL) {
+ thumbnailer->priv->queue = g_slist_prepend(thumbnailer->priv->queue,
+ file);
+ }
+
+ thumbnailer->priv->request_timer_id = g_timeout_add_full(
+ G_PRIORITY_LOW,
+ 300,
+ (GSourceFunc)xfdesktop_thumbnailer_queue_request_timer,
+ thumbnailer,
+ NULL);
+
+ return TRUE;
+}
+
+/**
+ * xfdesktop_thumbnailer_dequeue_thumbnail:
+ *
+ * Removes a file from the list of pending thumbnail creations.
+ * This is not guaranteed to always remove the file, if processing
+ * of that thumbnail has started it won't stop.
+ */
+void
+xfdesktop_thumbnailer_dequeue_thumbnail(XfdesktopThumbnailer *thumbnailer,
+ gchar *file)
+{
+ g_return_if_fail(XFDESKTOP_IS_THUMBNAILER(thumbnailer));
+ g_return_if_fail(file != NULL);
+
+ if(thumbnailer->priv->request_timer_id) {
+ g_source_remove(thumbnailer->priv->request_timer_id);
+
+ if(thumbnailer->priv->handle && thumbnailer->priv->proxy) {
+ if(dbus_g_proxy_call(thumbnailer->priv->proxy,
+ "Dequeue",
+ NULL,
+ G_TYPE_UINT, thumbnailer->priv->handle,
+ G_TYPE_INVALID) == FALSE)
+ {
+ g_warning("Dequeue of thumbnailer->priv->handle: %d failed",
+ thumbnailer->priv->handle);
+ }
+ }
+ thumbnailer->priv->handle = 0;
+ }
+
+ if(g_slist_find(thumbnailer->priv->queue, file) != NULL) {
+ thumbnailer->priv->queue = g_slist_remove_all(
+ thumbnailer->priv->queue,
+ file);
+ }
+
+ thumbnailer->priv->request_timer_id = g_timeout_add_full(
+ G_PRIORITY_LOW,
+ 300,
+ (GSourceFunc)xfdesktop_thumbnailer_queue_request_timer,
+ thumbnailer,
+ NULL);
+}
+
+static gboolean
+xfdesktop_thumbnailer_queue_request_timer(XfdesktopThumbnailer *thumbnailer)
+{
+ gchar **uris;
+ gchar **mimetypes;
+ GSList *iter;
+ gint i = 0;
+ GFile *file;
+ GError *error = NULL;
+ gchar *thumbnail_flavor;
+
+ g_return_val_if_fail(XFDESKTOP_IS_THUMBNAILER(thumbnailer), FALSE);
+
+ uris = g_new0(gchar *,
+ g_slist_length(thumbnailer->priv->queue) + 1);
+ mimetypes = g_new0(gchar *,
+ g_slist_length (thumbnailer->priv->queue) + 1);
+
+ iter = thumbnailer->priv->queue;
+ while(iter) {
+ if(iter->data) {
+ file = g_file_new_for_path(iter->data);
+ uris[i] = g_file_get_uri(file);
+ mimetypes[i] = xfdesktop_get_file_mimetype(iter->data);
+ g_object_unref(file);
+ }
+ iter = g_slist_next(iter);
+ i++;
+ }
+
+ if(thumbnailer->priv->big_thumbnails == TRUE)
+ thumbnail_flavor = "large";
+ else
+ thumbnail_flavor = "normal";
+
+ if(thumbnailer->priv->proxy != NULL) {
+ if(dbus_g_proxy_call(thumbnailer->priv->proxy,
+ "Queue",
+ &error,
+ G_TYPE_STRV, uris,
+ G_TYPE_STRV, mimetypes,
+ G_TYPE_STRING, thumbnail_flavor,
+ G_TYPE_STRING, "default",
+ G_TYPE_UINT, 0,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &thumbnailer->priv->handle,
+ G_TYPE_INVALID) == FALSE)
+ {
+ if(error != NULL)
+ g_warning("DBUS-call failed: %s", error->message);
+ }
+ }
+
+ g_free(uris);
+ g_free(mimetypes);
+
+ if(error)
+ g_error_free(error);
+
+ thumbnailer->priv->request_timer_id = 0;
+
+ return FALSE;
+}
+
+static void
+xfdesktop_thumbnailer_request_finished_dbus(DBusGProxy *proxy,
+ gint handle,
+ gpointer data)
+{
+ XfdesktopThumbnailer *thumbnailer = XFDESKTOP_THUMBNAILER(data);
+
+ g_return_if_fail(XFDESKTOP_IS_THUMBNAILER(thumbnailer));
+
+ thumbnailer->priv->handle = 0;
+}
+
+static void
+xfdesktop_thumbnailer_thumbnail_ready_dbus(DBusGProxy *proxy,
+ gint handle,
+ const gchar **uri,
+ gpointer data)
+{
+ XfdesktopThumbnailer *thumbnailer = XFDESKTOP_THUMBNAILER(data);
+ gchar *thumbnail_location;
+ GFile *file;
+ GSList *iter = thumbnailer->priv->queue;
+ gchar *f_uri, *f_uri_checksum, *filename;
+ gchar *thumbnail_flavor;
+ gint x = 0;
+
+ g_return_if_fail(XFDESKTOP_IS_THUMBNAILER(thumbnailer));
+
+ while(iter) {
+ if((uri[x] == NULL) || (iter->data == NULL)) {
+ break;
+ }
+
+ file = g_file_new_for_path(iter->data);
+ f_uri = g_file_get_uri(file);
+
+ if(strcmp (uri[x], f_uri) == 0) {
+ /* The thumbnail is in the format/location
+ * /homedir/.thumbnails/(normal|large)/MD5_Hash_Of_URI.png
+ */
+ f_uri_checksum = g_compute_checksum_for_string(G_CHECKSUM_MD5,
+ f_uri, strlen (f_uri));
+
+ if(thumbnailer->priv->big_thumbnails == TRUE)
+ thumbnail_flavor = "large";
+ else
+ thumbnail_flavor = "normal";
+
+ filename = g_strconcat(f_uri_checksum, ".png", NULL);
+
+ thumbnail_location = g_build_path("/", g_get_home_dir(),
+ ".thumbnails", thumbnail_flavor,
+ filename, NULL);
+
+ g_debug("thumbnail-ready src: %s thumbnail: %s",
+ (char*)iter->data,
+ thumbnail_location);
+
+ g_signal_emit(G_OBJECT(thumbnailer),
+ thumbnailer_signals[THUMBNAIL_READY],
+ 0,
+ iter->data,
+ thumbnail_location);
+
+ thumbnailer->priv->queue = g_slist_remove(thumbnailer->priv->queue,
+ iter->data);
+
+ iter = thumbnailer->priv->queue;
+ x++;
+
+ g_free(filename);
+ g_free(f_uri_checksum);
+ } else {
+ iter = g_slist_next(iter);
+ }
+
+ g_object_unref(file);
+ g_free(f_uri);
+ }
+}
+
+/**
+ * xfdesktop_thumbnailer_delete_thumbnail:
+ *
+ * Tells the thumbnail service the src_file will be deleted.
+ * This function should be called when the file is deleted or moved so
+ * the thumbnail file doesn't take up space on the user's drive.
+ */
+void
+xfdesktop_thumbnailer_delete_thumbnail(XfdesktopThumbnailer *thumbnailer, gchar *src_file)
+{
+ DBusGConnection *connection;
+ gchar **uris;
+ GFile *file;
+ GError *error = NULL;
+ static DBusGProxy *cache = NULL;
+
+ if(!cache) {
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+ if (connection != NULL) {
+ cache = dbus_g_proxy_new_for_name(connection,
+ "org.freedesktop.thumbnails.Cache1",
+ "/org/freedesktop/thumbnails/Cache1",
+ "org.freedesktop.thumbnails.Cache1");
+
+ dbus_g_connection_unref(connection);
+ }
+ }
+
+ file = g_file_new_for_path(src_file);
+
+ if(cache) {
+ uris = g_new0 (gchar *, 2);
+ uris[0] = g_file_get_uri(file);
+ dbus_g_proxy_call(cache, "Delete", &error, G_TYPE_STRV, uris, G_TYPE_INVALID, G_TYPE_INVALID);
+ if(error != NULL) {
+ g_warning("DBUS-call failed:%s", error->message);
+ }
+ g_free(uris);
+ }
+
+ g_object_unref(file);
+ if(error)
+ g_error_free(error);
+}
diff --git a/common/xfdesktop-thumbnailer.h b/common/xfdesktop-thumbnailer.h
new file mode 100644
index 0000000..842f155
--- /dev/null
+++ b/common/xfdesktop-thumbnailer.h
@@ -0,0 +1,76 @@
+/*
+ * xfdesktop - xfce4's desktop manager
+ *
+ * Copyright(c) 2006 Brian Tarricone, <bjt23 at cornell.edu>
+ * Copyright(c) 2006 Benedikt Meurer, <benny at xfce.org>
+ * Copyright(c) 2010-2011 Jannis Pohlmann, <jannis at xfce.org>
+ *
+ * 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-thumbnailer is based on thumbnailer code from Ristretto
+ * Copyright (c) Stephan Arts 2009-2011 <stephan at xfce.org>
+ */
+
+#ifndef __XFDESKTOP_THUMBNAILER_H__
+#define __XFDESKTOP_THUMBNAILER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define XFDESKTOP_TYPE_THUMBNAILER (xfdesktop_thumbnailer_get_type())
+#define XFDESKTOP_THUMBNAILER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XFDESKTOP_TYPE_THUMBNAILER, XfdesktopThumbnailer))
+#define XFDESKTOP_IS_THUMBNAILER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XFDESKTOP_TYPE_THUMBNAILER))
+#define XFDESKTOP_THUMBNAILER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XFDESKTOP_TYPE_THUMBNAILER, XfdesktopThumbnailerClass))
+#define XFDESKTOP_IS_THUMBNAILER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFDESKTOP_TYPE_THUMBNAILER()))
+
+typedef struct _XfdesktopThumbnailer XfdesktopThumbnailer;
+typedef struct _XfdesktopThumbnailerPriv XfdesktopThumbnailerPriv;
+
+struct _XfdesktopThumbnailer
+{
+ GObject parent;
+
+ XfdesktopThumbnailerPriv *priv;
+};
+
+typedef struct _XfdesktopThumbnailerClass XfdesktopThumbnailerClass;
+
+struct _XfdesktopThumbnailerClass
+{
+ GObjectClass parent_class;
+
+ /*< signals >*/
+ void (*thumbnail_ready)(gchar *src_file, gchar *thumb_file);
+};
+
+XfdesktopThumbnailer * xfdesktop_thumbnailer_new(void);
+
+GType xfdesktop_thumbnailer_get_type(void);
+
+gboolean xfdesktop_thumbnailer_is_supported(XfdesktopThumbnailer *thumbnailer,
+ gchar *file);
+
+gboolean xfdesktop_thumbnailer_queue_thumbnail(XfdesktopThumbnailer *thumbnailer,
+ gchar *file);
+void xfdesktop_thumbnailer_dequeue_thumbnail(XfdesktopThumbnailer *thumbnailer,
+ gchar *file);
+
+void xfdesktop_thumbnailer_delete_thumbnail(XfdesktopThumbnailer *thumbnailer,
+ gchar *src_file);
+
+G_END_DECLS
+
+#endif /* __XFDESKTOP_THUMBNAILER_H__ */
diff --git a/doc/README.xfconf b/doc/README.xfconf
index 2fa1c40..3832521 100644
--- a/doc/README.xfconf
+++ b/doc/README.xfconf
@@ -37,6 +37,7 @@ property is listd after the name.
<use-custom-font-size bool>
<font-size uint>
<icon-size uint>
+ <show-thumbnails bool>
<file-icons>
<show-filesystem bool>
<show-home bool>
diff --git a/settings/main.c b/settings/main.c
index 1f76be9..a6be3b8 100644
--- a/settings/main.c
+++ b/settings/main.c
@@ -70,6 +70,7 @@
#define DESKTOP_ICONS_ICON_SIZE_PROP "/desktop-icons/icon-size"
#define DESKTOP_ICONS_FONT_SIZE_PROP "/desktop-icons/font-size"
#define DESKTOP_ICONS_CUSTOM_FONT_SIZE_PROP "/desktop-icons/use-custom-font-size"
+#define DESKTOP_ICONS_SHOW_THUMBNAILS_PROP "/desktop-icons/show-thumbnails"
#define DESKTOP_ICONS_SHOW_HOME "/desktop-icons/file-icons/show-home"
#define DESKTOP_ICONS_SHOW_TRASH "/desktop-icons/file-icons/show-trash"
#define DESKTOP_ICONS_SHOW_FILESYSTEM "/desktop-icons/file-icons/show-filesystem"
@@ -758,6 +759,41 @@ cb_xfdesktop_chk_custom_font_size_toggled(GtkCheckButton *button,
}
static gboolean
+xfdesktop_spin_icon_size_timer(GtkSpinButton *button)
+{
+ XfconfChannel *channel = g_object_get_data(G_OBJECT(button), "xfconf-chanel");
+
+ g_return_val_if_fail(XFCONF_IS_CHANNEL(channel), FALSE);
+
+ xfconf_channel_set_uint(channel,
+ DESKTOP_ICONS_ICON_SIZE_PROP,
+ gtk_spin_button_get_value(button));
+
+ return FALSE;
+}
+
+static void
+cb_xfdesktop_spin_icon_size_changed(GtkSpinButton *button,
+ gpointer user_data)
+{
+ guint timer_id = 0;
+
+ g_object_set_data(G_OBJECT(button), "xfconf-chanel", user_data);
+
+ timer_id = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(button), "timer-id"));
+ if(timer_id != 0) {
+ g_source_remove(timer_id);
+ timer_id = 0;
+ }
+
+ timer_id = g_timeout_add(2000,
+ (GSourceFunc)xfdesktop_spin_icon_size_timer,
+ button);
+
+ g_object_set_data(G_OBJECT(button), "timer-id", GUINT_TO_POINTER(timer_id));
+}
+
+static gboolean
xfdesktop_settings_save_backdrop_list(AppearancePanel *panel,
GtkTreeModel *model)
{
@@ -1225,11 +1261,23 @@ xfdesktop_settings_dialog_add_screens(GtkBuilder *main_gxml,
{
gint i, j, nmonitors, nscreens;
GtkWidget *appearance_container, *chk_custom_font_size,
- *spin_font_size, *color_style_widget, *w, *box;
+ *spin_font_size, *color_style_widget, *w, *box,
+ *spin_icon_size, *chk_show_thumbnails;
appearance_container = GTK_WIDGET(gtk_builder_get_object(main_gxml,
"notebook_screens"));
+ spin_icon_size = GTK_WIDGET(gtk_builder_get_object(main_gxml, "spin_icon_size"));
+
+ g_signal_connect(G_OBJECT(spin_icon_size), "value-changed",
+ G_CALLBACK(cb_xfdesktop_spin_icon_size_changed),
+ channel);
+
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_icon_size),
+ xfconf_channel_get_uint(channel,
+ DESKTOP_ICONS_ICON_SIZE_PROP,
+ DEFAULT_ICON_SIZE));
+
chk_custom_font_size = GTK_WIDGET(gtk_builder_get_object(main_gxml,
"chk_custom_font_size"));
spin_font_size = GTK_WIDGET(gtk_builder_get_object(main_gxml, "spin_font_size"));
@@ -1238,6 +1286,9 @@ xfdesktop_settings_dialog_add_screens(GtkBuilder *main_gxml,
G_CALLBACK(cb_xfdesktop_chk_custom_font_size_toggled),
spin_font_size);
+ chk_show_thumbnails = GTK_WIDGET(gtk_builder_get_object(main_gxml,
+ "chk_show_thumbnails"));
+
nscreens = gdk_display_get_n_screens(gdk_display_get_default());
for(i = 0; i < nscreens; ++i) {
@@ -1477,16 +1528,15 @@ xfdesktop_settings_dialog_add_screens(GtkBuilder *main_gxml,
#endif
xfconf_g_property_bind(channel, DESKTOP_ICONS_STYLE_PROP, G_TYPE_INT,
G_OBJECT(w), "active");
- xfconf_g_property_bind(channel, DESKTOP_ICONS_ICON_SIZE_PROP, G_TYPE_UINT,
- G_OBJECT(gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(gtk_builder_get_object(main_gxml,
- "spin_icon_size")))),
- "value");
xfconf_g_property_bind(channel, DESKTOP_ICONS_FONT_SIZE_PROP, G_TYPE_DOUBLE,
G_OBJECT(gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin_font_size))),
"value");
xfconf_g_property_bind(channel, DESKTOP_ICONS_CUSTOM_FONT_SIZE_PROP,
G_TYPE_BOOLEAN, G_OBJECT(chk_custom_font_size),
"active");
+ xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_THUMBNAILS_PROP,
+ G_TYPE_BOOLEAN, G_OBJECT(chk_show_thumbnails),
+ "active");
setup_special_icon_list(main_gxml, channel);
}
diff --git a/settings/xfdesktop-settings-ui.glade b/settings/xfdesktop-settings-ui.glade
index 0ae289c..5fcc836 100644
--- a/settings/xfdesktop-settings-ui.glade
+++ b/settings/xfdesktop-settings-ui.glade
@@ -685,6 +685,17 @@
</packing>
</child>
<child>
+ <object class="GtkCheckButton" id="chk_show_thumbnails">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Show t_humbnails</property>
+ <property name="tooltip-text" translatable="yes">Select this option to display preview-able files on the desktop as automatically generated thumbnail icons.</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ <child>
<object class="GtkHBox" id="hbox9">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
diff --git a/src/Makefile.am b/src/Makefile.am
index 5d1fd4d..3adb3d2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,9 +4,7 @@ bin_PROGRAMS = xfdesktop
xfdesktop_built_sources = \
xfce-desktop-enum-types.c \
- xfce-desktop-enum-types.h \
- xfdesktop-marshal.c \
- xfdesktop-marshal.h
+ xfce-desktop-enum-types.h
if HAVE_LIBNOTIFY
xfdesktop_notify_sources = \
@@ -149,17 +147,8 @@ BUILT_SOURCES = \
DISTCLEANFILES = \
$(xfdesktop_built_sources) \
- stamp-xfdesktop-marshal.h \
stamp-xfce-desktop-enum-types.h
-xfdesktop-marshal.h: stamp-xfdesktop-marshal.h
- @true
-stamp-xfdesktop-marshal.h: xfdesktop-marshal.list Makefile
- $(AM_V_GEN) glib-genmarshal --prefix=xfdesktop_marshal xfdesktop-marshal.list --header > xfdesktop-marshal.h && \
- echo timestamp > $(@F)
-xfdesktop-marshal.c: xfdesktop-marshal.list Makefile
- $(AM_V_GEN) echo '#include "xfdesktop-marshal.h"' > xfdesktop-marshal.c && \
- glib-genmarshal --prefix=xfdesktop_marshal xfdesktop-marshal.list --body >> xfdesktop-marshal.c
enum_headers = \
xfce-backdrop.h \
@@ -227,5 +216,4 @@ endif
EXTRA_DIST = \
$(desktop_menu_sources) \
$(desktop_icon_sources) \
- $(desktop_file_icon_sources) \
- xfdesktop-marshal.list
+ $(desktop_file_icon_sources)
diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c
index 8b82fdc..5a897a1 100644
--- a/src/xfdesktop-file-icon-manager.c
+++ b/src/xfdesktop-file-icon-manager.c
@@ -71,6 +71,7 @@
#include "xfdesktop-special-file-icon.h"
#include "xfdesktop-trash-proxy.h"
#include "xfdesktop-volume-icon.h"
+#include "xfdesktop-thumbnailer.h"
#include <libxfce4util/libxfce4util.h>
#include <libxfce4ui/libxfce4ui.h>
@@ -82,6 +83,7 @@
#define SETTING_SHOW_HOME "/desktop-icons/file-icons/show-home"
#define SETTING_SHOW_TRASH "/desktop-icons/file-icons/show-trash"
#define SETTING_SHOW_REMOVABLE "/desktop-icons/file-icons/show-removable"
+#define SETTING_SHOW_THUMBNAILS "/desktop-icons/show-thumbnails"
enum
{
@@ -91,6 +93,7 @@ enum
PROP_SHOW_HOME,
PROP_SHOW_TRASH,
PROP_SHOW_REMOVABLE,
+ PROP_SHOW_THUMBNAILS
};
struct _XfdesktopFileIconManagerPrivate
@@ -117,6 +120,7 @@ struct _XfdesktopFileIconManagerPrivate
gboolean show_removable_media;
gboolean show_special[XFDESKTOP_SPECIAL_FILE_ICON_TRASH+1];
+ gboolean show_thumbnails;
guint save_icons_id;
@@ -129,6 +133,8 @@ struct _XfdesktopFileIconManagerPrivate
GList *thunarx_menu_providers;
GList *thunarx_properties_providers;
#endif
+
+ XfdesktopThumbnailer *thumbnailer;
};
static void xfdesktop_file_icon_manager_set_property(GObject *object,
@@ -175,6 +181,10 @@ static void xfdesktop_file_icon_manager_remove_removable_media(XfdesktopFileIcon
static void xfdesktop_file_icon_position_changed(XfdesktopFileIcon *icon,
gpointer user_data);
+static void xfdesktop_file_icon_manager_update_image(GtkWidget *widget,
+ gchar *srcfile,
+ gchar *thumbfile,
+ XfdesktopFileIconManager *fmanager);
G_DEFINE_TYPE_EXTENDED(XfdesktopFileIconManager,
xfdesktop_file_icon_manager,
@@ -264,6 +274,12 @@ xfdesktop_file_icon_manager_class_init(XfdesktopFileIconManagerClass *klass)
"show removable",
TRUE,
XFDESKTOP_PARAM_FLAGS));
+ g_object_class_install_property(gobject_class, PROP_SHOW_THUMBNAILS,
+ g_param_spec_boolean("show-thumbnails",
+ "show-thumbnails",
+ "show-thumbnails",
+ TRUE,
+ XFDESKTOP_PARAM_FLAGS));
#undef XFDESKTOP_PARAM_FLAGS
xfdesktop_app_info_quark = g_quark_from_static_string("xfdesktop-app-info-quark");
@@ -282,6 +298,10 @@ xfdesktop_file_icon_manager_init(XfdesktopFileIconManager *fmanager)
n_drag_targets);
fmanager->priv->drop_targets = gtk_target_list_new(drop_targets,
n_drop_targets);
+
+ fmanager->priv->thumbnailer = xfdesktop_thumbnailer_new();
+
+ g_signal_connect(G_OBJECT(fmanager->priv->thumbnailer), "thumbnail-ready", G_CALLBACK(xfdesktop_file_icon_manager_update_image), fmanager);
}
static void
@@ -321,6 +341,11 @@ xfdesktop_file_icon_manager_set_property(GObject *object,
g_value_get_boolean(value));
break;
+ case PROP_SHOW_THUMBNAILS:
+ xfdesktop_file_icon_manager_set_show_thumbnails(fmanager,
+ g_value_get_boolean(value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
}
@@ -357,6 +382,10 @@ xfdesktop_file_icon_manager_get_property(GObject *object,
case PROP_SHOW_REMOVABLE:
g_value_set_boolean(value, fmanager->priv->show_removable_media);
break;
+
+ case PROP_SHOW_THUMBNAILS:
+ g_value_set_boolean(value, fmanager->priv->show_thumbnails);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
@@ -377,6 +406,7 @@ xfdesktop_file_icon_manager_finalize(GObject *obj)
gtk_target_list_unref(fmanager->priv->drop_targets);
g_object_unref(fmanager->priv->folder);
+ g_object_unref(fmanager->priv->thumbnailer);
G_OBJECT_CLASS(xfdesktop_file_icon_manager_parent_class)->finalize(obj);
}
@@ -1829,6 +1859,15 @@ xfdesktop_file_icon_manager_add_icon(XfdesktopFileIconManager *fmanager,
gint16 row = -1, col = -1;
gboolean do_add = FALSE;
const gchar *name;
+ GFile *file;
+
+ 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));
+ }
+
name = xfdesktop_icon_peek_label(XFDESKTOP_ICON(icon));
if(xfdesktop_file_icon_manager_get_cached_icon_position(fmanager, name,
@@ -1839,7 +1878,6 @@ xfdesktop_file_icon_manager_add_icon(XfdesktopFileIconManager *fmanager,
do_add = TRUE;
} else {
if(defer_if_missing) {
- GFile *file = xfdesktop_file_icon_peek_file(icon);
fmanager->priv->deferred_icons = g_list_prepend(fmanager->priv->deferred_icons,
g_object_ref(file));
} else
@@ -2195,6 +2233,13 @@ xfdesktop_file_icon_manager_file_changed(GFileMonitor *monitor,
icon = g_hash_table_lookup(fmanager->priv->icons, file);
if(icon) {
+ /* Always try to remove thumbnail so it doesn't take up
+ * space on the user's disk.
+ */
+ xfdesktop_thumbnailer_delete_thumbnail(fmanager->priv->thumbnailer,
+ g_file_get_path(file));
+ xfdesktop_icon_delete_thumbnail(XFDESKTOP_ICON(icon));
+
xfdesktop_icon_view_remove_item(fmanager->priv->icon_view,
XFDESKTOP_ICON(icon));
g_hash_table_remove(fmanager->priv->icons, file);
@@ -3136,6 +3181,8 @@ xfdesktop_file_icon_manager_new(GFile *folder,
G_OBJECT(fmanager), "show-trash");
xfconf_g_property_bind(channel, SETTING_SHOW_REMOVABLE, G_TYPE_BOOLEAN,
G_OBJECT(fmanager), "show-removable");
+ xfconf_g_property_bind(channel, SETTING_SHOW_THUMBNAILS, G_TYPE_BOOLEAN,
+ G_OBJECT(fmanager), "show-thumbnails");
return XFDESKTOP_ICON_VIEW_MANAGER(fmanager);
}
@@ -3167,6 +3214,64 @@ xfdesktop_file_icon_manager_get_show_removable_media(XfdesktopFileIconManager *m
return manager->priv->show_removable_media;
}
+static void
+xfdesktop_file_icon_manager_requeue_thumbnails(gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ GFile *file = key;
+ XfdesktopFileIconManager *fmanager = XFDESKTOP_FILE_ICON_MANAGER(data);
+
+ xfdesktop_thumbnailer_queue_thumbnail(fmanager->priv->thumbnailer,
+ g_file_get_path(file));
+}
+
+static void
+xfdesktop_file_icon_manager_remove_thumbnails(gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ XfdesktopRegularFileIcon *icon = XFDESKTOP_REGULAR_FILE_ICON(value);
+
+ xfdesktop_icon_delete_thumbnail(XFDESKTOP_ICON(icon));
+}
+
+void
+xfdesktop_file_icon_manager_set_show_thumbnails(XfdesktopFileIconManager *manager,
+ gboolean show_thumbnails)
+{
+ g_return_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager));
+
+ if(show_thumbnails == manager->priv->show_thumbnails)
+ return;
+
+ manager->priv->show_thumbnails = show_thumbnails;
+
+ if(!manager->priv->inited)
+ return;
+
+ if(show_thumbnails) {
+ /* We have to request to create the thumbnails everytime. */
+ g_hash_table_foreach(manager->priv->icons,
+ xfdesktop_file_icon_manager_requeue_thumbnails,
+ manager);
+ } else {
+ /* We have to remove the thumbnails because the regular file
+ * icons can't easily check if thumbnails are allowed.
+ */
+ g_hash_table_foreach(manager->priv->icons,
+ xfdesktop_file_icon_manager_remove_thumbnails,
+ manager);
+ }
+}
+
+gboolean
+xfdesktop_file_icon_manager_get_show_thumbnails(XfdesktopFileIconManager *manager)
+{
+ g_return_val_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager), FALSE);
+ return manager->priv->show_thumbnails;
+}
+
void
xfdesktop_file_icon_manager_set_show_special_file(XfdesktopFileIconManager *manager,
XfdesktopSpecialFileIconType type,
@@ -3208,3 +3313,26 @@ xfdesktop_file_icon_manager_get_show_special_file(XfdesktopFileIconManager *mana
return manager->priv->show_special[type];
}
+
+static void
+xfdesktop_file_icon_manager_update_image(GtkWidget *widget,
+ gchar *srcfile,
+ gchar *thumbfile,
+ XfdesktopFileIconManager *manager)
+{
+ GFile *file;
+ XfdesktopIcon *icon;
+
+ g_return_if_fail(srcfile && thumbfile);
+ g_return_if_fail(XFDESKTOP_FILE_ICON_MANAGER(manager));
+
+ file = g_file_new_for_path(srcfile);
+
+ icon = g_hash_table_lookup(manager->priv->icons, file);
+ if(icon)
+ {
+ g_object_unref(file);
+ file = g_file_new_for_path(thumbfile);
+ xfdesktop_icon_set_thumbnail_file(icon, file);
+ }
+}
diff --git a/src/xfdesktop-file-icon-manager.h b/src/xfdesktop-file-icon-manager.h
index 703a6f4..1c45ecb 100644
--- a/src/xfdesktop-file-icon-manager.h
+++ b/src/xfdesktop-file-icon-manager.h
@@ -64,6 +64,10 @@ void xfdesktop_file_icon_manager_set_show_special_file(XfdesktopFileIconManager
gboolean show_special_file);
gboolean xfdesktop_file_icon_manager_get_show_special_file(XfdesktopFileIconManager *manager,
XfdesktopSpecialFileIconType type);
+void xfdesktop_file_icon_manager_set_show_thumbnails(XfdesktopFileIconManager *manager,
+ gboolean show_thumbnails);
+gboolean xfdesktop_file_icon_manager_get_show_thumbnails(XfdesktopFileIconManager *manager);
+
G_END_DECLS
diff --git a/src/xfdesktop-icon-view.c b/src/xfdesktop-icon-view.c
index e1c918a..fb18856 100644
--- a/src/xfdesktop-icon-view.c
+++ b/src/xfdesktop-icon-view.c
@@ -169,6 +169,7 @@ struct _XfdesktopIconViewPrivate
gdouble cell_text_width_proportion;
gboolean ellipsize_icon_labels;
+ guint tooltip_size;
};
static gboolean xfdesktop_icon_view_button_press(GtkWidget *widget,
@@ -546,6 +547,13 @@ xfdesktop_icon_view_class_init(XfdesktopIconViewClass *klass)
0.0, 50.0, 4.0,
G_PARAM_READABLE));
+ gtk_widget_class_install_style_property(widget_class,
+ g_param_spec_uint("tooltip-size",
+ "Tooltip Image Size",
+ "The size of the tooltip image preview",
+ 0, 512, 128,
+ G_PARAM_READABLE));
+
/* same binding entries as GtkIconView */
gtk_binding_entry_add_signal(binding_set, GDK_a, GDK_CONTROL_MASK,
"select-all", 0);
@@ -932,7 +940,13 @@ xfdesktop_icon_view_show_tooltip(GtkWidget *widget,
tip_text = xfdesktop_icon_peek_tooltip(icon_view->priv->item_under_pointer);
if(!tip_text)
return FALSE;
-
+
+ if(icon_view->priv->tooltip_size > 0) {
+ gtk_tooltip_set_icon(tooltip,
+ xfdesktop_icon_peek_pixbuf(icon_view->priv->item_under_pointer,
+ icon_view->priv->tooltip_size));
+ }
+
gtk_tooltip_set_text(tooltip, tip_text);
return TRUE;
@@ -1382,7 +1396,6 @@ xfdesktop_icon_view_drag_drop(GtkWidget *widget,
/* clear out old extents, if any */
/* FIXME: is this right? */
- //xfdesktop_icon_mark_extents_dirty(icon);
xfdesktop_icon_view_invalidate_icon(icon_view, icon, TRUE);
DBG("drag succeeded");
@@ -1520,12 +1533,14 @@ xfdesktop_icon_view_style_set(GtkWidget *widget,
"cell-padding", &icon_view->priv->cell_padding,
"cell-text-width-proportion", &icon_view->priv->cell_text_width_proportion,
"ellipsize-icon-labels", &icon_view->priv->ellipsize_icon_labels,
+ "tooltip-size", &icon_view->priv->tooltip_size,
NULL);
DBG("cell spacing is %d", icon_view->priv->cell_spacing);
DBG("cell padding is %d", icon_view->priv->cell_padding);
DBG("cell text width proportion is %f", icon_view->priv->cell_text_width_proportion);
DBG("ellipsize icon label is %s", icon_view->priv->ellipsize_icon_labels?"true":"false");
+ DBG("tooltip size is %d", icon_view->priv->tooltip_size);
if(icon_view->priv->selection_box_color) {
gdk_color_free(icon_view->priv->selection_box_color);
@@ -2628,29 +2643,17 @@ xfdesktop_icon_view_paint_icon(XfdesktopIconView *icon_view,
playout = icon_view->priv->playout;
- if(xfdesktop_icon_get_extents(icon, &pixbuf_extents,
- &text_extents, &total_extents))
+ xfdesktop_icon_get_extents(icon, &pixbuf_extents,
+ &text_extents, &total_extents);
+ xfdesktop_icon_view_setup_pango_layout(icon_view, icon, playout);
+
+ if(!xfdesktop_icon_view_update_icon_extents(icon_view, icon,
+ &pixbuf_extents,
+ &text_extents,
+ &total_extents))
{
- xfdesktop_icon_view_setup_pango_layout(icon_view, icon, playout);
- } else {
- /* if we get here, it's likely that the expose area doesn't
- * include everything we *actually* need to repaint. the
- * extents should be recalculated before invalidating rects
- * in the first place. for now just fix it up and re-expose
- * the correct area. */
- if(!xfdesktop_icon_view_update_icon_extents(icon_view, icon,
- &pixbuf_extents,
- &text_extents,
- &total_extents))
- {
- g_warning("Can't update extents for icon '%s'",
- xfdesktop_icon_peek_label(icon));
- } else {
- gtk_widget_queue_draw_area(GTK_WIDGET(icon_view),
- total_extents.x, total_extents.y,
- total_extents.width, total_extents.height);
- }
- return;
+ g_warning("Can't update extents for icon '%s'",
+ xfdesktop_icon_peek_label(icon));
}
if(g_list_find(icon_view->priv->selected_icons, icon)) {
@@ -2790,7 +2793,6 @@ xfdesktop_grid_do_resize(XfdesktopIconView *icon_view)
/* move all icons into the pending_icons list */
for(l = icon_view->priv->icons; l; l = l->next) {
- xfdesktop_icon_mark_extents_dirty(XFDESKTOP_ICON(l->data));
g_signal_handlers_disconnect_by_func(G_OBJECT(l->data),
G_CALLBACK(xfdesktop_icon_view_icon_changed),
icon_view);
@@ -3210,7 +3212,6 @@ xfdesktop_icon_view_remove_item(XfdesktopIconView *icon_view,
if(xfdesktop_icon_get_position(icon, &row, &col)) {
xfdesktop_icon_view_invalidate_icon(icon_view, icon, FALSE);
- xfdesktop_icon_mark_extents_dirty(icon);
xfdesktop_grid_set_position_free(icon_view, row, col);
}
icon_view->priv->icons = g_list_delete_link(icon_view->priv->icons, l);
@@ -3258,7 +3259,6 @@ xfdesktop_icon_view_remove_all(XfdesktopIconView *icon_view)
if(xfdesktop_icon_get_position(icon, &row, &col)) {
xfdesktop_icon_view_invalidate_icon(icon_view, icon, FALSE);
xfdesktop_grid_set_position_free(icon_view, row, col);
- xfdesktop_icon_mark_extents_dirty(icon);
}
g_signal_handlers_disconnect_by_func(G_OBJECT(l->data),
diff --git a/src/xfdesktop-icon.c b/src/xfdesktop-icon.c
index 431ba79..38c1538 100644
--- a/src/xfdesktop-icon.c
+++ b/src/xfdesktop-icon.c
@@ -37,7 +37,6 @@ struct _XfdesktopIconPrivate
gint16 row;
gint16 col;
- gboolean extents_dirty;
GdkRectangle pixbuf_extents;
GdkRectangle text_extents;
GdkRectangle total_extents;
@@ -116,7 +115,6 @@ xfdesktop_icon_init(XfdesktopIcon *icon)
{
icon->priv = G_TYPE_INSTANCE_GET_PRIVATE(icon, XFDESKTOP_TYPE_ICON,
XfdesktopIconPrivate);
- icon->priv->extents_dirty = TRUE;
}
@@ -158,7 +156,6 @@ xfdesktop_icon_set_extents(XfdesktopIcon *icon,
icon->priv->pixbuf_extents = *pixbuf_extents;
icon->priv->text_extents = *text_extents;
icon->priv->total_extents = *total_extents;
- icon->priv->extents_dirty = FALSE;
}
gboolean
@@ -169,9 +166,6 @@ xfdesktop_icon_get_extents(XfdesktopIcon *icon,
{
g_return_val_if_fail(XFDESKTOP_IS_ICON(icon), FALSE);
- if(icon->priv->extents_dirty)
- return FALSE;
-
if(pixbuf_extents)
*pixbuf_extents = icon->priv->pixbuf_extents;
if(text_extents)
@@ -182,16 +176,6 @@ xfdesktop_icon_get_extents(XfdesktopIcon *icon,
return TRUE;
}
-void
-xfdesktop_icon_mark_extents_dirty(XfdesktopIcon *icon)
-{
- g_return_if_fail(XFDESKTOP_IS_ICON(icon));
-
- icon->priv->extents_dirty = TRUE;
-}
-
-
-
/*< required >*/
GdkPixbuf *
xfdesktop_icon_peek_pixbuf(XfdesktopIcon *icon,
@@ -283,6 +267,37 @@ xfdesktop_icon_peek_tooltip(XfdesktopIcon *icon)
}
/*< optional >*/
+void xfdesktop_icon_delete_thumbnail(XfdesktopIcon *icon)
+{
+ XfdesktopIconClass *klass;
+
+ g_return_if_fail(XFDESKTOP_IS_ICON(icon));
+
+ klass = XFDESKTOP_ICON_GET_CLASS(icon);
+
+ if(!klass->delete_thumbnail_file)
+ return;
+
+ klass->delete_thumbnail_file(icon);
+}
+
+/*< optional >*/
+void
+xfdesktop_icon_set_thumbnail_file(XfdesktopIcon *icon, GFile *file)
+{
+ XfdesktopIconClass *klass;
+
+ g_return_if_fail(XFDESKTOP_IS_ICON(icon));
+
+ klass = XFDESKTOP_ICON_GET_CLASS(icon);
+
+ if(!klass->set_thumbnail_file)
+ return;
+
+ klass->set_thumbnail_file(icon, file);
+}
+
+/*< optional >*/
gboolean
xfdesktop_icon_populate_context_menu(XfdesktopIcon *icon,
GtkWidget *menu)
@@ -312,7 +327,6 @@ void
xfdesktop_icon_pixbuf_changed(XfdesktopIcon *icon)
{
g_return_if_fail(XFDESKTOP_IS_ICON(icon));
- xfdesktop_icon_mark_extents_dirty(icon);
g_signal_emit(icon, __signals[SIG_PIXBUF_CHANGED], 0);
}
@@ -320,7 +334,6 @@ void
xfdesktop_icon_label_changed(XfdesktopIcon *icon)
{
g_return_if_fail(XFDESKTOP_IS_ICON(icon));
- xfdesktop_icon_mark_extents_dirty(icon);
g_signal_emit(icon, __signals[SIG_LABEL_CHANGED], 0);
}
@@ -328,7 +341,6 @@ void
xfdesktop_icon_position_changed(XfdesktopIcon *icon)
{
g_return_if_fail(XFDESKTOP_IS_ICON(icon));
- xfdesktop_icon_mark_extents_dirty(icon);
g_signal_emit(icon, __signals[SIG_POS_CHANGED], 0);
}
@@ -337,7 +349,6 @@ void
xfdesktop_icon_selected(XfdesktopIcon *icon)
{
g_return_if_fail(XFDESKTOP_IS_ICON(icon));
- xfdesktop_icon_mark_extents_dirty(icon);
g_signal_emit(G_OBJECT(icon), __signals[SIG_SELECTED], 0, NULL);
}
diff --git a/src/xfdesktop-icon.h b/src/xfdesktop-icon.h
index b838ed5..e42261e 100644
--- a/src/xfdesktop-icon.h
+++ b/src/xfdesktop-icon.h
@@ -73,6 +73,9 @@ struct _XfdesktopIconClass
G_CONST_RETURN gchar *(*peek_tooltip)(XfdesktopIcon *icon);
+ void (*set_thumbnail_file)(XfdesktopIcon *icon, GFile *file);
+ void (*delete_thumbnail_file)(XfdesktopIcon *icon);
+
gboolean (*populate_context_menu)(XfdesktopIcon *icon,
GtkWidget *menu);
};
@@ -105,6 +108,9 @@ gboolean xfdesktop_icon_populate_context_menu(XfdesktopIcon *icon,
GtkWidget *xfdesktop_icon_peek_icon_view(XfdesktopIcon *icon);
+void xfdesktop_icon_set_thumbnail_file(XfdesktopIcon *icon, GFile *file);
+void xfdesktop_icon_delete_thumbnail(XfdesktopIcon *icon);
+
/*< signal triggers >*/
void xfdesktop_icon_pixbuf_changed(XfdesktopIcon *icon);
@@ -123,7 +129,6 @@ gboolean xfdesktop_icon_get_extents(XfdesktopIcon *icon,
GdkRectangle *pixbuf_extents,
GdkRectangle *text_extents,
GdkRectangle *total_extents);
-void xfdesktop_icon_mark_extents_dirty(XfdesktopIcon *icon);
G_END_DECLS
diff --git a/src/xfdesktop-marshal.list b/src/xfdesktop-marshal.list
deleted file mode 100644
index 819c32e..0000000
--- a/src/xfdesktop-marshal.list
+++ /dev/null
@@ -1,2 +0,0 @@
-BOOLEAN:VOID
-BOOLEAN:ENUM,INT
diff --git a/src/xfdesktop-regular-file-icon.c b/src/xfdesktop-regular-file-icon.c
index e14256a..4a2d6c6 100644
--- a/src/xfdesktop-regular-file-icon.c
+++ b/src/xfdesktop-regular-file-icon.c
@@ -68,11 +68,15 @@ struct _XfdesktopRegularFileIconPrivate
GFileInfo *file_info;
GFileInfo *filesystem_info;
GFile *file;
+ GFile *thumbnail_file;
GdkScreen *gscreen;
};
static void xfdesktop_regular_file_icon_finalize(GObject *obj);
+static void xfdesktop_regular_file_icon_set_thumbnail_file(XfdesktopIcon *icon, GFile *file);
+static void xfdesktop_regular_file_icon_delete_thumbnail_file(XfdesktopIcon *icon);
+
static GdkPixbuf *xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon,
gint size);
static G_CONST_RETURN gchar *xfdesktop_regular_file_icon_peek_label(XfdesktopIcon *icon);
@@ -127,6 +131,8 @@ xfdesktop_regular_file_icon_class_init(XfdesktopRegularFileIconClass *klass)
icon_class->get_allowed_drag_actions = xfdesktop_regular_file_icon_get_allowed_drag_actions;
icon_class->get_allowed_drop_actions = xfdesktop_regular_file_icon_get_allowed_drop_actions;
icon_class->do_drop_dest = xfdesktop_regular_file_icon_do_drop_dest;
+ icon_class->set_thumbnail_file = xfdesktop_regular_file_icon_set_thumbnail_file;
+ icon_class->delete_thumbnail_file = xfdesktop_regular_file_icon_delete_thumbnail_file;
file_icon_class->peek_file_info = xfdesktop_regular_file_icon_peek_file_info;
file_icon_class->peek_filesystem_info = xfdesktop_regular_file_icon_peek_filesystem_info;
@@ -171,6 +177,9 @@ xfdesktop_regular_file_icon_finalize(GObject *obj)
if(icon->priv->tooltip)
g_free(icon->priv->tooltip);
+
+ if(icon->priv->thumbnail_file)
+ g_object_unref(icon->priv->thumbnail_file);
G_OBJECT_CLASS(xfdesktop_regular_file_icon_parent_class)->finalize(obj);
}
@@ -201,6 +210,43 @@ xfdesktop_regular_file_icon_invalidate_pixbuf(XfdesktopRegularFileIcon *icon)
}
}
+static void
+xfdesktop_regular_file_icon_delete_thumbnail_file(XfdesktopIcon *icon)
+{
+ XfdesktopRegularFileIcon *file_icon;
+
+ if(!XFDESKTOP_IS_REGULAR_FILE_ICON(icon))
+ return;
+
+ file_icon = XFDESKTOP_REGULAR_FILE_ICON(icon);
+
+ if(file_icon->priv->thumbnail_file) {
+ g_object_unref(file_icon->priv->thumbnail_file);
+ file_icon->priv->thumbnail_file = NULL;
+ }
+
+ xfdesktop_regular_file_icon_invalidate_pixbuf(file_icon);
+ xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon));
+}
+
+static void
+xfdesktop_regular_file_icon_set_thumbnail_file(XfdesktopIcon *icon, GFile *file)
+{
+ XfdesktopRegularFileIcon *file_icon;
+
+ if(!XFDESKTOP_IS_REGULAR_FILE_ICON(icon))
+ return;
+
+ file_icon = XFDESKTOP_REGULAR_FILE_ICON(icon);
+
+ if(file_icon->priv->thumbnail_file)
+ g_object_unref(file_icon->priv->thumbnail_file);
+
+ file_icon->priv->thumbnail_file = file;
+
+ xfdesktop_regular_file_icon_invalidate_pixbuf(file_icon);
+ xfdesktop_icon_pixbuf_changed(XFDESKTOP_ICON(icon));
+}
static GdkPixbuf *
xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon,
@@ -224,6 +270,10 @@ xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon,
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;
@@ -248,12 +298,16 @@ xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon,
g_key_file_free(key_file);
g_free(contents);
}
+ } 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);
+ }
}
- /* release thumbnail path */
- g_object_unref(thumbnail_dir);
- g_free(thumbnail_dir_path);
-
/* load the symlink emblem if necessary */
if(g_file_info_get_attribute_boolean(file_icon->priv->file_info,
G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK))
@@ -280,10 +334,24 @@ xfdesktop_regular_file_icon_peek_pixbuf(XfdesktopIcon *icon,
if(file_icon->priv->file_info)
gicon = g_file_info_get_icon(file_icon->priv->file_info);
-
- file_icon->priv->pix = xfdesktop_file_utils_get_icon(icon_name, gicon,
- size, emblem_pix,
- file_icon->priv->pix_opacity);
+
+ 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);
+ }
+ } else {
+ file_icon->priv->pix = xfdesktop_file_utils_get_icon(icon_name, gicon,
+ size, emblem_pix,
+ file_icon->priv->pix_opacity);
+ }
file_icon->priv->cur_pix_size = size;
More information about the Xfce4-commits
mailing list