From 8962aad37871aa7ad76665b7f3c0605fed39a15c Mon Sep 17 00:00:00 2001 From: Nick Schermer <nick@xfce.org> Date: Sun, 28 Jul 2013 18:18:43 +0200 Subject: [PATCH] Improve handling of renames (bug #10242). Support move operating in gio better and don't show empty folders if renaming them from within Thunar. --- thunar/thunar-file.c | 99 +++++++++------ thunar/thunar-folder.c | 9 +- thunar/thunar-standard-view.c | 3 + thunar/thunar-thumbnail-cache.c | 216 ++++++++++++++++---------------- 4 files changed, 176 insertions(+), 151 deletions(-) diff --git a/thunar/thunar-file.c b/thunar/thunar-file.c index 580638e3e..dc3165429 100644 --- a/thunar/thunar-file.c +++ b/thunar/thunar-file.c @@ -108,6 +108,7 @@ static void thunar_file_monitor (GFileMonitor GFile *other_path, GFileMonitorEvent event_type, gpointer user_data); +static void thunar_file_watch_reconnect (ThunarFile *file); static gboolean thunar_file_load (ThunarFile *file, GCancellable *cancellable, GError **error); @@ -679,6 +680,49 @@ thunar_file_monitor_update (GFile *path, +static void +thunar_file_monitor_moved (ThunarFile *file, + GFile *renamed_file) +{ + ThunarApplication *application; + ThunarThumbnailCache *thumbnail_cache; + GFile *previous_file; + + /* ref the old location */ + previous_file = g_object_ref (G_OBJECT (file->gfile)); + + /* 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); + + /* set the new file */ + file->gfile = g_object_ref (G_OBJECT (renamed_file)); + + /* reload file information */ + thunar_file_load (file, NULL, NULL); + + /* need to re-register the monitor handle for the new uri */ + thunar_file_watch_reconnect (file); + + G_LOCK (file_cache_mutex); + + /* drop the previous entry from the cache */ + g_hash_table_remove (file_cache, previous_file); + + /* drop the reference on the previous file */ + g_object_unref (previous_file); + + /* insert the new entry */ + g_hash_table_insert (file_cache, g_object_ref (file->gfile), file); + + G_UNLOCK (file_cache_mutex); +} + + + static void thunar_file_monitor (GFileMonitor *monitor, GFile *path, @@ -691,9 +735,17 @@ thunar_file_monitor (GFileMonitor *monitor, _thunar_return_if_fail (G_IS_FILE_MONITOR (monitor)); _thunar_return_if_fail (THUNAR_IS_FILE (file)); - if (G_UNLIKELY (!G_IS_FILE (path) || !g_file_equal (path, file->gfile))) + if (G_UNLIKELY (!G_IS_FILE (path) + || !g_file_equal (path, file->gfile))) return; + if (event_type == G_FILE_MONITOR_EVENT_MOVED) + { + if (G_IS_FILE (other_path)) + thunar_file_monitor_moved (file, other_path); + return; + } + if (G_LIKELY (G_IS_FILE (path))) thunar_file_monitor_update (path, event_type); @@ -736,7 +788,7 @@ thunar_file_watch_reconnect (ThunarFile *file) } /* create a file or directory monitor */ - file_watch->monitor = g_file_monitor (file->gfile, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL); + file_watch->monitor = g_file_monitor (file->gfile, G_FILE_MONITOR_WATCH_MOUNTS | G_FILE_MONITOR_SEND_MOVED, NULL, NULL); if (G_LIKELY (file_watch->monitor != NULL)) { /* watch monitor for file changes */ @@ -1701,11 +1753,8 @@ thunar_file_rename (ThunarFile *file, gboolean called_from_job, GError **error) { - ThunarApplication *application; - ThunarThumbnailCache *thumbnail_cache; GKeyFile *key_file; GError *err = NULL; - GFile *previous_file; GFile *renamed_file; gboolean is_secure; const gchar * const *languages; @@ -1787,49 +1836,19 @@ thunar_file_rename (ThunarFile *file, } else { - /* remember the previous file */ - previous_file = g_object_ref (file->gfile); - /* 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) { - /* set the new file */ - file->gfile = renamed_file; - - /* reload file information */ - thunar_file_load (file, NULL, NULL); + /* notify the file is renamed */ + thunar_file_monitor_moved (file, renamed_file); - /* need to re-register the monitor handle for the new uri */ - thunar_file_watch_reconnect (file); - - G_LOCK (file_cache_mutex); - - /* drop the previous entry from the cache */ - g_hash_table_remove (file_cache, previous_file); - - /* drop the reference on the previous file */ - g_object_unref (previous_file); - - /* insert the new entry */ - g_hash_table_insert (file_cache, g_object_ref (file->gfile), file); - - G_UNLOCK (file_cache_mutex); + g_object_unref (G_OBJECT (renamed_file)); if (!called_from_job) { - /* tell the associated folder that the file was renamed */ - thunarx_file_info_renamed (THUNARX_FILE_INFO (file)); - /* emit the file changed signal */ thunar_file_changed (file); } @@ -1838,8 +1857,6 @@ thunar_file_rename (ThunarFile *file, } else { - g_object_unref (previous_file); - return FALSE; } } @@ -3680,7 +3697,7 @@ thunar_file_watch (ThunarFile *file) file_watch->watch_count = 1; /* create a file or directory monitor */ - file_watch->monitor = g_file_monitor (file->gfile, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL); + file_watch->monitor = g_file_monitor (file->gfile, G_FILE_MONITOR_WATCH_MOUNTS | G_FILE_MONITOR_SEND_MOVED, NULL, NULL); if (G_LIKELY (file_watch->monitor != NULL)) { /* watch monitor for file changes */ diff --git a/thunar/thunar-folder.c b/thunar/thunar-folder.c index 3a259bcc5..bc1dcdfdf 100644 --- a/thunar/thunar-folder.c +++ b/thunar/thunar-folder.c @@ -758,9 +758,14 @@ thunar_folder_monitor (GFileMonitor *monitor, { /* update/destroy the corresponding file */ if (event_type == G_FILE_MONITOR_EVENT_DELETED) - thunar_file_destroy (folder->corresponding_file); + { + if (!thunar_file_exists (folder->corresponding_file)) + thunar_file_destroy (folder->corresponding_file); + } else - thunar_file_reload (folder->corresponding_file); + { + thunar_file_reload (folder->corresponding_file); + } } } diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c index 9c2ed1b4a..6d5dd481a 100644 --- a/thunar/thunar-standard-view.c +++ b/thunar/thunar-standard-view.c @@ -2227,6 +2227,9 @@ thunar_standard_view_current_directory_changed (ThunarFile *current_dire /* update tab label and tooltip */ g_object_notify_by_pspec (G_OBJECT (standard_view), standard_view_props[PROP_DISPLAY_NAME]); g_object_notify_by_pspec (G_OBJECT (standard_view), standard_view_props[PROP_TOOLTIP_TEXT]); + + /* directory is possibly moved, schedule a thumbnail update */ + thunar_standard_view_schedule_thumbnail_timeout (standard_view); } diff --git a/thunar/thunar-thumbnail-cache.c b/thunar/thunar-thumbnail-cache.c index c7ff0c8fb..348ec53ee 100644 --- a/thunar/thunar-thumbnail-cache.c +++ b/thunar/thunar-thumbnail-cache.c @@ -2,18 +2,18 @@ /*- * Copyright (c) 2011 Jannis Pohlmann <jannis@xfce.org> * - * This program is free software; you can redistribute it and/or + * 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 + * 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 + * 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 + * 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. */ @@ -35,6 +35,7 @@ #include <thunar/thunar-private.h> #include <thunar/thunar-thumbnail-cache.h> +#include <thunar/thunar-file.h> #if GLIB_CHECK_VERSION (2, 32, 0) #define _thumbnail_cache_lock(cache) g_mutex_lock (&((cache)->lock)) @@ -61,7 +62,7 @@ struct _ThunarThumbnailCache #ifdef HAVE_DBUS DBusGProxy *cache_proxy; - + GList *move_source_queue; GList *move_target_queue; guint move_queue_idle_id; @@ -99,7 +100,7 @@ thunar_thumbnail_cache_class_init (ThunarThumbnailCacheClass *klass) thunar_thumbnail_cache_parent_class = g_type_class_peek_parent (klass); gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_thumbnail_cache_finalize; + gobject_class->finalize = thunar_thumbnail_cache_finalize; } @@ -189,11 +190,29 @@ thunar_thumbnail_cache_finalize (GObject *object) #ifdef HAVE_DBUS static void -thunar_thumbnail_cache_move_async_reply (DBusGProxy *proxy, - GError *error, - gpointer user_data) +thunar_thumbnail_cache_move_copy_async_reply (DBusGProxy *proxy, + GError *error, + gpointer user_data) { + GList *li; + ThunarFile *file; + _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy)); + + for (li = user_data; li != NULL; li = li->next) + { + file = thunar_file_cache_lookup (G_FILE (li->data)); + g_object_unref (G_OBJECT (li->data)); + + if (G_LIKELY (file != NULL)) + { + /* if visible, let the view know there might be a thumb */ + thunar_file_changed (file); + g_object_unref (file); + } + } + + g_list_free (user_data); } @@ -201,7 +220,8 @@ thunar_thumbnail_cache_move_async_reply (DBusGProxy *proxy, static void thunar_thumbnail_cache_move_async (ThunarThumbnailCache *cache, const gchar **source_uris, - const gchar **target_uris) + const gchar **target_uris, + gpointer user_data) { _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache)); _thunar_return_if_fail (source_uris != NULL); @@ -210,18 +230,8 @@ thunar_thumbnail_cache_move_async (ThunarThumbnailCache *cache, /* 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)); + thunar_thumbnail_cache_move_copy_async_reply, + user_data); } @@ -229,7 +239,8 @@ thunar_thumbnail_cache_copy_async_reply (DBusGProxy *proxy, static void thunar_thumbnail_cache_copy_async (ThunarThumbnailCache *cache, const gchar **source_uris, - const gchar **target_uris) + const gchar **target_uris, + gpointer user_data) { _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache)); _thunar_return_if_fail (source_uris != NULL); @@ -238,8 +249,8 @@ thunar_thumbnail_cache_copy_async (ThunarThumbnailCache *cache, /* 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); + thunar_thumbnail_cache_move_copy_async_reply, + user_data); } @@ -287,7 +298,7 @@ thunar_thumbnail_cache_cleanup_async (ThunarThumbnailCache *cache, _thunar_return_if_fail (base_uris != NULL); /* request a thumbnail cache update asynchronously */ - thunar_thumbnail_cache_proxy_cleanup_async (cache->cache_proxy, + thunar_thumbnail_cache_proxy_cleanup_async (cache->cache_proxy, (const gchar **)base_uris, 0, thunar_thumbnail_cache_cleanup_async_reply, NULL); @@ -296,7 +307,8 @@ thunar_thumbnail_cache_cleanup_async (ThunarThumbnailCache *cache, static gboolean -thunar_thumbnail_cache_process_move_queue (ThunarThumbnailCache *cache) +thunar_thumbnail_cache_process_queue (ThunarThumbnailCache *cache, + gboolean copy_async) { GList *sp; GList *tp; @@ -304,14 +316,32 @@ thunar_thumbnail_cache_process_move_queue (ThunarThumbnailCache *cache) gchar **target_uris; guint n_uris; guint n; + GList *source_queue; + GList *target_queue; _thunar_return_val_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache), FALSE); /* acquire a cache lock */ _thumbnail_cache_lock (cache); - + + /* steal the lists */ + if (copy_async) + { + source_queue = cache->copy_source_queue; + cache->copy_source_queue = NULL; + target_queue = cache->copy_target_queue; + cache->copy_target_queue = NULL; + } + else + { + source_queue = cache->move_source_queue; + cache->move_source_queue = NULL; + target_queue = cache->move_target_queue; + cache->move_target_queue = NULL; + } + /* compute how many URIs there are */ - n_uris = g_list_length (cache->move_source_queue); + n_uris = g_list_length (source_queue); /* allocate a string array for the URIs */ source_uris = g_new0 (gchar *, n_uris + 1); @@ -319,40 +349,45 @@ thunar_thumbnail_cache_process_move_queue (ThunarThumbnailCache *cache) /* 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 = g_list_last (source_queue), + tp = g_list_last (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 */ + /* release the source object */ 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); + if (copy_async) + { + /* asynchronously copy the thumbnails */ + thunar_thumbnail_cache_copy_async (cache, + (const gchar **)source_uris, + (const gchar **)target_uris, + target_queue); + } + else + { + /* asynchronously move the thumbnails */ + thunar_thumbnail_cache_move_async (cache, + (const gchar **)source_uris, + (const gchar **)target_uris, + target_queue); + } /* free the URI arrays */ g_strfreev (source_uris); g_strfreev (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; + g_list_free (source_queue); /* release the cache lock */ _thumbnail_cache_unlock (cache); @@ -363,68 +398,33 @@ thunar_thumbnail_cache_process_move_queue (ThunarThumbnailCache *cache) static gboolean -thunar_thumbnail_cache_process_copy_queue (ThunarThumbnailCache *cache) +thunar_thumbnail_cache_process_move_queue (gpointer user_data) { - 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 */ - _thumbnail_cache_lock (cache); - - /* 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); + return thunar_thumbnail_cache_process_queue (user_data, FALSE); +} - /* 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; +static void +thunar_thumbnail_cache_process_move_queue_destroy (gpointer user_data) +{ + THUNAR_THUMBNAIL_CACHE (user_data)->move_queue_idle_id = 0; +} - /* asynchronously copy the thumbnails */ - thunar_thumbnail_cache_copy_async (cache, - (const gchar **)source_uris, - (const gchar **)target_uris); - /* free the URI arrays */ - g_strfreev (source_uris); - g_strfreev (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; +static gboolean +thunar_thumbnail_cache_process_copy_queue (gpointer user_data) +{ + return thunar_thumbnail_cache_process_queue (user_data, TRUE); +} - /* reset the copy queue idle ID */ - cache->copy_queue_idle_id = 0; - /* release the cache lock */ - _thumbnail_cache_unlock (cache); - return FALSE; +static void +thunar_thumbnail_cache_process_copy_queue_destroy (gpointer user_data) +{ + THUNAR_THUMBNAIL_CACHE (user_data)->copy_queue_idle_id = 0; } @@ -441,7 +441,7 @@ thunar_thumbnail_cache_process_delete_queue (ThunarThumbnailCache *cache) /* acquire a cache lock */ _thumbnail_cache_lock (cache); - + /* compute how many URIs there are */ n_uris = g_list_length (cache->delete_queue); @@ -493,7 +493,7 @@ thunar_thumbnail_cache_process_cleanup_queue (ThunarThumbnailCache *cache) /* acquire a cache lock */ _thumbnail_cache_lock (cache); - + /* compute how many URIs there are */ n_uris = g_list_length (cache->cleanup_queue); @@ -574,15 +574,15 @@ thunar_thumbnail_cache_move_file (ThunarThumbnailCache *cache, } /* add the files to the move queue */ - cache->move_source_queue = g_list_prepend (cache->move_source_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); + g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 250, thunar_thumbnail_cache_process_move_queue, + cache, thunar_thumbnail_cache_process_move_queue_destroy); } /* release the cache lock */ @@ -616,15 +616,15 @@ thunar_thumbnail_cache_copy_file (ThunarThumbnailCache *cache, } /* add the files to the copy queues */ - cache->copy_source_queue = g_list_prepend (cache->copy_source_queue, + 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); + g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 500, thunar_thumbnail_cache_process_copy_queue, + cache, thunar_thumbnail_cache_process_copy_queue_destroy); } /* release the cache lock */ @@ -659,8 +659,8 @@ thunar_thumbnail_cache_delete_file (ThunarThumbnailCache *cache, 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->delete_queue_idle_id = + g_timeout_add (500, (GSourceFunc) thunar_thumbnail_cache_process_delete_queue, cache); } -- GitLab