[nautilus/wip/antoniof/update-starred-uris: 2/2] tag-manager: Update starred URIs on move & rename




commit 9f2abc04cbe93274da96929bad0519ec899782fe
Author: António Fernandes <antoniof gnome org>
Date:   Wed Sep 9 23:32:01 2020 +0100

    tag-manager: Update starred URIs on move & rename
    
    We don't rely on tracker-miner-fs's rename tracking for starred files
    anymore, as explained in 29105fc9f6abf2eca6f986104763d21b9f22f0fb.
    
    However, losing track of starred files, when they or their containing
    folders are renamed or moved, is a major regression for this feature.
    
    The common case is that the operation is performed using this very app,
    so, we can largely restore the feature by updating URI on every rename
    and move operation we perform.
    
    Additionally, this allows us to finally close https://gitlab.gnome.org/GNOME/nautilus/-/issues/161 and 
https://gitlab.gnome.org/GNOME/nautilus/-/issues/169

 src/nautilus-file-operations.c |  11 ++++
 src/nautilus-file.c            |  13 ++++-
 src/nautilus-tag-manager.c     | 130 +++++++++++++++++++++++++++++++++++++++++
 src/nautilus-tag-manager.h     |   3 +
 4 files changed, 155 insertions(+), 2 deletions(-)
---
diff --git a/src/nautilus-file-operations.c b/src/nautilus-file-operations.c
index c61c3d9ef..3aebfb6e6 100644
--- a/src/nautilus-file-operations.c
+++ b/src/nautilus-file-operations.c
@@ -59,6 +59,7 @@
 #include "nautilus-file-utilities.h"
 #include "nautilus-file-undo-operations.h"
 #include "nautilus-file-undo-manager.h"
+#include "nautilus-tag-manager.h"
 #include "nautilus-ui-utilities.h"
 
 #ifdef GDK_WINDOWING_X11
@@ -5451,6 +5452,13 @@ retry:
                                                                 src, dest);
         }
 
+        if (copy_job->is_move)
+        {
+            g_autoptr (NautilusTagManager) tag_manager = nautilus_tag_manager_get ();
+
+            nautilus_tag_manager_update_moved_uris (tag_manager, src, dest);
+        }
+
         g_object_unref (dest);
         return;
     }
