[gnome-photos/wip/rishi/collection: 3/10] utils: Add photos_utils_copy_files_async



commit 66566acc48cfc7f65975210a2fd69198a7af768c
Author: Debarshi Ray <debarshir gnome org>
Date:   Sun Feb 4 20:38:00 2018 +0100

    utils: Add photos_utils_copy_files_async
    
    It's meant to copy a list of source GFiles to a destination directory
    and handle name collisions in the process. A subsequent commit will use
    this to copy files while importing content from attached devices.
    
    https://gitlab.gnome.org/GNOME/gnome-photos/issues/29

 src/photos-utils.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/photos-utils.h |  13 ++++
 2 files changed, 199 insertions(+)
---
diff --git a/src/photos-utils.c b/src/photos-utils.c
index 9f333e8b..25adde86 100644
--- a/src/photos-utils.c
+++ b/src/photos-utils.c
@@ -40,6 +40,7 @@
 #include "photos-facebook-item.h"
 #include "photos-flickr-item.h"
 #include "photos-gegl.h"
+#include "photos-glib.h"
 #include "photos-google-item.h"
 #include "photos-local-item.h"
 #include "photos-media-server-item.h"
@@ -71,6 +72,18 @@
 #include "photos-utils.h"
 
 
+typedef struct _PhotosUtilsCopyFilesData PhotosUtilsCopyFilesData;
+
+struct _PhotosUtilsCopyFilesData
+{
+  GError *error;
+  GFile *destination_dir;
+  GList *files;
+  PhotosUtilsCopiedCallback copied_callback;
+  gint io_priority;
+  gpointer copied_callback_data;
+};
+
 static const gdouble EPSILON = 1e-5;
 
 
@@ -101,6 +114,179 @@ photos_utils_center_pixbuf (GdkPixbuf *pixbuf, gint size)
 }
 
 
