[gnome-photos/wip/rishi/unbreak-delete: 6/6] Unbreak deletion of items from the Tracker database




commit cbb73139bd3153d796c55a05ac1577f5ab512589
Author: Debarshi Ray <debarshir gnome org>
Date:   Sun Mar 14 12:14:38 2021 +0100

    Unbreak deletion of items from the Tracker database
    
    Tracker 3 enforces a clear separation between metadata stored in the
    application's private database and the filesystem miner's global
    database. The application is only permitted to delete metadata from its
    private database.
    
    Therefore, a "DELETE ..." SPARQL update is only used for collections,
    which are stored in the application's private database. For other
    items, the underlying file is trashed and the application relies on
    the filesystem miner to react to it.
    
    As a nice side-effect, the PhotosBaseItem::trash virtual method has now
    been converted into an asynchronous API.
    
    Fallout from bd087d67f938c29776842afbc3b7bc745d2ca9a2
    
    https://gitlab.gnome.org/GNOME/gnome-photos/-/merge_requests/175

 src/photos-base-item.c     | 23 +++++------
 src/photos-base-item.h     |  6 ++-
 src/photos-device-item.c   |  5 ++-
 src/photos-local-item.c    | 95 +++++++++++++++++++++++++++++++++++++---------
 src/photos-query-builder.c |  9 ++++-
 5 files changed, 104 insertions(+), 34 deletions(-)