@@ -6159,12 +6167,15 @@ retry:
                      NULL,
                      &error))
     {
+        g_autoptr (NautilusTagManager) tag_manager = nautilus_tag_manager_get ();
+
         if (debuting_files)
         {
             g_hash_table_replace (debuting_files, g_object_ref (dest), GINT_TO_POINTER (TRUE));
         }
 
         nautilus_file_changes_queue_file_moved (src, dest);
+        nautilus_tag_manager_update_moved_uris (tag_manager, src, dest);
 
         dest_uri = g_file_get_uri (dest);
 
diff --git a/src/nautilus-file.c b/src/nautilus-file.c
index ff902db12..572183f97 100644
--- a/src/nautilus-file.c
+++ b/src/nautilus-file.c
@@ -1853,6 +1853,10 @@ rename_get_info_callback (GObject      *source_object,
     new_info = g_file_query_info_finish (G_FILE (source_object), res, &error);
     if (new_info != NULL)
     {
+        g_autoptr (NautilusTagManager) tag_manager = nautilus_tag_manager_get ();
+        g_autoptr (GFile) old_location = NULL;
+        g_autoptr (GFile) new_location = NULL;
+
         directory = op->file->details->directory;
 
         new_name = g_file_info_get_name (new_info);
@@ -1868,12 +1872,17 @@ rename_get_info_callback (GObject      *source_object,
             nautilus_file_changed (existing_file);
         }
 
-        old_uri = nautilus_file_get_uri (op->file);
+        old_location = nautilus_file_get_location (op->file);
+        old_uri = g_file_get_uri (old_location);
 
         update_info_and_name (op->file, new_info);
 
-        new_uri = nautilus_file_get_uri (op->file);
+        new_location = nautilus_file_get_location (op->file);
+        new_uri = g_file_get_uri (new_location);
+
         nautilus_directory_moved (old_uri, new_uri);
+        nautilus_tag_manager_update_moved_uris (tag_manager, old_location, new_location);
+
         g_free (new_uri);
         g_free (old_uri);
 
diff --git a/src/nautilus-tag-manager.c b/src/nautilus-tag-manager.c
index fbd8571e5..15dd634e5 100644
--- a/src/nautilus-tag-manager.c
+++ b/src/nautilus-tag-manager.c
@@ -700,6 +700,136 @@ nautilus_tag_manager_can_star_contents (NautilusTagManager *tag_manager,
     return g_file_has_prefix (directory, tag_manager->home) || g_file_equal (directory, tag_manager->home);
 }
 
+static void
+update_moved_uris_callback (GObject      *object,
+                            GAsyncResult *result,
+                            gpointer      user_data)
+{
+    g_autoptr (GError) error = NULL;
+    g_autoptr (GPtrArray) new_uris = user_data;
+
+    tracker_sparql_connection_update_finish (TRACKER_SPARQL_CONNECTION (object),
+                                             result,
+                                             &error);
+
+    if (error != NULL && error->code != G_IO_ERROR_CANCELLED)
+    {
+        g_warning ("Error updating moved uris: %s", error->message);
+    }
+    else
+    {
+        g_autolist (NautilusFile) updated_files = NULL;
+        g_autoptr (NautilusTagManager) tag_manager = NULL;
+
+        for (guint i = 0; i < new_uris->len; i++)
+        {
+            gchar *new_uri = g_ptr_array_index (new_uris, i);
+
+            updated_files = g_list_prepend (updated_files, nautilus_file_get_by_uri (new_uri));
+        }
+
+        tag_manager = nautilus_tag_manager_get ();
+        g_signal_emit_by_name (tag_manager, "starred-changed", updated_files);
+    }
+}
+
+/**
+ * nautilus_tag_manager_update_moved_uris:
+ * @self: The tag manager singleton
+ * @src: The original location as a #GFile
+ * @dest: The new location as a #GFile
+ *
+ * Checks whether the rename/move operation (@src to @dest) has modified
+ * the URIs of any starred files, and updates the database accordingly.
+ */
+void
+nautilus_tag_manager_update_moved_uris (NautilusTagManager *self,
+                                        GFile              *src,
+                                        GFile              *dest)
+{
+    GHashTableIter starred_iter;
+    gchar *starred_uri;
+    g_autoptr (GString) query = NULL;
+    g_autoptr (GPtrArray) old_uris = NULL;
+    g_autoptr (GPtrArray) new_uris = NULL;
+
+    if (!self->database_ok)
+    {
+        g_message ("nautilus-tag-manager: No Tracker connection");
+        return;
+    }
+
+    old_uris = g_ptr_array_new ();
+    new_uris = g_ptr_array_new_with_free_func (g_free);
+
+    g_hash_table_iter_init (&starred_iter, self->starred_file_uris);
+    while (g_hash_table_iter_next (&starred_iter, (gpointer *) &starred_uri, NULL))
+    {
+        g_autoptr (GFile) starred_location = NULL;
+        g_autofree gchar *relative_path = NULL;
+
+        starred_location = g_file_new_for_uri (starred_uri);
+
+        if (g_file_equal (starred_location, src))
+        {
+            /* The moved file/folder is starred */
+            g_ptr_array_add (old_uris, starred_uri);
+            g_ptr_array_add (new_uris, g_file_get_uri (dest));
+            continue;
+        }
+
+        relative_path = g_file_get_relative_path (src, starred_location);
+        if (relative_path != NULL)
+        {
+            /* The starred file/folder is descendant of the moved/renamed directory */
+            g_autoptr (GFile) new_location = NULL;
+
+            new_location = g_file_resolve_relative_path (dest, relative_path);
+
+            g_ptr_array_add (old_uris, starred_uri);
+            g_ptr_array_add (new_uris, g_file_get_uri (new_location));
+        }
+    }
+
+    if (new_uris->len == 0)
+    {
+        /* No starred files are affected by this move/rename */
+        return;
+    }
+
+    DEBUG ("Updating moved URI for %i starred files", new_uris->len);
+
+    query = g_string_new ("DELETE DATA {");
+
+    for (guint i = 0; i < old_uris->len; i++)
+    {
+        gchar *old_uri = g_ptr_array_index (old_uris, i);
+        g_string_append_printf (query,
+                                "    <%s> a nautilus:File ; "
+                                "        nautilus:starred true . ",
+                                old_uri);
+    }
+
+    g_string_append (query, "} ; INSERT DATA {");
+
+    for (guint i = 0; i < new_uris->len; i++)
+    {
+        gchar *new_uri = g_ptr_array_index (new_uris, i);
+        g_string_append_printf (query,
+                                "    <%s> a nautilus:File ; "
+                                "        nautilus:starred true . ",
+                                new_uri);
+    }
+
+    g_string_append (query, "}");
+
+    tracker_sparql_connection_update_async (self->db,
+                                            query->str,
+                                            self->cancellable,
+                                            update_moved_uris_callback,
+                                            g_steal_pointer (&new_uris));
+}
+
 static void
 process_tracker2_data_cb (GObject      *source_object,
                           GAsyncResult *res,
diff --git a/src/nautilus-tag-manager.h b/src/nautilus-tag-manager.h
index 2e926ae75..1ba8a48dd 100644
--- a/src/nautilus-tag-manager.h
+++ b/src/nautilus-tag-manager.h
@@ -53,6 +53,9 @@ gboolean            nautilus_tag_manager_file_is_starred   (NautilusTagManager *
 
 gboolean            nautilus_tag_manager_can_star_contents (NautilusTagManager *self,
                                                             GFile              *directory);
+void                nautilus_tag_manager_update_moved_uris  (NautilusTagManager *tag_manager,
+                                                             GFile              *src,
+                                                             GFile              *dest);
 
 void                nautilus_tag_manager_maybe_migrate_tracker2_data (NautilusTagManager *self);
 


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