+static void
+photos_utils_copy_files_data_free (PhotosUtilsCopyFilesData *data)
+{
+  g_clear_error (&data->error);
+  g_object_unref (data->destination_dir);
+  g_list_free_full (data->files, g_object_unref);
+  g_slice_free (PhotosUtilsCopyFilesData, data);
+}
+
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (PhotosUtilsCopyFilesData, photos_utils_copy_files_data_free);
+
+
+static PhotosUtilsCopyFilesData *
+photos_utils_copy_files_data_new (GList *files,
+                                  GFile *destination_dir,
+                                  gint io_priority,
+                                  PhotosUtilsCopiedCallback copied_callback,
+                                  gpointer copied_callback_data)
+{
+  PhotosUtilsCopyFilesData *data;
+
+  data = g_slice_new0 (PhotosUtilsCopyFilesData);
+
+  data->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL);
+  data->destination_dir = g_object_ref (destination_dir);
+  data->io_priority = io_priority;
+  data->copied_callback = copied_callback;
+  data->copied_callback_data = copied_callback_data;
+
+  return data;
+}
+
+
+static void
+photos_utils_copy_files_copy (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  GCancellable *cancellable;
+  g_autoptr (GTask) task = G_TASK (user_data);
+  PhotosUtilsCopyFilesData *data;
+
+  cancellable = g_task_get_cancellable (task);
+  data = (PhotosUtilsCopyFilesData *) g_task_get_task_data (task);
+
+  g_assert_nonnull (data->files);
+  data->files = g_list_remove_link (data->files, data->files);
+
+  {
+    g_autoptr (GFile) destination = NULL;
+    GFile *source = G_FILE (source_object);
+
+    {
+      g_autoptr (GError) error = NULL;
+
+      destination = photos_glib_file_copy_finish (source, res, &error);
+      if (error != NULL)
+        {
+          if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)
+              || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE))
+            {
+              g_task_return_error (task, g_steal_pointer (&error));
+              goto out;
+            }
+          else
+            {
+              if (data->error == NULL)
+                {
+                  g_autofree gchar *uri = NULL;
+
+                  uri = g_file_get_uri (source);
+                  g_prefix_error (&error, "Unable to copy %s: ", uri);
+                  data->error = g_steal_pointer (&error);
+                }
+            }
+        }
+
+      if (destination != NULL && data->copied_callback != NULL)
+        (*data->copied_callback) (source, destination, data->copied_callback_data);
+    }
+  }
+
+  if (data->files == NULL)
+    {
+      if (data->error)
+        g_task_return_error (task, g_error_copy (data->error));
+      else
+        g_task_return_boolean (task, TRUE);
+
+      goto out;
+    }
+
+  {
+    g_autoptr (GFile) destination = NULL;
+    GFile *source;
+    g_autofree gchar *filename = NULL;
+
+    source = G_FILE (data->files->data);
+    filename = g_file_get_basename (source);
+    destination = g_file_get_child (data->destination_dir, filename);
+
+    photos_glib_file_copy_async (source,
+                                 destination,
+                                 G_FILE_COPY_TARGET_DEFAULT_PERMS,
+                                 data->io_priority,
+                                 cancellable,
+                                 photos_utils_copy_files_copy,
+                                 g_object_ref (task));
+  }
+
+ out:
+  return;
+}
+
+
+void
+photos_utils_copy_files_async (GList *files,
+                               GFile *destination_dir,
+                               gint io_priority,
+                               GCancellable *cancellable,
+                               PhotosUtilsCopiedCallback copied_callback,
+                               gpointer copied_callback_data,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
+{
+  g_autoptr (GFile) destination = NULL;
+  GFile *source;
+  g_autoptr (GTask) task = NULL;
+  g_autoptr (PhotosUtilsCopyFilesData) data = NULL;
+  g_autofree gchar *filename = NULL;
+
+  g_return_if_fail (files != NULL);
+  g_return_if_fail (G_IS_FILE (destination_dir));
+  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (NULL, cancellable, callback, user_data);
+  g_task_set_source_tag (task, photos_utils_copy_files_async);
+
+  data = photos_utils_copy_files_data_new (files,
+                                           destination_dir,
+                                           io_priority,
+                                           copied_callback,
+                                           copied_callback_data);
+  g_task_set_task_data (task, g_steal_pointer (&data), (GDestroyNotify) photos_utils_copy_files_data_free);
+
+  source = G_FILE (files->data);
+  filename = g_file_get_basename (source);
+  destination = g_file_get_child (destination_dir, filename);
+
+  photos_glib_file_copy_async (source,
+                               destination,
+                               G_FILE_COPY_TARGET_DEFAULT_PERMS,
+                               io_priority,
+                               cancellable,
+                               photos_utils_copy_files_copy,
+                               g_object_ref (task));
+}
+
+
+gboolean
+photos_utils_copy_files_finish (GAsyncResult *res, GError **error)
+{
+  GTask *task;
+
+  g_return_val_if_fail (g_task_is_valid (res, NULL), FALSE);
+  task = G_TASK (res);
+
+  g_return_val_if_fail (g_task_get_source_tag (task) == photos_utils_copy_files_async, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  return g_task_propagate_boolean (task, error);
+}
+
+
 gchar *
 photos_utils_convert_path_to_uri (const gchar *path)
 {
diff --git a/src/photos-utils.h b/src/photos-utils.h
index b1662451..567e5828 100644
--- a/src/photos-utils.h
+++ b/src/photos-utils.h
@@ -58,8 +58,21 @@ typedef enum
   PHOTOS_ZOOM_EVENT_TOUCH
 } PhotosZoomEvent;
 
+typedef void (*PhotosUtilsCopiedCallback) (GFile *source, GFile *destination, gpointer user_data);
+
 GdkPixbuf       *photos_utils_center_pixbuf               (GdkPixbuf *pixbuf, gint size);
 
+void             photos_utils_copy_files_async            (GList *files,
+                                                           GFile *destination_dir,
+                                                           gint io_priority,
+                                                           GCancellable *cancellable,
+                                                           PhotosUtilsCopiedCallback copied_callback,
+                                                           gpointer copied_callback_data,
+                                                           GAsyncReadyCallback callback,
+                                                           gpointer user_data);
+
+gboolean         photos_utils_copy_files_finish           (GAsyncResult *res, GError **error);
+
 gchar           *photos_utils_convert_path_to_uri         (const gchar *path);
 
 GIcon           *photos_utils_create_collection_icon      (gint base_size, GList *pixbufs);


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