---
diff --git a/src/photos-base-item.c b/src/photos-base-item.c
index 6ccde753..8673eed4 100644
--- a/src/photos-base-item.c
+++ b/src/photos-base-item.c
@@ -2743,16 +2743,16 @@ photos_base_item_save_to_stream_load (GObject *source_object, GAsyncResult *res,
 
 
 static void
-photos_base_item_trash_executed (GObject *source_object, GAsyncResult *res, gpointer user_data)
+photos_base_item_trash_trash (GObject *source_object, GAsyncResult *res, gpointer user_data)
 {
+  PhotosBaseItem *self = PHOTOS_BASE_ITEM (source_object);
   GApplication *app;
   g_autoptr (GTask) task = G_TASK (user_data);
-  PhotosDeleteItemJob *job = PHOTOS_DELETE_ITEM_JOB (source_object);
 
   {
     g_autoptr (GError) error = NULL;
 
-    if (!photos_delete_item_job_finish (job, res, &error))
+    if (!PHOTOS_BASE_ITEM_GET_CLASS (self)->trash_finish (self, res, &error))
       {
         g_task_return_error (task, g_steal_pointer (&error));
         goto out;
@@ -3264,7 +3264,7 @@ gboolean
 photos_base_item_can_trash (PhotosBaseItem *self)
 {
   g_return_val_if_fail (PHOTOS_IS_BASE_ITEM (self), FALSE);
-  return PHOTOS_BASE_ITEM_GET_CLASS (self)->trash != NULL;
+  return PHOTOS_BASE_ITEM_GET_CLASS (self)->trash_async != NULL;
 }
 
 
@@ -4758,24 +4758,21 @@ photos_base_item_trash_async (PhotosBaseItem *self,
                               GAsyncReadyCallback callback,
                               gpointer user_data)
 {
-  PhotosBaseItemPrivate *priv;
   GApplication *app;
   g_autoptr (GTask) task = NULL;
-  g_autoptr (PhotosDeleteItemJob) job = NULL;
 
   g_return_if_fail (PHOTOS_IS_BASE_ITEM (self));
-  priv = photos_base_item_get_instance_private (self);
+
+  app = g_application_get_default ();
 
   task = g_task_new (self, cancellable, callback, user_data);
   g_task_set_source_tag (task, photos_base_item_trash_async);
 
-  PHOTOS_BASE_ITEM_GET_CLASS (self)->trash (self);
-
-  app = g_application_get_default ();
-  job = photos_delete_item_job_new (priv->id);
-
   g_application_hold (app);
-  photos_delete_item_job_run (job, cancellable, photos_base_item_trash_executed, g_object_ref (task));
+  PHOTOS_BASE_ITEM_GET_CLASS (self)->trash_async (self,
+                                                  cancellable,
+                                                  photos_base_item_trash_trash,
+                                                  g_object_ref (task));
 }
 
 
diff --git a/src/photos-base-item.h b/src/photos-base-item.h
index 20f971ce..1d18410c 100644
--- a/src/photos-base-item.h
+++ b/src/photos-base-item.h
@@ -71,7 +71,11 @@ struct _PhotosBaseItemClass
   void        (*open)                       (PhotosBaseItem *self, GtkWindow *parent, guint32 timestamp);
   void        (*refresh_icon)               (PhotosBaseItem *self);
   void        (*set_favorite)               (PhotosBaseItem *self, gboolean favorite);
-  void        (*trash)                      (PhotosBaseItem *self);
+  void        (*trash_async)                (PhotosBaseItem *self,
+                                             GCancellable *cancellable,
+                                             GAsyncReadyCallback callback,
+                                             gpointer user_data);
+  gboolean    (*trash_finish)               (PhotosBaseItem *self, GAsyncResult *res, GError **error);
   void        (*update_type_description)    (PhotosBaseItem *self);
 
   /* signals */
diff --git a/src/photos-device-item.c b/src/photos-device-item.c
index 275900a9..3b476d51 100644
--- a/src/photos-device-item.c
+++ b/src/photos-device-item.c
@@ -382,7 +382,10 @@ photos_device_item_refresh_icon (PhotosBaseItem *item)
 
 
 static void
-photos_device_item_trash (PhotosBaseItem *item)
+photos_device_item_trash_async (PhotosBaseItem *item,
+                                GCancellable *cancellable,
+                                GAsyncReadyCallback callback,
+                                gpointer user_data)
 {
   g_assert_not_reached ();
 }
diff --git a/src/photos-local-item.c b/src/photos-local-item.c
index 2d130634..a6e1c193 100644
--- a/src/photos-local-item.c
+++ b/src/photos-local-item.c
@@ -381,41 +381,101 @@ photos_local_item_metadata_add_shared (PhotosBaseItem  *item,
 
 
 static void
-photos_local_item_trash_finish (GObject *source_object, GAsyncResult *res, gpointer user_data)
+photos_local_item_trash_executed (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  g_autoptr (GTask) task = G_TASK (user_data);
+  PhotosDeleteItemJob *job = PHOTOS_DELETE_ITEM_JOB (source_object);
+
+  {
+    g_autoptr (GError) error = NULL;
+
+    if (!photos_delete_item_job_finish (job, res, &error))
+      {
+        g_task_return_error (task, g_steal_pointer (&error));
+        goto out;
+      }
+  }
+
+  g_task_return_boolean (task, TRUE);
+
+ out:
+  return;
+}
+
+
+static void
+photos_local_item_trash_trash (GObject *source_object, GAsyncResult *res, gpointer user_data)
 {
   GFile *file = G_FILE (source_object);
+  g_autoptr (GTask) task = G_TASK (user_data);
 
   {
     g_autoptr (GError) error = NULL;
 
     if (!g_file_trash_finish (file, res, &error))
       {
-        if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-          {
-            PhotosLocalItem *self = PHOTOS_LOCAL_ITEM (user_data);
-            const gchar *uri;
-
-            uri = photos_base_item_get_uri (PHOTOS_BASE_ITEM (self));
-            g_warning ("Unable to trash %s: %s", uri, error->message);
-          }
+        g_task_return_error (task, g_steal_pointer (&error));
+        goto out;
       }
   }
+
+  g_task_return_boolean (task, TRUE);
+
+ out:
+  return;
 }
 
 
 static void
-photos_local_item_trash (PhotosBaseItem *item)
+photos_local_item_trash_async (PhotosBaseItem *item,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
 {
-  g_autoptr (GFile) file = NULL;
-  const gchar *uri;
   PhotosLocalItem *self = PHOTOS_LOCAL_ITEM (item);
+  g_autoptr (GTask) task = NULL;
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, photos_local_item_trash_async);
 
   if (photos_base_item_is_collection (item))
-    return;
+    {
+      g_autoptr (PhotosDeleteItemJob) job = NULL;
+      const gchar *id;
 
-  uri = photos_base_item_get_uri (item);
-  file = g_file_new_for_uri (uri);
-  g_file_trash_async (file, G_PRIORITY_DEFAULT, self->cancellable, photos_local_item_trash_finish, self);
+      id = photos_filterable_get_id (PHOTOS_FILTERABLE (self));
+      job = photos_delete_item_job_new (id);
+      photos_delete_item_job_run (job, cancellable, photo_local_item_trash_executed, g_object_ref (task));
+    }
+  else
+    {
+      g_autoptr (GFile) file = NULL;
+      const gchar *uri;
+
+      uri = photos_base_item_get_uri (item);
+      file = g_file_new_for_uri (uri);
+      g_file_trash_async (file,
+                          G_PRIORITY_DEFAULT,
+                          cancellable,
+                          photos_local_item_trash_trash,
+                          g_object_ref (task));
+    }
+}
+
+
+static gboolean
+photos_local_item_trash_finish (PhotosBaseItem *item, GAsyncResult *res, GError **error)
+{
+  PhotosLocalItem *self = PHOTOS_LOCAL_ITEM (item);
+  GTask *task;
+
+  g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+  task = G_TASK (res);
+
+  g_return_val_if_fail (g_task_get_source_tag (task) == photos_local_item_trash_async, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  return g_task_propagate_boolean (task, error);
 }
 
 
@@ -477,5 +537,6 @@ photos_local_item_class_init (PhotosLocalItemClass *class)
   base_item_class->download = photos_local_item_download;
   base_item_class->get_source_widget = photos_local_item_get_source_widget;
   base_item_class->metadata_add_shared = photos_local_item_metadata_add_shared;
-  base_item_class->trash = photos_local_item_trash;
+  base_item_class->trash_async = photos_local_item_trash_async;
+  base_item_class->trash_finish = photos_local_item_trash_finish;
 }
diff --git a/src/photos-query-builder.c b/src/photos-query-builder.c
index c7249ba6..85df12cb 100644
--- a/src/photos-query-builder.c
+++ b/src/photos-query-builder.c
@@ -321,9 +321,14 @@ photos_query_builder_delete_resource_query (PhotosSearchContextState *state, con
   PhotosQuery *query;
   g_autofree gchar *sparql = NULL;
 
-  sparql = g_strdup_printf ("DELETE { <%s> a rdfs:Resource }", resource);
-  query = photos_query_new (state, sparql);
+  sparql = g_strdup_printf ("DELETE DATA {"
+                            "  GRAPH tracker:Pictures {"
+                            "    <%s> a rdfs:Resource"
+                            "  }"
+                            "}",
+                            resource);
 
+  query = photos_query_new (state, sparql);
   return query;
 }
 


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