[Xfce4-commits] <thunar:master> Merge branch 'jannis/thumbnailer-improvements'
Jannis Pohlmann
noreply at xfce.org
Mon Feb 14 14:12:03 CET 2011
Updating branch refs/heads/master
to 6ebca95f7cd2b2de82057994c7b8239f7cc3b5fb (commit)
from 26d6c13238f21f0967aa0ad4506e433934558c2e (commit)
commit 6ebca95f7cd2b2de82057994c7b8239f7cc3b5fb
Merge: 26d6c13 3415bea
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 14 14:09:15 2011 +0100
Merge branch 'jannis/thumbnailer-improvements'
commit 3415bea8e7624012c4104791f0caf839b689636d
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Sun Feb 13 14:36:08 2011 +0100
Call thunar_thumbnail_cache_cleanup_file() when trashing a file/folder.
When trashing a directory we cannot call the Delete() method of the
thumbnailer service as that would not delete thumbnails of its
descendants. Using the base URI parameter of Cleanup() we can achieve
this however.
commit 9beaffa4809e88a52bd84bb0d51180bfd47ed2a0
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Sun Feb 13 14:32:58 2011 +0100
Add thunar_thumbnail_cache_cleanup_file(). Sync with thumbnailer spec.
Also increase the timeouts for Copy() and Delete() D-Bus method calls to
500ms to reduce the D-Bus traffic.
commit 5a20e93a0d2734e8cb200d29dcb0ca31560805d0
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Tue Feb 8 11:40:07 2011 +0100
Fix build without D-Bus.
commit 216f3e9921557ddf2c763ac12d95ec085836cf14
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 7 22:24:55 2011 +0100
Make the thumbnailing in ThunarStandardView a bit more responsive.
Use a timeout of 175ms instead of 250ms.
commit d52a31fda15823809f23c42724ae43c39ecd20df
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 7 22:22:40 2011 +0100
Improve the thumbnail cache support in transfer jobs a tiny bit.
commit 9317f1b660ac0e3753c5a6cc6341a1b59d609381
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 7 22:17:35 2011 +0100
Add thumbnail cache update support to the link job.
This does wonders when linking stuff from slow remote locations into
your local system.
commit ee3d81ed900dfd3e23b374504f34cc264abb3d2f
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 7 21:54:58 2011 +0100
Use Move(), Copy() and Delete() cache methods in transfer jobs.
This probably has to be improved (at least Copy() sometimes causes weird
icon view behavior when copying a lot of files to an open window).
Move transfer jobs work fine.
commit 4f6e985763adc4c6dfed5153aaa5ec973f498f82
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 7 21:51:17 2011 +0100
Call thunar_thumbnail_cache_delete_file() in the unlink job.
This helps removing thumbnails from the on-disk cache that are no longer
needed because the original file no longer exists. It does a pretty good
job at that but there's more work to do to integrate Copy(), Move() and
Delete() in all the jobs.
commit bdfbba792be55b094647fe06c739c5ac151b134f
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 7 21:49:22 2011 +0100
Add thunar_thumbnail_cache_copy_file().
This one also uses a queue and a timeout of 250ms to group Copy() D-Bus
method calls.
commit 133d32f0fcc2c37f5c581d647ae5fd02014244f3
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 7 21:21:58 2011 +0100
Add thunar_thumbnail_cache_delete_file(). Use queues for processing.
We again use something like the wait queue in the old ThunarThumbnailer
here for grouping Move() and Delete() calls. The same will be done for
Copy(). It performs really well, moving 200 images from one folder to
another only generates a single Move() request with all images. At least
on my fast machine.
The actual calls to thunar_thumbnail_cache_move_file() and
thunar_thumbnail_cache_delete_file() in the transfer and I/O jobs still
have to be added.
commit 57cee92472be55feb9cb3549725190dfc035c314
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 7 16:50:15 2011 +0100
Make sure to reset the thumbnail timeout/idle handler ID.
commit d2dd3f68af0afaf4035a3ffbc7340d257703a003
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 7 16:34:47 2011 +0100
Add a ThunarThumbnailCache to ThunarApplication, implement Move().
With this tumblerd can just copy the thumbnail and adjust its meta data
when a file is renamed. We thereby avoid regenerating thumbnails for
files that are simply renamed but whose contents don't change at all.
We probably need some extra code to check whether the file type has now
changed or become incompatible with tumbler. In that case we will have
to drop the thumbnail. But how often does this really happen?
commit 834e6455488ccfb505127ba175e5366e1c652691
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 7 15:12:29 2011 +0100
Use a timeout/idle to request thumbnails in ThunarStandardView.
This is the second part of redesigning how thumbnails are requested in
Thunar. Each ThunarStandardView now has a ThunerThumbnailer object.
On scroll and resize events and whenever a new directory has finished
loading, ThunarStandardView now schedules a timeout or idle handler
(depending on the situation) to request thumbnails for all visible items
of the view.
This timeout/idle handler is rescheduled whenever the user starts
or continues scrolling or resizing. This avoids sending requests while
the user is scrolling and its important to not have D-Bus interfere with
the Thunar main loop. We now have a much more responsive thumbnailing
and scrolling experience!
Requests are also dropped by each view when a directory is closed/left.
This means that we no longer generate thumbnails the user is not
interested in any more.
This commit also uses the proper D-Bus method for cancelling thumbnail
requests (it's called "Dequeue", not "Unqueue").
The properties dialog is updated to match changes in the
ThunarThumbnailer API.
commit f19df728cf8798152b175dd61467ea1633663660
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Mon Feb 7 02:41:23 2011 +0100
Refactor ThunarThumbnailer and implement unqueue.
This commit also drops ThunarThumbnailer in ThunarIconFactory and adds
it to ThunarPropertiesDialog. There will be one ThunarThumbnailer for
each ThunarStandardView soon in order to bring back normal thumbnail
generation.
thunar/Makefile.am | 12 +
thunar/thunar-application.c | 43 ++-
thunar/thunar-application.h | 238 ++++++------
thunar/thunar-file.c | 19 +-
thunar/thunar-icon-factory.c | 55 +--
thunar/thunar-io-jobs.c | 85 +++-
thunar/thunar-properties-dialog.c | 59 +++-
thunar/thunar-standard-view.c | 261 ++++++++++++-
thunar/thunar-thumbnail-cache-dbus.xml | 27 ++
thunar/thunar-thumbnail-cache.c | 692 ++++++++++++++++++++++++++++++++
thunar/thunar-thumbnail-cache.h | 56 +++
thunar/thunar-thumbnailer-dbus.xml | 2 +-
thunar/thunar-thumbnailer.c | 606 ++++++----------------------
thunar/thunar-thumbnailer.h | 47 ++-
thunar/thunar-transfer-job.c | 131 ++++--
15 files changed, 1559 insertions(+), 774 deletions(-)
diff --git a/thunar/Makefile.am b/thunar/Makefile.am
index 0b45ce9..b715fea 100644
--- a/thunar/Makefile.am
+++ b/thunar/Makefile.am
@@ -201,6 +201,8 @@ Thunar_SOURCES = \
thunar-throbber.h \
thunar-throbber-fallback.c \
thunar-throbber-fallback.h \
+ thunar-thumbnail-cache.c \
+ thunar-thumbnail-cache.h \
thunar-thumbnailer.c \
thunar-thumbnailer.h \
thunar-thumbnail-frame.c \
@@ -260,6 +262,7 @@ Thunar_DEPENDENCIES = \
if HAVE_DBUS
thunar_built_sources += \
thunar-dbus-service-infos.h \
+ thunar-thumbnail-cache-proxy.h \
thunar-thumbnailer-proxy.h
thunar_dbus_sources = \
@@ -267,6 +270,7 @@ thunar_dbus_sources = \
thunar-dbus-client.h \
thunar-dbus-service.c \
thunar-dbus-service.h \
+ thunar-thumbnail-cache-proxy.h \
thunar-thumbnailer-proxy.h
Thunar_CFLAGS += \
@@ -344,6 +348,14 @@ thunar-thumbnailer-proxy.h: $(srcdir)/thunar-thumbnailer-dbus.xml Makefile
&& sed -i -e 's/org_freedesktop_thumbnails_Thumbnailer1/thunar_thumbnailer_proxy/g' \
thunar-thumbnailer-proxy.h \
)
+
+thunar-thumbnail-cache-proxy.h: $(srcdir)/thunar-thumbnail-cache-dbus.xml Makefile
+ $(AM_V_GEN) ( \
+ dbus-binding-tool --mode=glib-client \
+ $(srcdir)/thunar-thumbnail-cache-dbus.xml > thunar-thumbnail-cache-proxy.h \
+ && sed -i -e 's/org_freedesktop_thumbnails_Cache1/thunar_thumbnail_cache_proxy/g' \
+ thunar-thumbnail-cache-proxy.h \
+ )
endif
thunar-throbber-fallback.c: $(srcdir)/thunar-throbber-fallback.png Makefile
diff --git a/thunar/thunar-application.c b/thunar/thunar-application.c
index 4490105..8a5744a 100644
--- a/thunar/thunar-application.c
+++ b/thunar/thunar-application.c
@@ -1,22 +1,23 @@
-/* $Id$ */
+/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
* Copyright (c) 2005 Jeff Franks <jcfranks at xfce.org>
- * Copyright (c) 2009-2010 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-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 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 General Public License for
- * more details.
+ * 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 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
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
@@ -53,6 +54,7 @@
#include <thunar/thunar-private.h>
#include <thunar/thunar-progress-dialog.h>
#include <thunar/thunar-renamer-dialog.h>
+#include <thunar/thunar-thumbnail-cache.h>
#include <thunar/thunar-util.h>
@@ -130,6 +132,8 @@ struct _ThunarApplication
GtkWidget *progress_dialog;
GList *windows;
+ ThunarThumbnailCache *thumbnail_cache;
+
gboolean daemon;
guint show_dialogs_timer_id;
@@ -205,6 +209,7 @@ thunar_application_init (ThunarApplication *application)
/* initialize the application */
application->preferences = thunar_preferences_get ();
+ application->thumbnail_cache = thunar_thumbnail_cache_new ();
application->files_to_launch = NULL;
application->progress_dialog = NULL;
@@ -279,6 +284,9 @@ thunar_application_finalize (GObject *object)
}
g_list_free (application->windows);
+ /* release the thumbnail cache */
+ g_object_unref (G_OBJECT (application->thumbnail_cache));
+
/* disconnect from the preferences */
g_object_unref (G_OBJECT (application->preferences));
@@ -1985,3 +1993,12 @@ thunar_application_restore_files (ThunarApplication *application,
}
+
+ThunarThumbnailCache *
+thunar_application_get_thumbnail_cache (ThunarApplication *application)
+{
+ _thunar_return_val_if_fail (THUNAR_IS_APPLICATION (application), NULL);
+ return g_object_ref (application->thumbnail_cache);
+}
+
+
diff --git a/thunar/thunar-application.h b/thunar/thunar-application.h
index cb42877..50845a3 100644
--- a/thunar/thunar-application.h
+++ b/thunar/thunar-application.h
@@ -1,28 +1,30 @@
-/* $Id$ */
+/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2005-2006 Benedikt Meurer <benny at xfce.org>
* Copyright (c) 2005 Jeff Franks <jcfranks at xfce.org>
- * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-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 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 General Public License for
- * more details.
+ * 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 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
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __THUNAR_APPLICATION_H__
#define __THUNAR_APPLICATION_H__
#include <thunar/thunar-window.h>
+#include <thunar/thunar-thumbnail-cache.h>
G_BEGIN_DECLS;
@@ -36,110 +38,112 @@ typedef struct _ThunarApplication ThunarApplication;
#define THUNAR_IS_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_APPLICATION))
#define THUNAR_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_APPLICATION, ThunarApplicationClass))
-GType thunar_application_get_type (void) G_GNUC_CONST;
-
-ThunarApplication *thunar_application_get (void);
-
-gboolean thunar_application_get_daemon (ThunarApplication *application);
-void thunar_application_set_daemon (ThunarApplication *application,
- gboolean daemon);
-
-GList *thunar_application_get_windows (ThunarApplication *application);
-
-gboolean thunar_application_has_windows (ThunarApplication *application);
-
-void thunar_application_take_window (ThunarApplication *application,
- GtkWindow *window);
-
-GtkWidget *thunar_application_open_window (ThunarApplication *application,
- ThunarFile *directory,
- GdkScreen *screen,
- const gchar *startup_id);
-
-gboolean thunar_application_bulk_rename (ThunarApplication *application,
- const gchar *working_directory,
- gchar **filenames,
- gboolean standalone,
- GdkScreen *screen,
- const gchar *startup_id,
- GError **error);
-
-GtkWidget *thunar_application_get_progress_dialog (ThunarApplication *application);
-
-gboolean thunar_application_process_filenames (ThunarApplication *application,
- const gchar *working_directory,
- gchar **filenames,
- GdkScreen *screen,
- const gchar *startup_id,
- GError **error);
-
-gboolean thunar_application_is_processing (ThunarApplication *application);
-
-void thunar_application_rename_file (ThunarApplication *application,
- ThunarFile *file,
- GdkScreen *screen,
- const gchar *startup_id);
-void thunar_application_create_file (ThunarApplication *application,
- ThunarFile *parent_directory,
- const gchar *content_type,
- GdkScreen *screen,
- const gchar *startup_id);
-void thunar_application_create_file_from_template (ThunarApplication *application,
- ThunarFile *parent_directory,
- ThunarFile *template_file,
- GdkScreen *screen,
- const gchar *startup_id);
-void thunar_application_copy_to (ThunarApplication *application,
- gpointer parent,
- GList *source_file_list,
- GList *target_file_list,
- GClosure *new_files_closure);
-
-void thunar_application_copy_into (ThunarApplication *application,
- gpointer parent,
- GList *source_file_list,
- GFile *target_file,
- GClosure *new_files_closure);
-
-void thunar_application_link_into (ThunarApplication *application,
- gpointer parent,
- GList *source_file_list,
- GFile *target_file,
- GClosure *new_files_closure);
-
-void thunar_application_move_into (ThunarApplication *application,
- gpointer parent,
- GList *source_file_list,
- GFile *target_file,
- GClosure *new_files_closure);
-
-void thunar_application_unlink_files (ThunarApplication *application,
- gpointer parent,
- GList *file_list,
- gboolean permanently);
-
-void thunar_application_trash (ThunarApplication *application,
- gpointer parent,
- GList *file_list);
-
-void thunar_application_creat (ThunarApplication *application,
- gpointer parent,
- GList *file_list,
- GClosure *new_files_closure);
-
-void thunar_application_mkdir (ThunarApplication *application,
- gpointer parent,
- GList *file_list,
- GClosure *new_files_closure);
-
-void thunar_application_empty_trash (ThunarApplication *application,
- gpointer parent,
- const gchar *startup_id);
-
-void thunar_application_restore_files (ThunarApplication *application,
- gpointer parent,
- GList *trash_file_list,
- GClosure *new_files_closure);
+GType thunar_application_get_type (void) G_GNUC_CONST;
+
+ThunarApplication *thunar_application_get (void);
+
+gboolean thunar_application_get_daemon (ThunarApplication *application);
+void thunar_application_set_daemon (ThunarApplication *application,
+ gboolean daemon);
+
+GList *thunar_application_get_windows (ThunarApplication *application);
+
+gboolean thunar_application_has_windows (ThunarApplication *application);
+
+void thunar_application_take_window (ThunarApplication *application,
+ GtkWindow *window);
+
+GtkWidget *thunar_application_open_window (ThunarApplication *application,
+ ThunarFile *directory,
+ GdkScreen *screen,
+ const gchar *startup_id);
+
+gboolean thunar_application_bulk_rename (ThunarApplication *application,
+ const gchar *working_directory,
+ gchar **filenames,
+ gboolean standalone,
+ GdkScreen *screen,
+ const gchar *startup_id,
+ GError **error);
+
+GtkWidget *thunar_application_get_progress_dialog (ThunarApplication *application);
+
+gboolean thunar_application_process_filenames (ThunarApplication *application,
+ const gchar *working_directory,
+ gchar **filenames,
+ GdkScreen *screen,
+ const gchar *startup_id,
+ GError **error);
+
+gboolean thunar_application_is_processing (ThunarApplication *application);
+
+void thunar_application_rename_file (ThunarApplication *application,
+ ThunarFile *file,
+ GdkScreen *screen,
+ const gchar *startup_id);
+void thunar_application_create_file (ThunarApplication *application,
+ ThunarFile *parent_directory,
+ const gchar *content_type,
+ GdkScreen *screen,
+ const gchar *startup_id);
+void thunar_application_create_file_from_template (ThunarApplication *application,
+ ThunarFile *parent_directory,
+ ThunarFile *template_file,
+ GdkScreen *screen,
+ const gchar *startup_id);
+void thunar_application_copy_to (ThunarApplication *application,
+ gpointer parent,
+ GList *source_file_list,
+ GList *target_file_list,
+ GClosure *new_files_closure);
+
+void thunar_application_copy_into (ThunarApplication *application,
+ gpointer parent,
+ GList *source_file_list,
+ GFile *target_file,
+ GClosure *new_files_closure);
+
+void thunar_application_link_into (ThunarApplication *application,
+ gpointer parent,
+ GList *source_file_list,
+ GFile *target_file,
+ GClosure *new_files_closure);
+
+void thunar_application_move_into (ThunarApplication *application,
+ gpointer parent,
+ GList *source_file_list,
+ GFile *target_file,
+ GClosure *new_files_closure);
+
+void thunar_application_unlink_files (ThunarApplication *application,
+ gpointer parent,
+ GList *file_list,
+ gboolean permanently);
+
+void thunar_application_trash (ThunarApplication *application,
+ gpointer parent,
+ GList *file_list);
+
+void thunar_application_creat (ThunarApplication *application,
+ gpointer parent,
+ GList *file_list,
+ GClosure *new_files_closure);
+
+void thunar_application_mkdir (ThunarApplication *application,
+ gpointer parent,
+ GList *file_list,
+ GClosure *new_files_closure);
+
+void thunar_application_empty_trash (ThunarApplication *application,
+ gpointer parent,
+ const gchar *startup_id);
+
+void thunar_application_restore_files (ThunarApplication *application,
+ gpointer parent,
+ GList *trash_file_list,
+ GClosure *new_files_closure);
+
+ThunarThumbnailCache *thunar_application_get_thumbnail_cache (ThunarApplication *application);
G_END_DECLS;
diff --git a/thunar/thunar-file.c b/thunar/thunar-file.c
index 1281841..ebb1032 100644
--- a/thunar/thunar-file.c
+++ b/thunar/thunar-file.c
@@ -1254,11 +1254,13 @@ thunar_file_rename (ThunarFile *file,
gboolean called_from_job,
GError **error)
{
- GKeyFile *key_file;
- GError *err = NULL;
- GFile *previous_file;
- GFile *renamed_file;
- gint watch_count;
+ ThunarApplication *application;
+ ThunarThumbnailCache *thumbnail_cache;
+ GKeyFile *key_file;
+ GError *err = NULL;
+ GFile *previous_file;
+ GFile *renamed_file;
+ gint watch_count;
_thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
_thunar_return_val_if_fail (g_utf8_validate (name, -1, NULL), FALSE);
@@ -1317,6 +1319,13 @@ thunar_file_rename (ThunarFile *file,
/* try to rename the file */
renamed_file = g_file_set_display_name (file->gfile, name, cancellable, error);
+ /* notify the thumbnail cache that we can now also move the thumbnail */
+ application = thunar_application_get ();
+ thumbnail_cache = thunar_application_get_thumbnail_cache (application);
+ thunar_thumbnail_cache_move_file (thumbnail_cache, previous_file, renamed_file);
+ g_object_unref (thumbnail_cache);
+ g_object_unref (application);
+
/* check if we succeeded */
if (renamed_file != NULL)
{
diff --git a/thunar/thunar-icon-factory.c b/thunar/thunar-icon-factory.c
index 576329a..4f2ec42 100644
--- a/thunar/thunar-icon-factory.c
+++ b/thunar/thunar-icon-factory.c
@@ -1,25 +1,22 @@
-/* $Id$ */
+/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2005-2006 Benedikt Meurer <benny at xfce.org>
- * Copyright (c) 2009-2010 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-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 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 General Public License for
- * more details.
+ * 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 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
- *
- * The basic idea for the icon factory implementation was borrowed from
- * Nautilus initially, but the implementation is very different from
- * what Nautilus does.
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
@@ -38,7 +35,6 @@
#include <thunar/thunar-preferences.h>
#include <thunar/thunar-private.h>
#include <thunar/thunar-thumbnail-frame.h>
-#include <thunar/thunar-thumbnailer.h>
@@ -106,8 +102,6 @@ struct _ThunarIconFactory
{
GObject __parent__;
- ThunarThumbnailer *thumbnailer;
-
ThunarPreferences *preferences;
GdkPixbuf *recently[MAX_RECENTLY]; /* ring buffer */
@@ -209,9 +203,6 @@ thunar_icon_factory_init (ThunarIconFactory *factory)
/* allocate the hash table for the icon cache */
factory->icon_cache = g_hash_table_new_full (thunar_icon_key_hash, thunar_icon_key_equal, g_free, g_object_unref);
-
- /* create a new thumbnailer */
- factory->thumbnailer = thunar_thumbnailer_new ();
}
@@ -250,9 +241,6 @@ thunar_icon_factory_finalize (GObject *object)
/* clear the icon cache hash table */
g_hash_table_destroy (factory->icon_cache);
- /* release the thumbnailer */
- g_object_unref (G_OBJECT (factory->thumbnailer));
-
/* remove the "changed" emission hook from the GtkIconTheme class */
g_signal_remove_emission_hook (g_signal_lookup ("changed", GTK_TYPE_ICON_THEME), factory->changed_hook_id);
@@ -804,7 +792,6 @@ thunar_icon_factory_load_file_icon (ThunarIconFactory *factory,
ThunarFileIconState icon_state,
gint icon_size)
{
- ThunarFileThumbState thumb_state;
GInputStream *stream;
GtkIconInfo *icon_info;
const gchar *thumbnail_path;
@@ -830,20 +817,6 @@ thunar_icon_factory_load_file_icon (ThunarIconFactory *factory,
/* check if thumbnails are enabled and we can display a thumbnail for the item */
if (G_LIKELY (factory->show_thumbnails && thunar_file_is_regular (file)))
{
- /* this is how thumbnails for files are loaded: first, we check the thumbnail
- * state. If that is unknown, we request a thumbnail to be generated in the
- * background. At the same time we already try to load the thumbnail, in case
- * it's already there. when the thumbnail is ready, we just load it */
-
- /* determine the thumbnail state of the file */
- thumb_state = thunar_file_get_thumb_state (file);
-
- if (thumb_state == THUNAR_FILE_THUMB_STATE_UNKNOWN)
- {
- /* we don't know the state yet so request a new thumbnail in the background */
- thunar_thumbnailer_queue_file (factory->thumbnailer, file);
- }
-
/* determine the preview icon first */
gicon = thunar_file_get_preview_icon (file);
diff --git a/thunar/thunar-io-jobs.c b/thunar/thunar-io-jobs.c
index 898118a..859bdef 100644
--- a/thunar/thunar-io-jobs.c
+++ b/thunar/thunar-io-jobs.c
@@ -24,6 +24,7 @@
#include <gio/gio.h>
+#include <thunar/thunar-application.h>
#include <thunar/thunar-enum-types.h>
#include <thunar/thunar-gio-extensions.h>
#include <thunar/thunar-io-scan-directory.h>
@@ -32,6 +33,7 @@
#include <thunar/thunar-job.h>
#include <thunar/thunar-private.h>
#include <thunar/thunar-simple-job.h>
+#include <thunar/thunar-thumbnail-cache.h>
#include <thunar/thunar-transfer-job.h>
@@ -367,13 +369,15 @@ _thunar_io_jobs_unlink (ThunarJob *job,
GValueArray *param_values,
GError **error)
{
- ThunarJobResponse response;
- GFileInfo *info;
- GError *err = NULL;
- GList *file_list;
- GList *lp;
- gchar *base_name;
- gchar *display_name;
+ ThunarThumbnailCache *thumbnail_cache;
+ ThunarApplication *application;
+ ThunarJobResponse response;
+ GFileInfo *info;
+ GError *err = NULL;
+ GList *file_list;
+ GList *lp;
+ gchar *base_name;
+ gchar *display_name;
_thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
_thunar_return_val_if_fail (param_values != NULL, FALSE);
@@ -404,6 +408,11 @@ _thunar_io_jobs_unlink (ThunarJob *job,
/* we know the total list of files to process */
thunar_job_set_total_files (THUNAR_JOB (job), file_list);
+ /* take a reference on the thumbnail cache */
+ application = thunar_application_get ();
+ thumbnail_cache = thunar_application_get_thumbnail_cache (application);
+ g_object_unref (application);
+
/* remove all the files */
for (lp = file_list; lp != NULL && !exo_job_is_cancelled (EXO_JOB (job)); lp = lp->next)
{
@@ -415,7 +424,13 @@ _thunar_io_jobs_unlink (ThunarJob *job,
again:
/* try to delete the file */
- if (!g_file_delete (lp->data, exo_job_get_cancellable (EXO_JOB (job)), &err))
+ if (g_file_delete (lp->data, exo_job_get_cancellable (EXO_JOB (job)), &err))
+ {
+ /* notify the thumbnail cache that the corresponding thumbnail can also
+ * be deleted now */
+ thunar_thumbnail_cache_delete_file (thumbnail_cache, lp->data);
+ }
+ else
{
/* query the file info for the display name */
info = g_file_query_info (lp->data,
@@ -459,6 +474,9 @@ again:
}
}
+ /* release the thumbnail cache */
+ g_object_unref (thumbnail_cache);
+
/* release the file list */
thunar_g_file_list_free (file_list);
@@ -646,13 +664,15 @@ _thunar_io_jobs_link (ThunarJob *job,
GValueArray *param_values,
GError **error)
{
- GError *err = NULL;
- GFile *real_target_file;
- GList *new_files_list = NULL;
- GList *source_file_list;
- GList *sp;
- GList *target_file_list;
- GList *tp;
+ ThunarThumbnailCache *thumbnail_cache;
+ ThunarApplication *application;
+ GError *err = NULL;
+ GFile *real_target_file;
+ GList *new_files_list = NULL;
+ GList *source_file_list;
+ GList *sp;
+ GList *target_file_list;
+ GList *tp;
_thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
_thunar_return_val_if_fail (param_values != NULL, FALSE);
@@ -665,6 +685,11 @@ _thunar_io_jobs_link (ThunarJob *job,
/* we know the total list of paths to process */
thunar_job_set_total_files (THUNAR_JOB (job), source_file_list);
+ /* take a reference on the thumbnail cache */
+ application = thunar_application_get ();
+ thumbnail_cache = thunar_application_get_thumbnail_cache (application);
+ g_object_unref (application);
+
/* process all files */
for (sp = source_file_list, tp = target_file_list;
err == NULL && sp != NULL && tp != NULL;
@@ -685,6 +710,12 @@ _thunar_io_jobs_link (ThunarJob *job,
{
new_files_list = thunar_g_file_list_prepend (new_files_list,
real_target_file);
+
+ /* notify the thumbnail cache that we need to copy the original
+ * thumbnail for the symlink to have one too */
+ thunar_thumbnail_cache_copy_file (thumbnail_cache, sp->data,
+ real_target_file);
+
}
/* release the real target file */
@@ -692,6 +723,9 @@ _thunar_io_jobs_link (ThunarJob *job,
}
}
+ /* release the thumbnail cache */
+ g_object_unref (thumbnail_cache);
+
if (err != NULL)
{
thunar_g_file_list_free (new_files_list);
@@ -728,9 +762,11 @@ _thunar_io_jobs_trash (ThunarJob *job,
GValueArray *param_values,
GError **error)
{
- GError *err = NULL;
- GList *file_list;
- GList *lp;
+ ThunarThumbnailCache *thumbnail_cache;
+ ThunarApplication *application;
+ GError *err = NULL;
+ GList *file_list;
+ GList *lp;
_thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
_thunar_return_val_if_fail (param_values != NULL, FALSE);
@@ -742,12 +778,25 @@ _thunar_io_jobs_trash (ThunarJob *job,
if (exo_job_set_error_if_cancelled (EXO_JOB (job), error))
return FALSE;
+ /* take a reference on the thumbnail cache */
+ application = thunar_application_get ();
+ thumbnail_cache = thunar_application_get_thumbnail_cache (application);
+ g_object_unref (application);
+
for (lp = file_list; err == NULL && lp != NULL; lp = lp->next)
{
_thunar_assert (G_IS_FILE (lp->data));
+
+ /* trash the file or folder */
g_file_trash (lp->data, exo_job_get_cancellable (EXO_JOB (job)), &err);
+
+ /* update the thumbnail cache */
+ thunar_thumbnail_cache_cleanup_file (thumbnail_cache, lp->data);
}
+ /* release the thumbnail cache */
+ g_object_unref (thumbnail_cache);
+
if (err != NULL)
{
g_propagate_error (error, err);
diff --git a/thunar/thunar-properties-dialog.c b/thunar/thunar-properties-dialog.c
index 9e5a39d..f52c20b 100644
--- a/thunar/thunar-properties-dialog.c
+++ b/thunar/thunar-properties-dialog.c
@@ -1,21 +1,22 @@
-/* $Id$ */
+/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
- * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-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 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 General Public License for
- * more details.
+ * 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 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
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
@@ -52,6 +53,7 @@
#include <thunar/thunar-private.h>
#include <thunar/thunar-properties-dialog.h>
#include <thunar/thunar-size-label.h>
+#include <thunar/thunar-thumbnailer.h>
@@ -115,6 +117,9 @@ struct _ThunarPropertiesDialog
ThunarFile *file;
+ ThunarThumbnailer *thumbnailer;
+ guint thumbnail_request;
+
GtkWidget *notebook;
GtkWidget *icon_button;
GtkWidget *icon_image;
@@ -209,6 +214,10 @@ thunar_properties_dialog_init (ThunarPropertiesDialog *dialog)
g_signal_connect_swapped (G_OBJECT (dialog->preferences), "notify::misc-date-style",
G_CALLBACK (thunar_properties_dialog_reload), dialog);
+ /* create a new thumbnailer */
+ dialog->thumbnailer = thunar_thumbnailer_new ();
+ dialog->thumbnail_request = 0;
+
dialog->provider_factory = thunarx_provider_factory_get_default ();
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
@@ -514,6 +523,16 @@ thunar_properties_dialog_finalize (GObject *object)
g_signal_handlers_disconnect_by_func (dialog->preferences, thunar_properties_dialog_reload, dialog);
g_object_unref (dialog->preferences);
+ /* cancel any pending thumbnailer requests */
+ if (dialog->thumbnail_request > 0)
+ {
+ thunar_thumbnailer_dequeue (dialog->thumbnailer, dialog->thumbnail_request);
+ dialog->thumbnail_request = 0;
+ }
+
+ /* release the thumbnailer */
+ g_object_unref (dialog->thumbnailer);
+
/* release the provider property pages */
g_list_foreach (dialog->provider_pages, (GFunc) g_object_unref, NULL);
g_list_free (dialog->provider_pages);
@@ -813,6 +832,20 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
_thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog));
_thunar_return_if_fail (THUNAR_IS_FILE (dialog->file));
+ /* cancel any pending thumbnail requests */
+ if (dialog->thumbnail_request > 0)
+ {
+ thunar_thumbnailer_dequeue (dialog->thumbnailer, dialog->thumbnail_request);
+ dialog->thumbnail_request = 0;
+ }
+
+ if (dialog->file != NULL)
+ {
+ /* queue a new thumbnail request */
+ thunar_thumbnailer_queue_file (dialog->thumbnailer, dialog->file,
+ &dialog->thumbnail_request);
+ }
+
icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (dialog)));
icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme);
diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c
index f671f05..2478d7e 100644
--- a/thunar/thunar-standard-view.c
+++ b/thunar/thunar-standard-view.c
@@ -1,21 +1,22 @@
-/* $Id$ */
+/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2005-2006 Benedikt Meurer <benny at xfce.org>
- * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-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 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 General Public License for
- * more details.
+ * 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 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
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
@@ -49,6 +50,7 @@
#include <thunar/thunar-standard-view-ui.h>
#include <thunar/thunar-templates-action.h>
#include <thunar/thunar-text-renderer.h>
+#include <thunar/thunar-thumbnailer.h>
#if defined(GDK_WINDOWING_X11)
#include <gdk/gdkx.h>
@@ -260,6 +262,14 @@ static gboolean thunar_standard_view_drag_scroll_timer (gpo
static void thunar_standard_view_drag_scroll_timer_destroy (gpointer user_data);
static gboolean thunar_standard_view_drag_timer (gpointer user_data);
static void thunar_standard_view_drag_timer_destroy (gpointer user_data);
+static void thunar_standard_view_cancel_thumbnailing (ThunarStandardView *standard_view);
+static void thunar_standard_view_schedule_thumbnail_timeout (ThunarStandardView *standard_view);
+static void thunar_standard_view_schedule_thumbnail_idle (ThunarStandardView *standard_view);
+static gboolean thunar_standard_view_request_thumbnails (ThunarStandardView *standard_view);
+static void thunar_standard_view_scrolled (GtkAdjustment *adjustment,
+ ThunarStandardView *standard_view);
+static void thunar_standard_view_size_allocate (ThunarStandardView *standard_view,
+ GtkAllocation *allocation);
@@ -326,6 +336,12 @@ struct _ThunarStandardViewPrivate
/* selected_files support */
GList *selected_files;
+ /* support for generating thumbnails */
+ ThunarThumbnailer *thumbnailer;
+ guint thumbnail_request;
+ guint thumbnail_source_id;
+ gboolean thumbnailing_scheduled;
+
/* Tree path for restoring the selection after selecting and
* deleting an item */
GtkTreePath *selection_before_delete;
@@ -531,6 +547,10 @@ thunar_standard_view_init (ThunarStandardView *standard_view)
/* grab a reference on the provider factory */
standard_view->priv->provider_factory = thunarx_provider_factory_get_default ();
+ /* create a thumbnailer */
+ standard_view->priv->thumbnailer = thunar_thumbnailer_new ();
+ standard_view->priv->thumbnailing_scheduled = FALSE;
+
/* initialize the scrolled window */
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (standard_view),
GTK_POLICY_AUTOMATIC,
@@ -596,6 +616,10 @@ thunar_standard_view_init (ThunarStandardView *standard_view)
* files in our model changes.
*/
g_signal_connect_swapped (G_OBJECT (standard_view->model), "notify::num-files", G_CALLBACK (thunar_standard_view_update_statusbar_text), standard_view);
+
+ /* connect to size allocation signals for generating thumbnail requests */
+ g_signal_connect_after (G_OBJECT (standard_view), "size-allocate",
+ G_CALLBACK (thunar_standard_view_size_allocate), NULL);
}
@@ -607,6 +631,7 @@ thunar_standard_view_constructor (GType type,
{
ThunarStandardView *standard_view;
ThunarZoomLevel zoom_level;
+ GtkAdjustment *adjustment;
ThunarColumn sort_column;
GtkSortType sort_order;
GtkWidget *view;
@@ -667,6 +692,14 @@ thunar_standard_view_constructor (GType type,
g_signal_connect (G_OBJECT (view), "drag-data-delete", G_CALLBACK (thunar_standard_view_drag_data_delete), object);
g_signal_connect (G_OBJECT (view), "drag-end", G_CALLBACK (thunar_standard_view_drag_end), object);
+ /* connect to scroll events for generating thumbnail requests */
+ adjustment = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (standard_view));
+ g_signal_connect (adjustment, "value-changed",
+ G_CALLBACK (thunar_standard_view_scrolled), object);
+ adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (standard_view));
+ g_signal_connect (adjustment, "value-changed",
+ G_CALLBACK (thunar_standard_view_scrolled), object);
+
/* done, we have a working object */
return object;
}
@@ -678,6 +711,9 @@ thunar_standard_view_dispose (GObject *object)
{
ThunarStandardView *standard_view = THUNAR_STANDARD_VIEW (object);
+ /* cancel pending thumbnail sources and requests */
+ thunar_standard_view_cancel_thumbnailing (standard_view);
+
/* unregister the "loading" binding */
if (G_UNLIKELY (standard_view->loading_binding != NULL))
exo_binding_unbind (standard_view->loading_binding);
@@ -709,6 +745,9 @@ thunar_standard_view_finalize (GObject *object)
_thunar_assert (standard_view->ui_manager == NULL);
_thunar_assert (standard_view->clipboard == NULL);
+ /* release the thumbnailer */
+ g_object_unref (standard_view->priv->thumbnailer);
+
/* release the scroll_to_file reference (if any) */
if (G_UNLIKELY (standard_view->priv->scroll_to_file != NULL))
g_object_unref (G_OBJECT (standard_view->priv->scroll_to_file));
@@ -1128,6 +1167,9 @@ thunar_standard_view_set_current_directory (ThunarNavigator *navigator,
_thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
_thunar_return_if_fail (current_directory == NULL || THUNAR_IS_FILE (current_directory));
+ /* cancel any pending thumbnail sources and requests */
+ thunar_standard_view_cancel_thumbnailing (standard_view);
+
/* disconnect any previous "loading" binding */
if (G_LIKELY (standard_view->loading_binding != NULL))
exo_binding_unbind (standard_view->loading_binding);
@@ -1189,6 +1231,9 @@ thunar_standard_view_set_current_directory (ThunarNavigator *navigator,
/* update the "Restore" action */
gtk_action_set_visible (standard_view->priv->action_restore, trashed);
+ /* schedule a thumbnail timeout */
+ thunar_standard_view_schedule_thumbnail_timeout (standard_view);
+
/* notify all listeners about the new/old current directory */
g_object_notify (G_OBJECT (standard_view), "current-directory");
}
@@ -1266,6 +1311,17 @@ thunar_standard_view_set_loading (ThunarStandardView *standard_view,
thunar_file_list_free (selected_files);
}
+ /* check if we're done loading and a thumbnail timeout or idle was requested */
+ if (!loading && standard_view->priv->thumbnailing_scheduled)
+ {
+ /* we've just finished loading. it will probably the user some time to
+ * understand the contents of the folder before he will start interacting
+ * with the view. so here we can safely schedule an idle function instead
+ * of a timeout */
+ thunar_standard_view_schedule_thumbnail_idle (standard_view);
+ standard_view->priv->thumbnailing_scheduled = FALSE;
+ }
+
/* notify listeners */
g_object_freeze_notify (G_OBJECT (standard_view));
g_object_notify (G_OBJECT (standard_view), "loading");
@@ -3240,6 +3296,185 @@ thunar_standard_view_drag_timer_destroy (gpointer user_data)
+static void
+thunar_standard_view_cancel_thumbnailing (ThunarStandardView *standard_view)
+{
+ _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+
+ /* check if we have a pending thumbnail timeout/idle handler */
+ if (standard_view->priv->thumbnail_source_id > 0)
+ {
+ /* cancel this handler */
+ g_source_remove (standard_view->priv->thumbnail_source_id);
+ standard_view->priv->thumbnail_source_id = 0;
+ }
+
+ /* check if we have a pending thumbnail request */
+ if (standard_view->priv->thumbnail_request > 0)
+ {
+ /* cancel the request */
+ thunar_thumbnailer_dequeue (standard_view->priv->thumbnailer,
+ standard_view->priv->thumbnail_request);
+ standard_view->priv->thumbnail_request = 0;
+ }
+}
+
+
+
+static void
+thunar_standard_view_schedule_thumbnail_timeout (ThunarStandardView *standard_view)
+{
+ _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+
+ /* delay creating the idle until the view has finished loading.
+ * this is done because we only can tell the visible range reliably after
+ * all items have been added and we've perhaps scrolled to the file remember
+ * the last time */
+ if (thunar_view_get_loading (THUNAR_VIEW (standard_view)))
+ {
+ standard_view->priv->thumbnailing_scheduled = TRUE;
+ return;
+ }
+
+ /* cancel any pending thumbnail sources and requests */
+ thunar_standard_view_cancel_thumbnailing (standard_view);
+
+ /* schedule the timeout handler */
+ standard_view->priv->thumbnail_source_id =
+ g_timeout_add (175, (GSourceFunc) thunar_standard_view_request_thumbnails,
+ standard_view);
+}
+
+
+
+static void
+thunar_standard_view_schedule_thumbnail_idle (ThunarStandardView *standard_view)
+{
+ _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+
+ /* delay creating the idle until the view has finished loading.
+ * this is done because we only can tell the visible range reliably after
+ * all items have been added, layouting has finished and we've perhaps
+ * scrolled to the file remembered the last time */
+ if (thunar_view_get_loading (THUNAR_VIEW (standard_view)))
+ {
+ standard_view->priv->thumbnailing_scheduled = TRUE;
+ return;
+ }
+
+ /* cancel any pending thumbnail sources or requests */
+ thunar_standard_view_cancel_thumbnailing (standard_view);
+
+ /* schedule the timeout or idle handler */
+ standard_view->priv->thumbnail_source_id =
+ g_idle_add ((GSourceFunc) thunar_standard_view_request_thumbnails, standard_view);
+}
+
+
+
+static gboolean
+thunar_standard_view_request_thumbnails (ThunarStandardView *standard_view)
+{
+ GtkTreePath *start_path;
+ GtkTreePath *end_path;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ ThunarFile *file;
+ gboolean valid_iter;
+ GList *visible_files = NULL;
+
+ _thunar_return_val_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view), FALSE);
+
+ /* reschedule the source if we're still loading the folder */
+ if (thunar_view_get_loading (THUNAR_VIEW (standard_view)))
+ {
+ g_debug ("weird, this should never happen");
+ return TRUE;
+ }
+
+ /* compute visible item range */
+ if ((*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->get_visible_range) (standard_view,
+ &start_path,
+ &end_path))
+ {
+ /* iterate over the range to collect all files */
+ valid_iter = gtk_tree_model_get_iter (GTK_TREE_MODEL (standard_view->model),
+ &iter, start_path);
+
+ while (valid_iter)
+ {
+ /* prepend the file to the visible items list */
+ file = thunar_list_model_get_file (standard_view->model, &iter);
+ visible_files = g_list_prepend (visible_files, file);
+
+ /* check if we've reached the end of the visible range */
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (standard_view->model), &iter);
+ if (gtk_tree_path_compare (path, end_path) != 0)
+ {
+ /* try to compute the next visible item */
+ valid_iter =
+ gtk_tree_model_iter_next (GTK_TREE_MODEL (standard_view->model), &iter);
+ }
+ else
+ {
+ /* we have reached the end, terminate the loop */
+ valid_iter = FALSE;
+ }
+
+ /* release the tree path */
+ gtk_tree_path_free (path);
+ }
+
+ /* queue a thumbnail request */
+ thunar_thumbnailer_queue_files (standard_view->priv->thumbnailer, visible_files,
+ &standard_view->priv->thumbnail_request);
+
+ /* release the file list */
+ g_list_foreach (visible_files, (GFunc) g_object_unref, NULL);
+ g_list_free (visible_files);
+
+ /* release the start and end path */
+ gtk_tree_path_free (start_path);
+ gtk_tree_path_free (end_path);
+ }
+
+ /* reset the timeout or idle handler ID */
+ standard_view->priv->thumbnail_source_id = 0;
+
+ return FALSE;
+}
+
+
+
+static void
+thunar_standard_view_scrolled (GtkAdjustment *adjustment,
+ ThunarStandardView *standard_view)
+{
+ _thunar_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+ _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+
+ /* ignore adjustment changes when the view is still loading */
+ if (thunar_view_get_loading (THUNAR_VIEW (standard_view)))
+ return;
+
+ /* reschedule a thumbnail request timeout */
+ thunar_standard_view_schedule_thumbnail_timeout (standard_view);
+}
+
+
+
+static void
+thunar_standard_view_size_allocate (ThunarStandardView *standard_view,
+ GtkAllocation *allocation)
+{
+ _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
+
+ /* reschedule a thumbnail request timeout */
+ thunar_standard_view_schedule_thumbnail_timeout (standard_view);
+}
+
+
+
/**
* thunar_standard_view_context_menu:
* @standard_view : a #ThunarStandardView instance.
diff --git a/thunar/thunar-thumbnail-cache-dbus.xml b/thunar/thunar-thumbnail-cache-dbus.xml
new file mode 100644
index 0000000..92ffa42
--- /dev/null
+++ b/thunar/thunar-thumbnail-cache-dbus.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/org/freedesktop/thumbnails/Cache1">
+ <interface name="org.freedesktop.thumbnails.Cache1">
+ <method name="Move">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+ <arg type="as" name="from_uris" direction="in" />
+ <arg type="as" name="to_uris" direction="in" />
+ </method>
+
+ <method name="Copy">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+ <arg type="as" name="from_uris" direction="in" />
+ <arg type="as" name="to_uris" direction="in" />
+ </method>
+
+ <method name="Delete">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+ <arg type="as" name="uris" direction="in" />
+ </method>
+
+ <method name="Cleanup">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
+ <arg type="as" name="base_uris" direction="in" />
+ <arg type="u" name="since" direction="in" />
+ </method>
+ </interface>
+</node>
diff --git a/thunar/thunar-thumbnail-cache.c b/thunar/thunar-thumbnail-cache.c
new file mode 100644
index 0000000..d1c482e
--- /dev/null
+++ b/thunar/thunar-thumbnail-cache.c
@@ -0,0 +1,692 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 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 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_DBUS
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include <thunar/thunar-thumbnail-cache-proxy.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include <thunar/thunar-private.h>
+#include <thunar/thunar-thumbnail-cache.h>
+
+
+
+static void thunar_thumbnail_cache_finalize (GObject *object);
+
+
+
+struct _ThunarThumbnailCacheClass
+{
+ GObjectClass __parent__;
+};
+
+struct _ThunarThumbnailCache
+{
+ GObject __parent__;
+
+#ifdef HAVE_DBUS
+ DBusGProxy *cache_proxy;
+
+ GList *move_source_queue;
+ GList *move_target_queue;
+ guint move_queue_idle_id;
+
+ GList *copy_source_queue;
+ GList *copy_target_queue;
+ guint copy_queue_idle_id;
+
+ GList *delete_queue;
+ guint delete_queue_idle_id;
+
+ GList *cleanup_queue;
+ guint cleanup_queue_idle_id;
+
+ GMutex *lock;
+#endif
+};
+
+
+
+G_DEFINE_TYPE (ThunarThumbnailCache, thunar_thumbnail_cache, G_TYPE_OBJECT)
+
+
+
+static void
+thunar_thumbnail_cache_class_init (ThunarThumbnailCacheClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ /* Determine the parent type class */
+ thunar_thumbnail_cache_parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = thunar_thumbnail_cache_finalize;
+}
+
+
+
+static void
+thunar_thumbnail_cache_init (ThunarThumbnailCache *cache)
+{
+#ifdef HAVE_DBUS
+ DBusGConnection *connection;
+
+ /* try to connect to D-Bus */
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+ if (connection != NULL)
+ {
+ /* create a proxy for the thumbnail cache service */
+ cache->cache_proxy =
+ dbus_g_proxy_new_for_name (connection,
+ "org.freedesktop.thumbnails.Cache1",
+ "/org/freedesktop/thumbnails/Cache1",
+ "org.freedesktop.thumbnails.Cache1");
+
+ /* release the D-Bus connection */
+ dbus_g_connection_unref (connection);
+ }
+
+ /* create a new mutex for accessing the cache from different threads */
+ cache->lock = g_mutex_new ();
+#endif
+}
+
+
+
+static void
+thunar_thumbnail_cache_finalize (GObject *object)
+{
+#ifdef HAVE_DBUS
+ ThunarThumbnailCache *cache = THUNAR_THUMBNAIL_CACHE (object);
+
+ /* acquire a cache lock */
+ g_mutex_lock (cache->lock);
+
+ /* drop the move queue idle and all queued files */
+ if (cache->move_queue_idle_id > 0)
+ g_source_remove (cache->move_queue_idle_id);
+ g_list_foreach (cache->move_source_queue, (GFunc) g_object_unref, NULL);
+ g_list_foreach (cache->move_target_queue, (GFunc) g_object_unref, NULL);
+ g_list_free (cache->move_source_queue);
+ g_list_free (cache->move_target_queue);
+
+ /* drop the copy queue idle and all queued files */
+ if (cache->copy_queue_idle_id > 0)
+ g_source_remove (cache->copy_queue_idle_id);
+ g_list_foreach (cache->copy_source_queue, (GFunc) g_object_unref, NULL);
+ g_list_foreach (cache->copy_target_queue, (GFunc) g_object_unref, NULL);
+ g_list_free (cache->copy_source_queue);
+ g_list_free (cache->copy_target_queue);
+
+ /* drop the delete queue idle and all queued files */
+ if (cache->delete_queue_idle_id > 0)
+ g_source_remove (cache->delete_queue_idle_id);
+ g_list_foreach (cache->delete_queue, (GFunc) g_object_unref, NULL);
+ g_list_free (cache->delete_queue);
+
+ /* drop the cleanup queue idle and all queued files */
+ if (cache->cleanup_queue_idle_id > 0)
+ g_source_remove (cache->cleanup_queue_idle_id);
+ g_list_foreach (cache->cleanup_queue, (GFunc) g_object_unref, NULL);
+ g_list_free (cache->cleanup_queue);
+
+ /* check if we have a valid cache proxy */
+ if (cache->cache_proxy != NULL)
+ {
+ /* release the cache proxy itself */
+ g_object_unref (cache->cache_proxy);
+ }
+
+ /* release the cache lock */
+ g_mutex_unlock (cache->lock);
+
+ /* release the mutex itself */
+ g_mutex_free (cache->lock);
+#endif
+
+ (*G_OBJECT_CLASS (thunar_thumbnail_cache_parent_class)->finalize) (object);
+}
+
+
+
+#ifdef HAVE_DBUS
+static void
+thunar_thumbnail_cache_move_async_reply (DBusGProxy *proxy,
+ GError *error,
+ gpointer user_data)
+{
+ _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
+}
+
+
+
+static void
+thunar_thumbnail_cache_move_async (ThunarThumbnailCache *cache,
+ const gchar **source_uris,
+ const gchar **target_uris)
+{
+ _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
+ _thunar_return_if_fail (source_uris != NULL);
+ _thunar_return_if_fail (target_uris != NULL);
+
+ /* request a thumbnail cache update asynchronously */
+ thunar_thumbnail_cache_proxy_move_async (cache->cache_proxy,
+ source_uris, target_uris,
+ thunar_thumbnail_cache_move_async_reply,
+ NULL);
+}
+
+
+
+static void
+thunar_thumbnail_cache_copy_async_reply (DBusGProxy *proxy,
+ GError *error,
+ gpointer user_data)
+{
+ _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
+}
+
+
+
+static void
+thunar_thumbnail_cache_copy_async (ThunarThumbnailCache *cache,
+ const gchar **source_uris,
+ const gchar **target_uris)
+{
+ _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
+ _thunar_return_if_fail (source_uris != NULL);
+ _thunar_return_if_fail (target_uris != NULL);
+
+ /* request a thumbnail cache update asynchronously */
+ thunar_thumbnail_cache_proxy_copy_async (cache->cache_proxy,
+ source_uris, target_uris,
+ thunar_thumbnail_cache_copy_async_reply,
+ NULL);
+}
+
+
+
+static void
+thunar_thumbnail_cache_delete_async_reply (DBusGProxy *proxy,
+ GError *error,
+ gpointer user_data)
+{
+ _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
+}
+
+
+
+static void
+thunar_thumbnail_cache_delete_async (ThunarThumbnailCache *cache,
+ const gchar **uris)
+{
+ _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
+ _thunar_return_if_fail (uris != NULL);
+
+ /* request a thumbnail cache update asynchronously */
+ thunar_thumbnail_cache_proxy_delete_async (cache->cache_proxy, uris,
+ thunar_thumbnail_cache_delete_async_reply,
+ NULL);
+}
+
+
+
+static void
+thunar_thumbnail_cache_cleanup_async_reply (DBusGProxy *proxy,
+ GError *error,
+ gpointer user_data)
+{
+ _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
+}
+
+
+
+static void
+thunar_thumbnail_cache_cleanup_async (ThunarThumbnailCache *cache,
+ const gchar *const *base_uris)
+{
+ _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
+ _thunar_return_if_fail (base_uris != NULL);
+
+ /* request a thumbnail cache update asynchronously */
+ thunar_thumbnail_cache_proxy_cleanup_async (cache->cache_proxy,
+ (const gchar **)base_uris, 0,
+ thunar_thumbnail_cache_cleanup_async_reply,
+ NULL);
+}
+
+
+
+static gboolean
+thunar_thumbnail_cache_process_move_queue (ThunarThumbnailCache *cache)
+{
+ GList *sp;
+ GList *tp;
+ gchar **source_uris;
+ gchar **target_uris;
+ guint n_uris;
+ guint n;
+
+ _thunar_return_val_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache), FALSE);
+
+ /* acquire a cache lock */
+ g_mutex_lock (cache->lock);
+
+ /* compute how many URIs there are */
+ n_uris = g_list_length (cache->move_source_queue);
+
+ /* allocate a string array for the URIs */
+ source_uris = g_new0 (gchar *, n_uris + 1);
+ target_uris = g_new0 (gchar *, n_uris + 1);
+
+ /* fill URI array with file URIs from the move queue */
+ for (n = 0,
+ sp = g_list_last (cache->move_source_queue),
+ tp = g_list_last (cache->move_target_queue);
+ sp != NULL && tp != NULL;
+ sp = sp->prev, tp = tp->prev, ++n)
+ {
+ source_uris[n] = g_file_get_uri (sp->data);
+ target_uris[n] = g_file_get_uri (tp->data);
+
+ /* release the file objects */
+ g_object_unref (sp->data);
+ g_object_unref (tp->data);
+ }
+
+ /* NULL-terminate the URI arrays */
+ source_uris[n] = NULL;
+ target_uris[n] = NULL;
+
+ /* asynchronously move the thumbnails */
+ thunar_thumbnail_cache_move_async (cache,
+ (const gchar **)source_uris,
+ (const gchar **)target_uris);
+
+ /* free the URI arrays */
+ g_free (source_uris);
+ g_free (target_uris);
+
+ /* release the move queue lists */
+ g_list_free (cache->move_source_queue);
+ g_list_free (cache->move_target_queue);
+ cache->move_source_queue = NULL;
+ cache->move_target_queue = NULL;
+
+ /* reset the move queue idle ID */
+ cache->move_queue_idle_id = 0;
+
+ /* release the cache lock */
+ g_mutex_unlock (cache->lock);
+
+ return FALSE;
+}
+
+
+
+static gboolean
+thunar_thumbnail_cache_process_copy_queue (ThunarThumbnailCache *cache)
+{
+ GList *sp;
+ GList *tp;
+ gchar **source_uris;
+ gchar **target_uris;
+ guint n_uris;
+ guint n;
+
+ _thunar_return_val_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache), FALSE);
+
+ /* acquire a cache lock */
+ g_mutex_lock (cache->lock);
+
+ /* compute how many URIs there are */
+ n_uris = g_list_length (cache->copy_source_queue);
+
+ /* allocate a string array for the URIs */
+ source_uris = g_new0 (gchar *, n_uris + 1);
+ target_uris = g_new0 (gchar *, n_uris + 1);
+
+ /* fill URI array with file URIs from the copy queue */
+ for (n = 0,
+ sp = g_list_last (cache->copy_source_queue),
+ tp = g_list_last (cache->copy_target_queue);
+ sp != NULL && tp != NULL;
+ sp = sp->prev, tp = tp->prev, ++n)
+ {
+ source_uris[n] = g_file_get_uri (sp->data);
+ target_uris[n] = g_file_get_uri (tp->data);
+
+ /* release the file objects */
+ g_object_unref (sp->data);
+ g_object_unref (tp->data);
+ }
+
+ /* NULL-terminate the URI arrays */
+ source_uris[n] = NULL;
+ target_uris[n] = NULL;
+
+ /* asynchronously copy the thumbnails */
+ thunar_thumbnail_cache_copy_async (cache,
+ (const gchar **)source_uris,
+ (const gchar **)target_uris);
+
+ /* free the URI arrays */
+ g_free (source_uris);
+ g_free (target_uris);
+
+ /* release the copy queue lists */
+ g_list_free (cache->copy_source_queue);
+ g_list_free (cache->copy_target_queue);
+ cache->copy_source_queue = NULL;
+ cache->copy_target_queue = NULL;
+
+ /* reset the copy queue idle ID */
+ cache->copy_queue_idle_id = 0;
+
+ /* release the cache lock */
+ g_mutex_unlock (cache->lock);
+
+ return FALSE;
+}
+
+
+
+static gboolean
+thunar_thumbnail_cache_process_delete_queue (ThunarThumbnailCache *cache)
+{
+ GList *lp;
+ gchar **uris;
+ guint n_uris;
+ guint n;
+
+ _thunar_return_val_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache), FALSE);
+
+ /* acquire a cache lock */
+ g_mutex_lock (cache->lock);
+
+ /* compute how many URIs there are */
+ n_uris = g_list_length (cache->delete_queue);
+
+ /* allocate a string array for the URIs */
+ uris = g_new0 (gchar *, n_uris + 1);
+
+ /* fill URI array with file URIs from the delete queue */
+ for (lp = g_list_last (cache->delete_queue), n = 0; lp != NULL; lp = lp->prev, ++n)
+ {
+ uris[n] = g_file_get_uri (lp->data);
+
+ /* release the file object */
+ g_object_unref (lp->data);
+ }
+
+ /* NULL-terminate the URI array */
+ uris[n] = NULL;
+
+ /* asynchronously delete the thumbnails */
+ thunar_thumbnail_cache_delete_async (cache, (const gchar **)uris);
+
+ /* free the URI array */
+ g_free (uris);
+
+ /* release the delete queue list */
+ g_list_free (cache->delete_queue);
+ cache->delete_queue = NULL;
+
+ /* reset the delete queue idle ID */
+ cache->delete_queue_idle_id = 0;
+
+ /* release the cache lock */
+ g_mutex_unlock (cache->lock);
+
+ return FALSE;
+}
+
+
+
+static gboolean
+thunar_thumbnail_cache_process_cleanup_queue (ThunarThumbnailCache *cache)
+{
+ GList *lp;
+ gchar **uris;
+ guint n_uris;
+ guint n;
+
+ _thunar_return_val_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache), FALSE);
+
+ /* acquire a cache lock */
+ g_mutex_lock (cache->lock);
+
+ /* compute how many URIs there are */
+ n_uris = g_list_length (cache->cleanup_queue);
+
+ /* allocate a string array for the URIs */
+ uris = g_new0 (gchar *, n_uris + 1);
+
+ g_debug ("cleanup:");
+
+ /* fill URI array with file URIs from the cleanup queue */
+ for (lp = g_list_last (cache->cleanup_queue), n = 0; lp != NULL; lp = lp->prev, ++n)
+ {
+ uris[n] = g_file_get_uri (lp->data);
+
+ g_debug (" %s", uris[n]);
+
+ /* release the file object */
+ g_object_unref (lp->data);
+ }
+
+ /* NULL-terminate the URI array */
+ uris[n] = NULL;
+
+ /* asynchronously cleanup the thumbnails */
+ thunar_thumbnail_cache_cleanup_async (cache, (const gchar *const *)uris);
+
+ /* free the URI array */
+ g_free (uris);
+
+ /* release the cleanup queue list */
+ g_list_free (cache->cleanup_queue);
+ cache->cleanup_queue = NULL;
+
+ /* reset the cleanup queue idle ID */
+ cache->cleanup_queue_idle_id = 0;
+
+ /* release the cache lock */
+ g_mutex_unlock (cache->lock);
+
+ return FALSE;
+}
+#endif /* HAVE_DBUS */
+
+
+
+ThunarThumbnailCache *
+thunar_thumbnail_cache_new (void)
+{
+ return g_object_new (THUNAR_TYPE_THUMBNAIL_CACHE, NULL);
+}
+
+
+
+void
+thunar_thumbnail_cache_move_file (ThunarThumbnailCache *cache,
+ GFile *source_file,
+ GFile *target_file)
+{
+ _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
+ _thunar_return_if_fail (G_IS_FILE (source_file));
+ _thunar_return_if_fail (G_IS_FILE (target_file));
+
+#ifdef HAVE_DBUS
+ /* acquire a cache lock */
+ g_mutex_lock (cache->lock);
+
+ /* check if we have a valid proxy for the cache service */
+ if (cache->cache_proxy != NULL)
+ {
+ /* cancel any pending timeout to process the move queue */
+ if (cache->move_queue_idle_id > 0)
+ {
+ g_source_remove (cache->move_queue_idle_id);
+ cache->move_queue_idle_id = 0;
+ }
+
+ /* add the files to the move queue */
+ cache->move_source_queue = g_list_prepend (cache->move_source_queue,
+ g_object_ref (source_file));
+ cache->move_target_queue = g_list_prepend (cache->move_target_queue,
+ g_object_ref (target_file));
+
+ /* process the move queue in a 250ms timeout */
+ cache->move_queue_idle_id =
+ g_timeout_add (250, (GSourceFunc) thunar_thumbnail_cache_process_move_queue,
+ cache);
+ }
+
+ /* release the cache lock */
+ g_mutex_unlock (cache->lock);
+#endif
+}
+
+
+
+void
+thunar_thumbnail_cache_copy_file (ThunarThumbnailCache *cache,
+ GFile *source_file,
+ GFile *target_file)
+{
+ _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
+ _thunar_return_if_fail (G_IS_FILE (source_file));
+ _thunar_return_if_fail (G_IS_FILE (target_file));
+
+#ifdef HAVE_DBUS
+ /* acquire a cache lock */
+ g_mutex_lock (cache->lock);
+
+ /* check if we have a valid proxy for the cache service */
+ if (cache->cache_proxy != NULL)
+ {
+ /* cancel any pending timeout to process the copy queue */
+ if (cache->copy_queue_idle_id > 0)
+ {
+ g_source_remove (cache->copy_queue_idle_id);
+ cache->copy_queue_idle_id = 0;
+ }
+
+ /* add the files to the copy queues */
+ cache->copy_source_queue = g_list_prepend (cache->copy_source_queue,
+ g_object_ref (source_file));
+ cache->copy_target_queue = g_list_prepend (cache->copy_target_queue,
+ g_object_ref (target_file));
+
+ /* process the copy queue in a 250ms timeout */
+ cache->copy_queue_idle_id =
+ g_timeout_add (500, (GSourceFunc) thunar_thumbnail_cache_process_copy_queue,
+ cache);
+ }
+
+ /* release the cache lock */
+ g_mutex_unlock (cache->lock);
+#endif
+}
+
+
+
+void
+thunar_thumbnail_cache_delete_file (ThunarThumbnailCache *cache,
+ GFile *file)
+{
+ _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
+ _thunar_return_if_fail (G_IS_FILE (file));
+
+#ifdef HAVE_DBUS
+ /* acquire a cache lock */
+ g_mutex_lock (cache->lock);
+
+ /* check if we have a valid proxy for the cache service */
+ if (cache->cache_proxy)
+ {
+ /* cancel any pending timeout to process the delete queue */
+ if (cache->delete_queue_idle_id > 0)
+ {
+ g_source_remove (cache->delete_queue_idle_id);
+ cache->delete_queue_idle_id = 0;
+ }
+
+ /* add the file to the delete queue */
+ cache->delete_queue = g_list_prepend (cache->delete_queue, g_object_ref (file));
+
+ /* process the delete queue in a 250ms timeout */
+ cache->delete_queue_idle_id =
+ g_timeout_add (500, (GSourceFunc) thunar_thumbnail_cache_process_delete_queue,
+ cache);
+ }
+
+ /* release the cache lock */
+ g_mutex_unlock (cache->lock);
+#endif
+}
+
+
+
+void
+thunar_thumbnail_cache_cleanup_file (ThunarThumbnailCache *cache,
+ GFile *file)
+{
+ _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
+ _thunar_return_if_fail (G_IS_FILE (file));
+
+#ifdef HAVE_DBUS
+ /* acquire a cache lock */
+ g_mutex_lock (cache->lock);
+
+ /* check if we have a valid proxy for the cache service */
+ if (cache->cache_proxy)
+ {
+ /* cancel any pending timeout to process the cleanup queue */
+ if (cache->cleanup_queue_idle_id > 0)
+ {
+ g_source_remove (cache->cleanup_queue_idle_id);
+ cache->cleanup_queue_idle_id = 0;
+ }
+
+ /* add the file to the cleanup queue */
+ cache->cleanup_queue = g_list_prepend (cache->cleanup_queue, g_object_ref (file));
+
+ /* process the cleanup queue in a 250ms timeout */
+ cache->cleanup_queue_idle_id =
+ g_timeout_add (1000, (GSourceFunc) thunar_thumbnail_cache_process_cleanup_queue,
+ cache);
+ }
+
+ /* release the cache lock */
+ g_mutex_unlock (cache->lock);
+#endif
+}
diff --git a/thunar/thunar-thumbnail-cache.h b/thunar/thunar-thumbnail-cache.h
new file mode 100644
index 0000000..dc32fc8
--- /dev/null
+++ b/thunar/thunar-thumbnail-cache.h
@@ -0,0 +1,56 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 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 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __THUNAR_THUMBNAIL_CACHE_H__
+#define __THUNAR_THUMBNAIL_CACHE_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define THUNAR_TYPE_THUMBNAIL_CACHE (thunar_thumbnail_cache_get_type ())
+#define THUNAR_THUMBNAIL_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_THUMBNAIL_CACHE, ThunarThumbnailCache))
+#define THUNAR_THUMBNAIL_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_THUMBNAIL_CACHE, ThunarThumbnailCacheClass))
+#define THUNAR_IS_THUMBNAIL_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_THUMBNAIL_CACHE))
+#define THUNAR_IS_THUMBNAIL_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_THUMBNAIL_CACHE)
+#define THUNAR_THUMBNAIL_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_THUMBNAIL_CACHE, ThunarThumbnailCacheClass))
+
+typedef struct _ThunarThumbnailCachePrivate ThunarThumbnailCachePrivate;
+typedef struct _ThunarThumbnailCacheClass ThunarThumbnailCacheClass;
+typedef struct _ThunarThumbnailCache ThunarThumbnailCache;
+
+GType thunar_thumbnail_cache_get_type (void) G_GNUC_CONST;
+
+ThunarThumbnailCache *thunar_thumbnail_cache_new (void) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+
+void thunar_thumbnail_cache_move_file (ThunarThumbnailCache *cache,
+ GFile *source_file,
+ GFile *target_file);
+void thunar_thumbnail_cache_copy_file (ThunarThumbnailCache *cache,
+ GFile *source_file,
+ GFile *target_file);
+void thunar_thumbnail_cache_delete_file (ThunarThumbnailCache *cache,
+ GFile *file);
+void thunar_thumbnail_cache_cleanup_file (ThunarThumbnailCache *cache,
+ GFile *file);
+
+G_END_DECLS
+
+#endif /* !__THUNAR_THUMBNAIL_CACHE_H__ */
diff --git a/thunar/thunar-thumbnailer-dbus.xml b/thunar/thunar-thumbnailer-dbus.xml
index e6b39f7..d0d2ada 100644
--- a/thunar/thunar-thumbnailer-dbus.xml
+++ b/thunar/thunar-thumbnailer-dbus.xml
@@ -11,7 +11,7 @@
<arg type="u" name="handle" direction="out" />
</method>
- <method name="Unqueue">
+ <method name="Dequeue">
<annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
<arg type="u" name="handle" direction="in" />
</method>
diff --git a/thunar/thunar-thumbnailer.c b/thunar/thunar-thumbnailer.c
index 8146d29..32d6218 100644
--- a/thunar/thunar-thumbnailer.c
+++ b/thunar/thunar-thumbnailer.c
@@ -1,6 +1,6 @@
/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
- * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-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
@@ -47,58 +47,21 @@
* Please note that all D-Bus calls are performed asynchronously.
*
*
- * Queue
- * =====
- *
- * ThunarThumbnailer maintains a wait queue to group individual thumbnail requests.
- * The wait queue is processed at most every 100ms. This is done to reduce the
- * overall D-Bus noise when dealing with a lot of requests. The more thumbnails are
- * requested in a 100ms time slot, the less D-Bus methods are sent.
- *
- * Let N be the number of requests made for individual files in a 100ms slot.
- * Compared to sending out one requests per file (which generates 4*N D-Bus messages,
- * 1 Queue, 1 Started, 1 Ready/Error and 1 Finished for each of the N files), the wait
- * queue technique only causes 3+N D-Bus messages to be sent (1 Queue, 1 Started,
- * N Ready/Error and 1 Finished). This can be further improved on the service side
- * if the D-Bus thumbnailer groups Ready/Error messages (which of course has drawbacks
- * with regards to the overall thumbnailing responsiveness).
- *
- * Before a URI is added to the wait queue, it is checked whether it isn't already
- * 1) in the wait queue, 2) part of a pending or active request or 3) part of a
- * finished request which has an idle function pending.
- *
- * When a request call is finally sent out, an internal request ID is created and
+ * When a request call is sent out, an internal request ID is created and
* associated with the corresponding DBusGProxyCall via the request_call_mapping hash
- * table. It also remembers the URIs for the internal request ID in the
- * request_uris_mapping hash table.
+ * table.
*
* The D-Bus reply handler then checks if there was an delivery error or
* not. If the request method was sent successfully, the handle returned by the
* D-Bus thumbnailer is associated bidirectionally with the internal request ID via
- * the request_handle_mapping and handle_request_mappings. If the request could
- * not be sent at all, the URIs array is dropped from request_uris_mapping. In
- * both cases, the association of the internal request ID with the DBusGProxyCall
- * is removed from request_call_mapping.
+ * the request_handle_mapping and handle_request_mappings. In both cases, the
+ * association of the internal request ID with the DBusGProxyCall is removed from
+ * request_call_mapping.
*
- * These hash tables play a major role in the Started, Finished, Error and Ready
+ * These hash tables play a major role in the Finished, Error and Ready
* signal handlers.
*
*
- * Started
- * =======
- *
- * When a Started signal is emitted by the D-Bus thumbnailer, ThunarThumbnailer
- * receives the handle and looks up the corresponding internal request ID. If
- * it exists (which it should), it schedules an idle function to handle the
- * signal in the application's main loop.
- *
- * The idle function then looks up the URIs array for the request ID from the
- * request_uris_mapping. For each of these URIs the corresponding ThunarFile
- * is looked up from the file cache (which represents files currently being
- * used somewhere in the UI), and if the ThunarFile exists in the cache it's
- * thumb state is set to _LOADING (unless it's already marked as _READY).
- *
- *
* Ready / Error
* =============
*
@@ -112,12 +75,12 @@
*
* The Finished signal handler looks up the internal request ID based on
* the D-Bus thumbnailer handle. It then drops all corresponding information
- * from handle_request_mapping, request_handle_mapping and request_uris_mapping.
+ * from handle_request_mapping and request_handle_mapping.
*/
-#if HAVE_DBUS
+#ifdef HAVE_DBUS
typedef enum
{
THUNAR_THUMBNAILER_IDLE_ERROR,
@@ -153,20 +116,13 @@ static void thunar_thumbnailer_thumbnailer_ready (DBusGPr
guint32 handle,
const gchar **uris,
ThunarThumbnailer *thumbnailer);
-static void thunar_thumbnailer_thumbnailer_started (DBusGProxy *proxy,
- guint handle,
- ThunarThumbnailer *thumbnailer);
-static gpointer thunar_thumbnailer_queue_async (ThunarThumbnailer *thumbnailer,
+static guint thunar_thumbnailer_queue_async (ThunarThumbnailer *thumbnailer,
gchar **uris,
const gchar **mime_hints);
static gboolean thunar_thumbnailer_error_idle (gpointer user_data);
static gboolean thunar_thumbnailer_ready_idle (gpointer user_data);
-static gboolean thunar_thumbnailer_started_idle (gpointer user_data);
static void thunar_thumbnailer_call_free (ThunarThumbnailerCall *call);
static void thunar_thumbnailer_idle_free (gpointer data);
-static ThunarThumbnailerItem *thunar_thumbnailer_item_new (GFile *file,
- const gchar *mime_hint);
-static void thunar_thumbnailer_item_free (gpointer data);
#endif
@@ -184,10 +140,6 @@ struct _ThunarThumbnailer
/* proxies to communicate with D-Bus services */
DBusGProxy *thumbnailer_proxy;
- /* wait queue used to delay (and thereby group) thumbnail requests */
- GList *wait_queue;
- guint wait_queue_idle_id;
-
/* hash table to map D-Bus service handles to ThunarThumbnailer requests */
GHashTable *handle_request_mapping;
@@ -197,9 +149,6 @@ struct _ThunarThumbnailer
/* hash table to map ThunarThumbnailer requests to DBusGProxyCalls */
GHashTable *request_call_mapping;
- /* hash table to map ThunarThumbnailer requests to URI arrays */
- GHashTable *request_uris_mapping;
-
GMutex *lock;
/* cached arrays of URI schemes and MIME types for which thumbnails
@@ -208,7 +157,7 @@ struct _ThunarThumbnailer
gchar **supported_types;
/* last ThunarThumbnailer request ID */
- gpointer last_request;
+ guint last_request;
/* IDs of idle functions */
GList *idles;
@@ -244,9 +193,6 @@ struct _ThunarThumbnailerItem
-#ifdef HAVE_DBUS
-static DBusGProxy *thunar_thumbnailer_proxy;
-#endif
@@ -274,9 +220,8 @@ thunar_thumbnailer_init (ThunarThumbnailer *thumbnailer)
thumbnailer->lock = g_mutex_new ();
thumbnailer->supported_schemes = NULL;
thumbnailer->supported_types = NULL;
- thumbnailer->last_request = GUINT_TO_POINTER (0);
+ thumbnailer->last_request = 0;
thumbnailer->idles = NULL;
- thumbnailer->wait_queue_idle_id = 0;
/* try to connect to D-Bus */
connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
@@ -294,9 +239,6 @@ thunar_thumbnailer_init (ThunarThumbnailer *thumbnailer)
g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
thumbnailer->request_call_mapping =
g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
- thumbnailer->request_uris_mapping =
- g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
- (GDestroyNotify) g_strfreev);
}
/* release the D-Bus connection if we have one */
@@ -319,14 +261,6 @@ thunar_thumbnailer_finalize (GObject *object)
/* acquire the thumbnailer lock */
g_mutex_lock (thumbnailer->lock);
- /* clear the request queue */
- g_list_foreach (thumbnailer->wait_queue, (GFunc) thunar_thumbnailer_item_free, NULL);
- g_list_free (thumbnailer->wait_queue);
-
- /* remove the request queue processing idle handler */
- if (thumbnailer->wait_queue_idle_id > 0)
- g_source_remove (thumbnailer->wait_queue_idle_id);
-
/* abort all pending idle functions */
for (lp = thumbnailer->idles; lp != NULL; lp = lp->next)
{
@@ -348,16 +282,15 @@ thunar_thumbnailer_finalize (GObject *object)
g_hash_table_unref (thumbnailer->request_call_mapping);
#if 0
- /* unqueue all pending requests */
+ /* dequeue all pending requests */
list = g_hash_table_get_keys (thumbnailer->handle_request_mapping);
for (lp = list; lp != NULL; lp = lp->next)
- thunar_thumbnailer_unqueue_internal (thumbnailer, GPOINTER_TO_UINT (lp->data));
+ thunar_thumbnailer_dequeue_internal (thumbnailer, GPOINTER_TO_UINT (lp->data));
g_list_free (list);
#endif
g_hash_table_unref (thumbnailer->handle_request_mapping);
g_hash_table_unref (thumbnailer->request_handle_mapping);
- g_hash_table_unref (thumbnailer->request_uris_mapping);
/* disconnect from the thumbnailer proxy */
g_signal_handlers_disconnect_matched (thumbnailer->thumbnailer_proxy,
@@ -396,51 +329,37 @@ thunar_thumbnailer_init_thumbnailer_proxy (ThunarThumbnailer *thumbnailer,
return;
}
- /* create the thumbnailer proxy shared by all ThunarThumbnailers on demand */
- if (thunar_thumbnailer_proxy == NULL)
- {
- /* create the shared thumbnailer proxy */
- thunar_thumbnailer_proxy =
- dbus_g_proxy_new_for_name (connection,
- "org.freedesktop.thumbnails.Thumbnailer1",
- "/org/freedesktop/thumbnails/Thumbnailer1",
- "org.freedesktop.thumbnails.Thumbnailer1");
-
- /* make sure to set it to NULL when the last reference is dropped */
- g_object_add_weak_pointer (G_OBJECT (thunar_thumbnailer_proxy),
- (gpointer) &thunar_thumbnailer_proxy);
-
- thumbnailer->thumbnailer_proxy = thunar_thumbnailer_proxy;
-
- /* TODO this should actually be VOID:UINT,BOXED,INT,STRING */
- dbus_g_object_register_marshaller (_thunar_marshal_VOID__UINT_BOXED_UINT_STRING,
- G_TYPE_NONE,
- G_TYPE_UINT,
- G_TYPE_STRV,
- G_TYPE_UINT,
- G_TYPE_STRING,
- G_TYPE_INVALID);
-
- dbus_g_object_register_marshaller ((GClosureMarshal) _thunar_marshal_VOID__UINT_BOXED,
- G_TYPE_NONE,
- G_TYPE_UINT,
- G_TYPE_STRV,
- G_TYPE_INVALID);
-
- dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Error",
- G_TYPE_UINT, G_TYPE_STRV, G_TYPE_UINT, G_TYPE_STRING,
- G_TYPE_INVALID);
- dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Finished",
- G_TYPE_UINT, G_TYPE_INVALID);
- dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Ready",
- G_TYPE_UINT, G_TYPE_STRV, G_TYPE_INVALID);
- dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Started",
- G_TYPE_UINT, G_TYPE_INVALID);
- }
- else
- {
- thumbnailer->thumbnailer_proxy = g_object_ref (thunar_thumbnailer_proxy);
- }
+ /* create the thumbnailer proxy */
+ thumbnailer->thumbnailer_proxy =
+ dbus_g_proxy_new_for_name (connection,
+ "org.freedesktop.thumbnails.Thumbnailer1",
+ "/org/freedesktop/thumbnails/Thumbnailer1",
+ "org.freedesktop.thumbnails.Thumbnailer1");
+
+ /* TODO this should actually be VOID:UINT,BOXED,INT,STRING */
+ dbus_g_object_register_marshaller (_thunar_marshal_VOID__UINT_BOXED_UINT_STRING,
+ G_TYPE_NONE,
+ G_TYPE_UINT,
+ G_TYPE_STRV,
+ G_TYPE_UINT,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
+
+ dbus_g_object_register_marshaller ((GClosureMarshal) _thunar_marshal_VOID__UINT_BOXED,
+ G_TYPE_NONE,
+ G_TYPE_UINT,
+ G_TYPE_STRV,
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Error",
+ G_TYPE_UINT, G_TYPE_STRV, G_TYPE_UINT, G_TYPE_STRING,
+ G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Finished",
+ G_TYPE_UINT, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Ready",
+ G_TYPE_UINT, G_TYPE_STRV, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Started",
+ G_TYPE_UINT, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (thumbnailer->thumbnailer_proxy, "Error",
G_CALLBACK (thunar_thumbnailer_thumbnailer_error),
@@ -451,9 +370,6 @@ thunar_thumbnailer_init_thumbnailer_proxy (ThunarThumbnailer *thumbnailer,
dbus_g_proxy_connect_signal (thumbnailer->thumbnailer_proxy, "Ready",
G_CALLBACK (thunar_thumbnailer_thumbnailer_ready),
thumbnailer, NULL);
- dbus_g_proxy_connect_signal (thumbnailer->thumbnailer_proxy, "Started",
- G_CALLBACK (thunar_thumbnailer_thumbnailer_started),
- thumbnailer, NULL);
}
@@ -576,12 +492,11 @@ thunar_thumbnailer_thumbnailer_finished (DBusGProxy *proxy,
GUINT_TO_POINTER (handle));
/* check if we have a request for this handle */
- if (request != NULL)
+ if (GPOINTER_TO_UINT (request) > 0)
{
/* the request is finished, drop all the information about it */
g_hash_table_remove (thumbnailer->handle_request_mapping, request);
g_hash_table_remove (thumbnailer->request_handle_mapping, request);
- g_hash_table_remove (thumbnailer->request_uris_mapping, request);
}
}
@@ -622,44 +537,6 @@ thunar_thumbnailer_thumbnailer_ready (DBusGProxy *proxy,
static void
-thunar_thumbnailer_thumbnailer_started (DBusGProxy *proxy,
- guint handle,
- ThunarThumbnailer *thumbnailer)
-{
- ThunarThumbnailerIdle *idle;
- gpointer request;
-
- _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
- _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
-
- /* look up the request for this D-Bus service handle */
- request = g_hash_table_lookup (thumbnailer->handle_request_mapping,
- GUINT_TO_POINTER (handle));
-
- /* check if we have a request for this handle */
- if (request != NULL)
- {
- /* allocate a new idle struct */
- idle = g_slice_new0 (ThunarThumbnailerIdle);
- idle->type = THUNAR_THUMBNAILER_IDLE_STARTED;
- idle->thumbnailer = g_object_ref (thumbnailer);
-
- /* remember the request because we need it in the idle function */
- idle->data.request = request;
-
- /* remember the idle struct because we might have to remove it in finalize() */
- thumbnailer->idles = g_list_prepend (thumbnailer->idles, idle);
-
- /* call the started idle function when we have the time */
- idle->id = g_idle_add_full (G_PRIORITY_LOW,
- thunar_thumbnailer_started_idle, idle,
- thunar_thumbnailer_idle_free);
- }
-}
-
-
-
-static void
thunar_thumbnailer_queue_async_reply (DBusGProxy *proxy,
guint handle,
GError *error,
@@ -667,9 +544,6 @@ thunar_thumbnailer_queue_async_reply (DBusGProxy *proxy,
{
ThunarThumbnailerCall *call = user_data;
ThunarThumbnailer *thumbnailer = THUNAR_THUMBNAILER (call->thumbnailer);
-#ifndef NDEBUG
- gchar **uris;
-#endif
_thunar_return_if_fail (DBUS_IS_G_PROXY (proxy));
_thunar_return_if_fail (call != NULL);
@@ -677,20 +551,7 @@ thunar_thumbnailer_queue_async_reply (DBusGProxy *proxy,
g_mutex_lock (thumbnailer->lock);
- if (error != NULL)
- {
-#ifndef NDEBUG
- /* get the URIs array for this request */
- uris = g_hash_table_lookup (thumbnailer->request_uris_mapping, call->request);
-
- /* the array should always exist, otherwise there's a bug in the program */
- _thunar_assert (uris != NULL);
-#endif
-
- /* the request is "finished", forget about its URIs */
- g_hash_table_remove (thumbnailer->request_uris_mapping, call->request);
- }
- else
+ if (error == NULL)
{
/* remember that this request and D-Bus handle belong together */
g_hash_table_insert (thumbnailer->request_handle_mapping,
@@ -709,7 +570,7 @@ thunar_thumbnailer_queue_async_reply (DBusGProxy *proxy,
-static gpointer
+static guint
thunar_thumbnailer_queue_async (ThunarThumbnailer *thumbnailer,
gchar **uris,
const gchar **mime_hints)
@@ -725,23 +586,20 @@ thunar_thumbnailer_queue_async (ThunarThumbnailer *thumbnailer,
_thunar_return_val_if_fail (DBUS_IS_G_PROXY (thumbnailer->thumbnailer_proxy), 0);
/* compute the next request ID, making sure it's never 0 */
- request_no = GPOINTER_TO_UINT (thumbnailer->last_request) + 1;
+ request_no = thumbnailer->last_request + 1;
request_no = MAX (request_no, 1);
/* remember the ID for the next request */
- thumbnailer->last_request = GUINT_TO_POINTER (request_no);
+ thumbnailer->last_request = request_no;
- /* use the new request ID for this request */
- request = thumbnailer->last_request;
+ /* use the newly generated ID for this request */
+ request = GUINT_TO_POINTER (request_no);
/* allocate a new call struct for the async D-Bus call */
thumbnailer_call = g_slice_new0 (ThunarThumbnailerCall);
thumbnailer_call->request = request;
thumbnailer_call->thumbnailer = g_object_ref (thumbnailer);
- /* remember the URIs for this request */
- g_hash_table_insert (thumbnailer->request_uris_mapping, request, uris);
-
/* queue thumbnails for the given URIs asynchronously */
call = thunar_thumbnailer_proxy_queue_async (thumbnailer->thumbnailer_proxy,
(const gchar **)uris, mime_hints,
@@ -753,7 +611,7 @@ thunar_thumbnailer_queue_async (ThunarThumbnailer *thumbnailer,
g_hash_table_insert (thumbnailer->request_call_mapping, request, call);
/* return the request ID used for this request */
- return request;
+ return request_no;
}
@@ -836,224 +694,6 @@ thunar_thumbnailer_ready_idle (gpointer user_data)
-static gboolean
-thunar_thumbnailer_started_idle (gpointer user_data)
-{
- ThunarThumbnailerIdle *idle = user_data;
- const gchar **uris;
- ThunarFile *file;
- GFile *gfile;
- guint n;
-
- _thunar_return_val_if_fail (idle != NULL, FALSE);
- _thunar_return_val_if_fail (idle->type == THUNAR_THUMBNAILER_IDLE_STARTED, FALSE);
-
- g_mutex_lock (idle->thumbnailer->lock);
-
- /* look up the URIs that belong to this request */
- uris = g_hash_table_lookup (idle->thumbnailer->request_uris_mapping,
- idle->data.request);
-
- /* iterate over all URIs if there are any */
- for (n = 0; uris != NULL && uris[n] != NULL; ++n)
- {
- /* look up the corresponding ThunarFile from the cache */
- gfile = g_file_new_for_uri (uris[n]);
- file = thunar_file_cache_lookup (gfile);
- g_object_unref (gfile);
-
- /* check if we have a file in the cache */
- if (file != NULL)
- {
- /* set the thumbnail state to loading unless we already have a thumbnail.
- * This is to prevent race conditions with the other idle functions */
- if (thunar_file_get_thumb_state (file) != THUNAR_FILE_THUMB_STATE_READY)
- thunar_file_set_thumb_state (file, THUNAR_FILE_THUMB_STATE_LOADING);
- }
- }
-
-
- /* remove the idle struct */
- idle->thumbnailer->idles = g_list_remove (idle->thumbnailer->idles, idle);
-
- g_mutex_unlock (idle->thumbnailer->lock);
-
- /* remove the idle source, which also destroys the idle struct */
- return FALSE;
-}
-
-
-
-static gboolean
-thunar_thumbnailer_file_is_in_wait_queue (ThunarThumbnailer *thumbnailer,
- ThunarFile *file)
-{
- ThunarThumbnailerItem *item;
- gboolean in_wait_queue = FALSE;
- GList *lp;
-
- g_mutex_lock (thumbnailer->lock);
-
- for (lp = thumbnailer->wait_queue; !in_wait_queue && lp != NULL; lp = lp->next)
- {
- item = lp->data;
-
- if (g_file_equal (item->file, thunar_file_get_file (file)))
- in_wait_queue = TRUE;
- }
-
- g_mutex_unlock (thumbnailer->lock);
-
- return in_wait_queue;
-}
-
-
-
-static gboolean
-thunar_thumbnailer_process_wait_queue (ThunarThumbnailer *thumbnailer)
-{
- ThunarThumbnailerItem *item;
- gpointer request;
- GList *lp;
- gchar **mime_hints;
- gchar **uris;
- guint n_items;
- guint n;
-
- _thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), FALSE);
-
- g_mutex_lock (thumbnailer->lock);
-
- /* determine how many URIs are in the wait queue */
- n_items = g_list_length (thumbnailer->wait_queue);
-
- /* allocate arrays for URIs and mime hints */
- uris = g_new0 (gchar *, n_items + 1);
- mime_hints = g_new0 (gchar *, n_items + 1);
-
- /* fill URI and MIME hint arrays with items from the wait queue */
- for (lp = g_list_last (thumbnailer->wait_queue), n = 0; lp != NULL; lp = lp->prev, ++n)
- {
- /* fetch the next item from the queue */
- item = lp->data;
-
- /* save URI and MIME hint in the arrays */
- uris[n] = g_file_get_uri (item->file);
- mime_hints[n] = item->mime_hint;
-
- /* destroy the GFile and the queue item. The MIME hints are free'd later */
- g_object_unref (item->file);
- g_slice_free (ThunarThumbnailerItem, item);
- }
-
- /* NULL-terminate both arrays */
- uris[n] = NULL;
- mime_hints[n] = NULL;
-
- /* queue a thumbnail request for the URIs from the wait queue */
- request = thunar_thumbnailer_queue_async (thumbnailer, uris,
- (const gchar **)mime_hints);
-
- /* free mime hints array */
- g_strfreev (mime_hints);
-
- /* clear the wait queue */
- g_list_free (thumbnailer->wait_queue);
- thumbnailer->wait_queue = NULL;
-
- /* reset the wait queue idle ID */
- thumbnailer->wait_queue_idle_id = 0;
-
- g_mutex_unlock (thumbnailer->lock);
-
- return FALSE;
-}
-
-
-
-static gboolean
-thunar_thumbnailer_file_is_queued (ThunarThumbnailer *thumbnailer,
- ThunarFile *file)
-{
- gboolean is_queued = FALSE;
- GList *values;
- GList *lp;
- gchar **uris;
- gchar *uri;
- guint n;
-
- /* get a list with all URI arrays of already queued requests */
- values = g_hash_table_get_values (thumbnailer->request_uris_mapping);
-
- /* if we have none, the file cannot be queued ... or can it? ;) */
- if (values == NULL)
- return FALSE;
-
- /* determine the URI for this file */
- uri = thunar_file_dup_uri (file);
-
- /* iterate over all URI arrays */
- for (lp = values; !is_queued && lp != NULL; lp = lp->next)
- {
- uris = lp->data;
-
- /* check if the file is included in the URI array of the current request */
- for (n = 0; !is_queued && uris != NULL && uris[n] != NULL; ++n)
- if (g_utf8_collate (uri, uris[n]) == 0)
- is_queued = TRUE;
- }
-
- /* free the file URI */
- g_free (uri);
-
- /* free the URI array list */
- g_list_free (values);
-
- return is_queued;
-}
-
-
-
-static gboolean
-thunar_thumbnailer_file_is_ready (ThunarThumbnailer *thumbnailer,
- ThunarFile *file)
-{
- ThunarThumbnailerIdle *idle;
- gboolean is_ready = FALSE;
- GList *lp;
- gchar *uri;
- guint n;
-
- /* determine the URI or this file */
- uri = thunar_file_dup_uri (file);
-
- /* iterate over all idle structs */
- for (lp = thumbnailer->idles; !is_ready && lp != NULL; lp = lp->next)
- {
- /* skip invalid idles */
- if (lp->data != NULL)
- continue;
-
- idle = lp->data;
-
- /* skip non-ready idles and idles without any URIs */
- if (idle->type != THUNAR_THUMBNAILER_IDLE_READY || idle->data.uris == NULL)
- continue;
-
- /* check if the file is included in this ready idle */
- for (n = 0; !is_ready && idle->data.uris[n] != NULL; ++n)
- if (g_utf8_collate (uri, idle->data.uris[n]) == 0)
- is_ready = TRUE;
- }
-
- /* free the file URI */
- g_free (uri);
-
- return is_ready;
-}
-
-
-
static void
thunar_thumbnailer_call_free (ThunarThumbnailerCall *call)
{
@@ -1088,35 +728,6 @@ thunar_thumbnailer_idle_free (gpointer data)
/* free the struct */
g_slice_free (ThunarThumbnailerIdle, idle);
}
-
-
-
-static ThunarThumbnailerItem *
-thunar_thumbnailer_item_new (GFile *file,
- const gchar *mime_hint)
-{
- ThunarThumbnailerItem *item;
-
- _thunar_return_val_if_fail (G_IS_FILE (file), NULL);
- _thunar_return_val_if_fail (mime_hint != NULL && mime_hint != '\0', NULL);
-
- item = g_slice_new0 (ThunarThumbnailerItem);
- item->file = g_object_ref (file);
- item->mime_hint = g_strdup (mime_hint);
-
- return item;
-}
-
-
-static void
-thunar_thumbnailer_item_free (gpointer data)
-{
- ThunarThumbnailerItem *item = data;
-
- g_object_unref (item->file);
- g_free (item->mime_hint);
- g_slice_free (ThunarThumbnailerItem, item);
-}
#endif /* HAVE_DBUS */
@@ -1142,7 +753,8 @@ thunar_thumbnailer_new (void)
gboolean
thunar_thumbnailer_queue_file (ThunarThumbnailer *thumbnailer,
- ThunarFile *file)
+ ThunarFile *file,
+ guint *request)
{
GList files;
@@ -1155,22 +767,24 @@ thunar_thumbnailer_queue_file (ThunarThumbnailer *thumbnailer,
files.prev = NULL;
/* queue a thumbnail request for the file */
- return thunar_thumbnailer_queue_files (thumbnailer, &files);
+ return thunar_thumbnailer_queue_files (thumbnailer, &files, request);
}
gboolean
thunar_thumbnailer_queue_files (ThunarThumbnailer *thumbnailer,
- GList *files)
+ GList *files,
+ guint *request)
{
+ gboolean success = FALSE;
#ifdef HAVE_DBUS
- ThunarThumbnailerItem *item;
-#endif
- gboolean success = FALSE;
-#ifdef HAVE_DBUS
- GList *lp;
- GList *supported_files = NULL;
+ const gchar **mime_hints;
+ gchar **uris;
+ GList *lp;
+ GList *supported_files = NULL;
+ guint n;
+ guint n_items;
#endif
_thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), FALSE);
@@ -1194,44 +808,49 @@ thunar_thumbnailer_queue_files (ThunarThumbnailer *thumbnailer,
* about to be queued (wait queue), nor already queued, nor already
* processed (and awaiting to be refreshed) */
for (lp = g_list_last (files); lp != NULL; lp = lp->prev)
- if (thunar_thumbnailer_file_is_supported (thumbnailer, lp->data))
- {
- if (!thunar_thumbnailer_file_is_in_wait_queue (thumbnailer, lp->data)
- && !thunar_thumbnailer_file_is_queued (thumbnailer, lp->data)
- && !thunar_thumbnailer_file_is_ready (thumbnailer, lp->data))
- {
- supported_files = g_list_prepend (supported_files, lp->data);
- }
- }
+ {
+ if (thunar_thumbnailer_file_is_supported (thumbnailer, lp->data))
+ supported_files = g_list_prepend (supported_files, lp->data);
+ }
+
+ /* determine how many URIs are in the wait queue */
+ n_items = g_list_length (supported_files);
/* check if we have any supported files */
- if (supported_files != NULL)
+ if (n_items > 0)
{
- for (lp = supported_files; lp != NULL; lp = lp->next)
- {
- g_mutex_lock (thumbnailer->lock);
-
- /* allocate a thumbnailer item for the wait queue */
- item = thunar_thumbnailer_item_new (thunar_file_get_file (lp->data),
- thunar_file_get_content_type (lp->data));
+ /* allocate arrays for URIs and mime hints */
+ uris = g_new0 (gchar *, n_items + 1);
+ mime_hints = g_new0 (const gchar *, n_items + 1);
- /* add the item to the wait queue */
- thumbnailer->wait_queue = g_list_prepend (thumbnailer->wait_queue, item);
+ /* fill URI and MIME hint arrays with items from the wait queue */
+ for (lp = g_list_last (supported_files), n = 0; lp != NULL; lp = lp->prev, ++n)
+ {
+ /* set the thumbnail state to loading */
+ thunar_file_set_thumb_state (lp->data, THUNAR_FILE_THUMB_STATE_LOADING);
- g_mutex_unlock (thumbnailer->lock);
+ /* save URI and MIME hint in the arrays */
+ uris[n] = thunar_file_dup_uri (lp->data);
+ mime_hints[n] = thunar_file_get_content_type (lp->data);
}
+ /* NULL-terminate both arrays */
+ uris[n] = NULL;
+ mime_hints[n] = NULL;
+
g_mutex_lock (thumbnailer->lock);
- if (thumbnailer->wait_queue_idle_id == 0)
- {
- thumbnailer->wait_queue_idle_id =
- g_timeout_add (100, (GSourceFunc) thunar_thumbnailer_process_wait_queue,
- thumbnailer);
- }
+ /* queue a thumbnail request for the URIs from the wait queue */
+ if (request != NULL)
+ *request = thunar_thumbnailer_queue_async (thumbnailer, uris, mime_hints);
+ else
+ thunar_thumbnailer_queue_async (thumbnailer, uris, mime_hints);
g_mutex_unlock (thumbnailer->lock);
-
+
+ /* free mime hints array */
+ g_free (mime_hints);
+
/* free the list of supported files */
g_list_free (supported_files);
@@ -1244,35 +863,42 @@ thunar_thumbnailer_queue_files (ThunarThumbnailer *thumbnailer,
}
-#if 0
-static void
-thunar_thumbnailer_unqueue (ThunarThumbnailer *thumbnailer,
- gpointer request)
+void
+thunar_thumbnailer_dequeue (ThunarThumbnailer *thumbnailer,
+ guint request)
{
#ifdef HAVE_DBUS
+ gpointer request_ptr;
gpointer handle;
#endif
_thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
#ifdef HAVE_DBUS
+ /* convert the number to a pointer */
+ request_ptr = GUINT_TO_POINTER (request);
+
/* acquire the thumbnailer lock */
g_mutex_lock (thumbnailer->lock);
+ /* check if we have a valid thumbnailer proxy */
if (thumbnailer->thumbnailer_proxy != NULL)
{
- handle = g_hash_table_lookup (thumbnailer->request_handle_mapping, request);
-
- thunar_thumbnailer_proxy_unqueue (thumbnailer->thumbnailer_proxy,
- GPOINTER_TO_UINT (handle), NULL);
+ /* check if there is a pending tumbler request handle for this request */
+ handle = g_hash_table_lookup (thumbnailer->request_handle_mapping, request_ptr);
+ if (GPOINTER_TO_UINT (handle) > 0)
+ {
+ /* Dequeue the request */
+ thunar_thumbnailer_proxy_dequeue (thumbnailer->thumbnailer_proxy,
+ GPOINTER_TO_UINT (handle), NULL);
- g_hash_table_remove (thumbnailer->handle_request_mapping, handle);
- g_hash_table_remove (thumbnailer->request_handle_mapping, request);
- g_hash_table_remove (thumbnailer->request_uris_mapping, request);
+ /* drop all the request information */
+ g_hash_table_remove (thumbnailer->handle_request_mapping, handle);
+ g_hash_table_remove (thumbnailer->request_handle_mapping, request_ptr);
+ }
}
/* release the thumbnailer lock */
g_mutex_unlock (thumbnailer->lock);
#endif
}
-#endif
diff --git a/thunar/thunar-thumbnailer.h b/thunar/thunar-thumbnailer.h
index 83fa4ce..81caf83 100644
--- a/thunar/thunar-thumbnailer.h
+++ b/thunar/thunar-thumbnailer.h
@@ -1,20 +1,21 @@
-/* $Id$ */
+/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
- * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-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 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 General Public License for
- * more details.
+ * 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 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
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifndef __THUNAR_THUMBNAILER_H__
@@ -22,7 +23,7 @@
#include <thunar/thunar-file.h>
-G_BEGIN_DECLS;
+G_BEGIN_DECLS
typedef struct _ThunarThumbnailerClass ThunarThumbnailerClass;
typedef struct _ThunarThumbnailer ThunarThumbnailer;
@@ -34,15 +35,19 @@ typedef struct _ThunarThumbnailer ThunarThumbnailer;
#define THUNAR_IS_THUMBNAILER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_THUMBNAILER))
#define THUNAR_THUMBNAILER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_THUMBNAILER, ThunarThumbnailerClass))
-GType thunar_thumbnailer_get_type (void) G_GNUC_CONST;
+GType thunar_thumbnailer_get_type (void) G_GNUC_CONST;
-ThunarThumbnailer *thunar_thumbnailer_new (void) G_GNUC_MALLOC;
+ThunarThumbnailer *thunar_thumbnailer_new (void) G_GNUC_MALLOC;
-gboolean thunar_thumbnailer_queue_file (ThunarThumbnailer *generator,
- ThunarFile *file);
-gboolean thunar_thumbnailer_queue_files (ThunarThumbnailer *generator,
- GList *files);
+gboolean thunar_thumbnailer_queue_file (ThunarThumbnailer *thumbnailer,
+ ThunarFile *file,
+ guint *request);
+gboolean thunar_thumbnailer_queue_files (ThunarThumbnailer *thumbnailer,
+ GList *files,
+ guint *request);
+void thunar_thumbnailer_dequeue (ThunarThumbnailer *thumbnailer,
+ guint request);
-G_END_DECLS;
+G_END_DECLS
#endif /* !__THUNAR_THUMBNAILER_H__ */
diff --git a/thunar/thunar-transfer-job.c b/thunar/thunar-transfer-job.c
index 364bd4e..f77839f 100644
--- a/thunar/thunar-transfer-job.c
+++ b/thunar/thunar-transfer-job.c
@@ -1,22 +1,22 @@
-/* vi:set sw=2 sts=2 ts=2 et ai: */
+/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
* Copyright (c) 2009-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 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
- * General Public License for more details.
+ * 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 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
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
@@ -25,11 +25,13 @@
#include <gio/gio.h>
+#include <thunar/thunar-application.h>
#include <thunar/thunar-gio-extensions.h>
#include <thunar/thunar-io-scan-directory.h>
#include <thunar/thunar-io-jobs-util.h>
#include <thunar/thunar-job.h>
#include <thunar/thunar-private.h>
+#include <thunar/thunar-thumbnail-cache.h>
#include <thunar/thunar-transfer-job.h>
@@ -481,11 +483,13 @@ thunar_transfer_job_copy_node (ThunarTransferJob *job,
GList **target_file_list_return,
GError **error)
{
- ThunarJobResponse response;
- GFileInfo *info;
- GError *err = NULL;
- GFile *real_target_file = NULL;
- gchar *base_name;
+ ThunarThumbnailCache *thumbnail_cache;
+ ThunarApplication *application;
+ ThunarJobResponse response;
+ GFileInfo *info;
+ GError *err = NULL;
+ GFile *real_target_file = NULL;
+ gchar *base_name;
_thunar_return_if_fail (THUNAR_IS_TRANSFER_JOB (job));
_thunar_return_if_fail (node != NULL && G_IS_FILE (node->source_file));
@@ -498,6 +502,11 @@ thunar_transfer_job_copy_node (ThunarTransferJob *job,
* wrt restoring files from the trash. Other transfer_nodes will be called with target_parent_file.
*/
+ /* take a reference on the thumbnail cache */
+ application = thunar_application_get ();
+ thumbnail_cache = thunar_application_get_thumbnail_cache (application);
+ g_object_unref (application);
+
for (; err == NULL && node != NULL; node = node->next)
{
/* guess the target file for this node (unless already provided) */
@@ -536,6 +545,11 @@ retry_copy:
/* node->source_file == real_target_file means to skip the file */
if (G_LIKELY (node->source_file != real_target_file))
{
+ /* notify the thumbnail cache of the copy operation */
+ thunar_thumbnail_cache_copy_file (thumbnail_cache,
+ node->source_file,
+ real_target_file);
+
/* check if we have children to copy */
if (node->children != NULL)
{
@@ -558,22 +572,37 @@ retry_copy:
/* add the real target file to the return list */
if (G_LIKELY (target_file_list_return != NULL))
- *target_file_list_return = thunar_g_file_list_prepend (*target_file_list_return, real_target_file);
+ {
+ *target_file_list_return =
+ thunar_g_file_list_prepend (*target_file_list_return,
+ real_target_file);
+ }
retry_remove:
/* try to remove the source directory if we are on copy+remove fallback for move */
- if (job->type == THUNAR_TRANSFER_JOB_MOVE &&
- !g_file_delete (node->source_file, exo_job_get_cancellable (EXO_JOB (job)), &err))
+ if (job->type == THUNAR_TRANSFER_JOB_MOVE)
{
- /* ask the user to retry */
- response = thunar_job_ask_skip (THUNAR_JOB (job), "%s", err->message);
+ if (g_file_delete (node->source_file,
+ exo_job_get_cancellable (EXO_JOB (job)),
+ &err))
+ {
+ /* notify the thumbnail cache of the delete operation */
+ thunar_thumbnail_cache_delete_file (thumbnail_cache,
+ node->source_file);
+ }
+ else
+ {
+ /* ask the user to retry */
+ response = thunar_job_ask_skip (THUNAR_JOB (job), "%s",
+ err->message);
- /* reset the error */
- g_clear_error (&err);
+ /* reset the error */
+ g_clear_error (&err);
- /* check whether to retry */
- if (G_UNLIKELY (response == THUNAR_JOB_RESPONSE_RETRY))
- goto retry_remove;
+ /* check whether to retry */
+ if (G_UNLIKELY (response == THUNAR_JOB_RESPONSE_RETRY))
+ goto retry_remove;
+ }
}
}
@@ -604,6 +633,9 @@ retry_remove:
g_object_unref (info);
}
+ /* release the thumbnail cache */
+ g_object_unref (thumbnail_cache);
+
/* propagate error if we failed or the job was cancelled */
if (G_UNLIKELY (err != NULL))
g_propagate_error (error, err);
@@ -614,20 +646,22 @@ static gboolean
thunar_transfer_job_execute (ExoJob *job,
GError **error)
{
- ThunarTransferNode *node;
- ThunarJobResponse response;
- ThunarTransferJob *transfer_job = THUNAR_TRANSFER_JOB (job);
- GFileInfo *info;
- gboolean parent_exists;
- GError *err = NULL;
- GList *new_files_list = NULL;
- GList *snext;
- GList *sp;
- GList *tnext;
- GList *tp;
- GFile *target_parent;
- gchar *base_name;
- gchar *parent_display_name;
+ ThunarThumbnailCache *thumbnail_cache;
+ ThunarTransferNode *node;
+ ThunarApplication *application;
+ ThunarJobResponse response;
+ ThunarTransferJob *transfer_job = THUNAR_TRANSFER_JOB (job);
+ GFileInfo *info;
+ gboolean parent_exists;
+ GError *err = NULL;
+ GList *new_files_list = NULL;
+ GList *snext;
+ GList *sp;
+ GList *tnext;
+ GList *tp;
+ GFile *target_parent;
+ gchar *base_name;
+ gchar *parent_display_name;
_thunar_return_val_if_fail (THUNAR_IS_TRANSFER_JOB (job), FALSE);
_thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
@@ -637,6 +671,11 @@ thunar_transfer_job_execute (ExoJob *job,
exo_job_info_message (job, _("Collecting files..."));
+ /* take a reference on the thumbnail cache */
+ application = thunar_application_get ();
+ thumbnail_cache = thunar_application_get_thumbnail_cache (application);
+ g_object_unref (application);
+
for (sp = transfer_job->source_node_list, tp = transfer_job->target_file_list;
sp != NULL && tp != NULL && err == NULL;
sp = snext, tp = tnext)
@@ -742,6 +781,11 @@ thunar_transfer_job_execute (ExoJob *job,
exo_job_get_cancellable (job),
NULL, NULL, &err))
{
+ /* notify the thumbnail cache of the move operation */
+ thunar_thumbnail_cache_move_file (thumbnail_cache,
+ node->source_file,
+ tp->data);
+
/* add the target file to the new files list */
new_files_list = thunar_g_file_list_prepend (new_files_list, tp->data);
@@ -779,6 +823,9 @@ thunar_transfer_job_execute (ExoJob *job,
g_object_unref (info);
}
+ /* release the thumbnail cache */
+ g_object_unref (thumbnail_cache);
+
/* continue if there were no errors yet */
if (G_LIKELY (err == NULL))
{
More information about the Xfce4-commits
mailing list