[nautilus/recent-manager-update: 2/5] file-utilities: Add function to update manager on file rename or move



commit ebaee6460519398258d31fd76bf2192c4895baa0
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Thu Apr 12 12:21:50 2018 -0500

    file-utilities: Add function to update manager on file rename or move
    
    Until now when we move o rename a file we don't update the recent files manager.
    Being recent files something used across various components (and exposed to
    the file picker), it's quite useful to keep this database updated.
    However these components can't be aware of file changes, while nautilus is, and
    then it's our job to keep the recent manager in sync with the filesystem.
    
    When the modified file is a directory (and in order to verify that it could be
    needed to fetch the file infos), we need to go through all the saved recent
    files and update the paths of all the matching descendants.
    
    If instead we move a file, we can just update the GtkRecentInfo; however
    in case the file display name has changed too (happening basically always on
    renames), due to a limitation of GtkRecentInfo APIs, we need instead to copy
    the current info item and recreate a new one copying the relevant fields, and
    updating the ones which have changed (uri and display name).

 src/nautilus-file-utilities.c | 132 ++++++++++++++++++++++++++++++++++++++++++
 src/nautilus-file-utilities.h |   5 ++
 2 files changed, 137 insertions(+)
---
diff --git a/src/nautilus-file-utilities.c b/src/nautilus-file-utilities.c
index f8afabbfe..0b8d22b17 100644
--- a/src/nautilus-file-utilities.c
+++ b/src/nautilus-file-utilities.c
@@ -28,6 +28,7 @@
 #include "nautilus-metadata.h"
 #include "nautilus-file.h"
 #include "nautilus-file-operations.h"
+#include "nautilus-file-private.h"
 #include "nautilus-search-directory.h"
 #include "nautilus-starred-directory.h"
 #include "nautilus-ui-utilities.h"
@@ -1508,3 +1509,134 @@ nautilus_file_system_is_remote (const char *file_system)
 
     return file_system != NULL && g_strv_contains (remote_types, file_system);
 }
+
+void
+nautilus_file_moved_update_recent (const gchar *old_uri,
+                                   const gchar *new_uri,
+                                   const gchar *old_display_name,
+                                   const gchar *new_display_name)
+{
+    GtkRecentManager *recent_manager = gtk_recent_manager_get_default ();
+    g_autoptr (NautilusFile) file = NULL;
+    NautilusFile *existing_file;
+
+    if (new_uri == NULL || old_uri == NULL ||
+        (g_strcmp0 (old_uri, new_uri) == 0 &&
+         g_strcmp0 (old_display_name, new_display_name) == 0))
+    {
+        return;
+    }
+
+    existing_file = nautilus_file_get_existing_by_uri (new_uri);
+
+    if (existing_file)
+    {
+        file = g_object_ref (existing_file);
+    }
+    else
+    {
+        g_autoptr (GFile) location = g_file_new_for_uri (new_uri);
+        g_autoptr (GFileInfo) file_info = NULL;
+
+        file_info = g_file_query_info (location,
+                                       NAUTILUS_FILE_DEFAULT_ATTRIBUTES,
+                                       0, NULL, NULL);
+        if (file_info == NULL)
+        {
+            return;
+        }
+
+        file = nautilus_file_get (location);
+        nautilus_file_update_info (file, file_info);
+    }
+
+    if (nautilus_file_is_directory (file))
+    {
+        g_autoptr (GFile) location = NULL;
+        GList *recent_items;
+        GList *l;
+
+        location = g_file_new_for_uri (old_uri);
+        recent_items = gtk_recent_manager_get_items (recent_manager);
+
+        for (l = recent_items; l; l = l->next)
+        {
+            GtkRecentInfo *info = l->data;
+            const gchar *item_uri = gtk_recent_info_get_uri (info);
+
+            if (g_str_has_prefix (item_uri, old_uri))
+            {
+                g_autoptr (GFile) item_file = NULL;
+                g_autofree gchar *relative_path = NULL;
+                g_autofree gchar *new_item_uri = NULL;
+
+                item_file = g_file_new_for_uri (item_uri);
+                relative_path = g_file_get_relative_path (location, item_file);
+                new_item_uri = g_build_filename (new_uri, relative_path, NULL);
+
+                gtk_recent_manager_move_item (recent_manager,
+                                              item_uri, new_item_uri, NULL);
+            }
+        }
+
+        g_list_free_full (recent_items, (GDestroyNotify) gtk_recent_info_unref);
+    }
+    else
+    {
+        GtkRecentInfo *old_recent;
+
+        old_recent = gtk_recent_manager_lookup_item (recent_manager,
+                                                     old_uri, NULL);
+        if (old_recent)
+        {
+            gboolean recreated = FALSE;
+
+            if ((new_display_name != NULL && old_display_name == NULL) ||
+                (g_strcmp0 (old_display_name, new_display_name) != 0 &&
+                 g_strcmp0 (old_display_name,
+                            gtk_recent_info_get_display_name (old_recent)) == 0))
+            {
+                /* If old display name, matches the one in the recent file
+                 * We can't just move it, but we need to recreate the
+                 * GtkRecentInfo
+                 */
+                GtkRecentData recent_data =
+                {
+                    .display_name = (gchar *) new_display_name,
+                    .description = (gchar *) gtk_recent_info_get_description (old_recent),
+                    .mime_type = (gchar *) gtk_recent_info_get_mime_type (old_recent),
+                    .app_name = gtk_recent_info_last_application (old_recent),
+                    .groups = gtk_recent_info_get_groups (old_recent, NULL),
+                    .is_private = gtk_recent_info_get_private_hint (old_recent),
+                };
+
+                if (recent_data.app_name)
+                {
+                    gtk_recent_info_get_application_info (old_recent,
+                                                          recent_data.app_name,
+                                                          (const gchar **) &(recent_data.app_exec),
+                                                          NULL, NULL);
+                }
+
+                if (gtk_recent_manager_add_full (recent_manager,
+                                                 new_uri,
+                                                 &recent_data))
+                {
+                    recreated = gtk_recent_manager_remove_item (recent_manager,
+                                                                old_uri,
+                                                                NULL);
+                }
+            }
+
+            if (!recreated)
+            {
+                gtk_recent_manager_move_item (recent_manager,
+                                              old_uri, new_uri, NULL);
+            }
+        }
+        else
+        {
+            gtk_recent_manager_remove_item (recent_manager, old_uri, NULL);
+        }
+    }
+}
diff --git a/src/nautilus-file-utilities.h b/src/nautilus-file-utilities.h
index 22d851c1b..386ae4aec 100644
--- a/src/nautilus-file-utilities.h
+++ b/src/nautilus-file-utilities.h
@@ -143,3 +143,8 @@ NautilusQueryRecursive location_settings_search_get_recursive (void);
 NautilusQueryRecursive location_settings_search_get_recursive_for_location (GFile *location);
 
 gboolean nautilus_file_system_is_remote (const char *file_system);
+
+void nautilus_file_moved_update_recent (const char *old_uri,
+                                        const char *new_uri,
+                                        const char *old_display_name,
+                                        const char *new_dispaly_name);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]