[gnome-photos/wip/rishi/collection: 48/54] utils: Add photos_utils_copy_files_async



commit 4fbd164d9721f3cfc2f23b93ee82a4a61a3510a7
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 | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/photos-utils.h |   9 ++++
 2 files changed, 165 insertions(+)
---
diff --git a/src/photos-utils.c b/src/photos-utils.c
index 9f333e8b..38648794 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,16 @@
 #include "photos-utils.h"
 
 
+typedef struct _PhotosUtilsCopyFilesData PhotosUtilsCopyFilesData;
+
+struct _PhotosUtilsCopyFilesData
+{
+  GError *error;
+  GFile *destination_dir;
+  GList *files;
+  gint io_priority;
+};
+
 static const gdouble EPSILON = 1e-5;
 
 
@@ -101,6 +112,151 @@ 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)
+{
+  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;
+
+  return data;
+}
+
+
+static void
+photos_utils_copy_files_copy (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  GCancellable *cancellable;
+  g_autoptr (GFile) destination = NULL;
+  g_autoptr (GFile) file = G_FILE (source_object);
+  GFile *source;
+  g_autoptr (GTask) task = G_TASK (user_data);
+  PhotosUtilsCopyFilesData *data;
+  g_autofree gchar *filename = NULL;
+
+  cancellable = g_task_get_cancellable (task);
+  data = (PhotosUtilsCopyFilesData *) g_task_get_task_data (task);
+
+  g_assert_nonnull (data->files);
+  g_assert_true (G_FILE (data->files->data) == file);
+  data->files = g_list_remove_link (data->files, data->files);
+
+  {
+    g_autoptr (GError) error = NULL;
+
+    if (!photos_glib_file_copy_finish (file, res, &error))
+      {
+        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)
+              data->error = g_steal_pointer (&error);
+          }
+      }
+  }
+
+  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;
+    }
+
+  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,
+                               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);
+  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..d7cce0f8 100644
--- a/src/photos-utils.h
+++ b/src/photos-utils.h
@@ -60,6 +60,15 @@ typedef enum
 
 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,
+                                                           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]