mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-11-04 01:58:54 +01:00 
			
		
		
		
	Implement async file movement
This commit is contained in:
		
				
					committed by
					
						
						Philip Withnall
					
				
			
			
				
	
			
			
			
						parent
						
							1cdb0f8bed
						
					
				
				
					commit
					eeb2bcf5a9
				
			@@ -149,6 +149,8 @@ g_file_copy
 | 
			
		||||
g_file_copy_async
 | 
			
		||||
g_file_copy_finish
 | 
			
		||||
g_file_move
 | 
			
		||||
g_file_move_async
 | 
			
		||||
g_file_move_finish
 | 
			
		||||
g_file_make_directory
 | 
			
		||||
g_file_make_directory_async
 | 
			
		||||
g_file_make_directory_finish
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										218
									
								
								gio/gfile.c
									
									
									
									
									
								
							
							
						
						
									
										218
									
								
								gio/gfile.c
									
									
									
									
									
								
							@@ -247,6 +247,18 @@ static void               g_file_real_trash_async                 (GFile
 | 
			
		||||
static gboolean           g_file_real_trash_finish                (GFile                  *file,
 | 
			
		||||
                                                                   GAsyncResult           *res,
 | 
			
		||||
                                                                   GError                **error);
 | 
			
		||||
static void               g_file_real_move_async                  (GFile                  *source,
 | 
			
		||||
                                                                   GFile                  *destination,
 | 
			
		||||
                                                                   GFileCopyFlags          flags,
 | 
			
		||||
                                                                   int                     io_priority,
 | 
			
		||||
                                                                   GCancellable           *cancellable,
 | 
			
		||||
                                                                   GFileProgressCallback   progress_callback,
 | 
			
		||||
                                                                   gpointer                progress_callback_data,
 | 
			
		||||
                                                                   GAsyncReadyCallback     callback,
 | 
			
		||||
                                                                   gpointer                user_data);
 | 
			
		||||
static gboolean           g_file_real_move_finish                 (GFile                  *file,
 | 
			
		||||
                                                                   GAsyncResult           *result,
 | 
			
		||||
                                                                   GError                **error);
 | 
			
		||||
static void               g_file_real_make_directory_async        (GFile                  *file,
 | 
			
		||||
                                                                   int                     io_priority,
 | 
			
		||||
                                                                   GCancellable           *cancellable,
 | 
			
		||||
@@ -381,6 +393,8 @@ g_file_default_init (GFileIface *iface)
 | 
			
		||||
  iface->delete_file_finish = g_file_real_delete_finish;
 | 
			
		||||
  iface->trash_async = g_file_real_trash_async;
 | 
			
		||||
  iface->trash_finish = g_file_real_trash_finish;
 | 
			
		||||
  iface->move_async = g_file_real_move_async;
 | 
			
		||||
  iface->move_finish = g_file_real_move_finish;
 | 
			
		||||
  iface->make_directory_async = g_file_real_make_directory_async;
 | 
			
		||||
  iface->make_directory_finish = g_file_real_make_directory_finish;
 | 
			
		||||
  iface->open_readwrite_async = g_file_real_open_readwrite_async;
 | 
			
		||||
@@ -3770,6 +3784,91 @@ g_file_move (GFile                  *source,
 | 
			
		||||
  return g_file_delete (source, cancellable, error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * g_file_move_async:
 | 
			
		||||
 * @source: #GFile pointing to the source location
 | 
			
		||||
 * @destination: #GFile pointing to the destination location
 | 
			
		||||
 * @flags: set of #GFileCopyFlags
 | 
			
		||||
 * @io_priority: the [I/O priority][io-priority] of the request
 | 
			
		||||
 * @cancellable: (nullable): optional #GCancellable object,
 | 
			
		||||
 *   %NULL to ignore
 | 
			
		||||
 * @progress_callback: (nullable) (scope call): #GFileProgressCallback
 | 
			
		||||
 *   function for updates
 | 
			
		||||
 * @progress_callback_data: (closure): gpointer to user data for
 | 
			
		||||
 *   the callback function
 | 
			
		||||
 * @callback: a #GAsyncReadyCallback to call
 | 
			
		||||
 *   when the request is satisfied
 | 
			
		||||
 * @user_data: the data to pass to callback function
 | 
			
		||||
 *
 | 
			
		||||
 * Asynchronously moves a file @source to the location of @destination. For details of the behaviour, see g_file_move().
 | 
			
		||||
 *
 | 
			
		||||
 * If @progress_callback is not %NULL, then that function that will be called
 | 
			
		||||
 * just like in g_file_move(). The callback will run in the default main context
 | 
			
		||||
 * of the thread calling g_file_move_async() — the same context as @callback is
 | 
			
		||||
 * run in.
 | 
			
		||||
 *
 | 
			
		||||
 * When the operation is finished, @callback will be called. You can then call
 | 
			
		||||
 * g_file_move_finish() to get the result of the operation.
 | 
			
		||||
 *
 | 
			
		||||
 * Since: 2.72
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
g_file_move_async (GFile                *source,
 | 
			
		||||
                   GFile                *destination,
 | 
			
		||||
                   GFileCopyFlags        flags,
 | 
			
		||||
                   int                   io_priority,
 | 
			
		||||
                   GCancellable         *cancellable,
 | 
			
		||||
                   GFileProgressCallback progress_callback,
 | 
			
		||||
                   gpointer              progress_callback_data,
 | 
			
		||||
                   GAsyncReadyCallback   callback,
 | 
			
		||||
                   gpointer              user_data)
 | 
			
		||||
{
 | 
			
		||||
  GFileIface *iface;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (G_IS_FILE (source));
 | 
			
		||||
  g_return_if_fail (G_IS_FILE (destination));
 | 
			
		||||
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 | 
			
		||||
 | 
			
		||||
  iface = G_FILE_GET_IFACE (source);
 | 
			
		||||
  (* iface->move_async) (source,
 | 
			
		||||
                         destination,
 | 
			
		||||
                         flags,
 | 
			
		||||
                         io_priority,
 | 
			
		||||
                         cancellable,
 | 
			
		||||
                         progress_callback,
 | 
			
		||||
                         progress_callback_data,
 | 
			
		||||
                         callback,
 | 
			
		||||
                         user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * g_file_move_finish:
 | 
			
		||||
 * @file: input source #GFile
 | 
			
		||||
 * @result: a #GAsyncResult
 | 
			
		||||
 * @error: a #GError, or %NULL
 | 
			
		||||
 *
 | 
			
		||||
 * Finishes an asynchronous file movement, started with
 | 
			
		||||
 * g_file_move_async().
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: %TRUE on successful file move, %FALSE otherwise.
 | 
			
		||||
 *
 | 
			
		||||
 * Since: 2.72
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
g_file_move_finish (GFile         *file,
 | 
			
		||||
                    GAsyncResult  *result,
 | 
			
		||||
                    GError       **error)
 | 
			
		||||
{
 | 
			
		||||
  GFileIface *iface;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (G_IS_FILE (file), FALSE);
 | 
			
		||||
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
 | 
			
		||||
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
  iface = G_FILE_GET_IFACE (file);
 | 
			
		||||
  return (* iface->move_finish) (file, result, error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * g_file_make_directory:
 | 
			
		||||
 * @file: input #GFile
 | 
			
		||||
@@ -6004,6 +6103,125 @@ g_file_real_trash_finish (GFile         *file,
 | 
			
		||||
  return g_task_propagate_boolean (G_TASK (res), error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  GFile *source;  /* (owned) */
 | 
			
		||||
  GFile *destination;  /* (owned) */
 | 
			
		||||
  GFileCopyFlags flags;
 | 
			
		||||
  GFileProgressCallback progress_cb;
 | 
			
		||||
  gpointer progress_cb_data;
 | 
			
		||||
} MoveAsyncData;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
move_async_data_free (MoveAsyncData *data)
 | 
			
		||||
{
 | 
			
		||||
  g_object_unref (data->source);
 | 
			
		||||
  g_object_unref (data->destination);
 | 
			
		||||
  g_slice_free (MoveAsyncData, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  MoveAsyncData *data;  /* (unowned) */
 | 
			
		||||
  goffset current_num_bytes;
 | 
			
		||||
  goffset total_num_bytes;
 | 
			
		||||
} MoveProgressData;
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
move_async_progress_in_main (gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  MoveProgressData *progress = user_data;
 | 
			
		||||
  MoveAsyncData *data = progress->data;
 | 
			
		||||
 | 
			
		||||
  data->progress_cb (progress->current_num_bytes,
 | 
			
		||||
                     progress->total_num_bytes,
 | 
			
		||||
                     data->progress_cb_data);
 | 
			
		||||
 | 
			
		||||
  return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
move_async_progress_callback (goffset  current_num_bytes,
 | 
			
		||||
                              goffset  total_num_bytes,
 | 
			
		||||
                              gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  GTask *task = user_data;
 | 
			
		||||
  MoveAsyncData *data = g_task_get_task_data (task);
 | 
			
		||||
  MoveProgressData *progress;
 | 
			
		||||
 | 
			
		||||
  progress = g_new0 (MoveProgressData, 1);
 | 
			
		||||
  progress->data = data;
 | 
			
		||||
  progress->current_num_bytes = current_num_bytes;
 | 
			
		||||
  progress->total_num_bytes = total_num_bytes;
 | 
			
		||||
 | 
			
		||||
  g_main_context_invoke_full (g_task_get_context (task),
 | 
			
		||||
                              g_task_get_priority (task),
 | 
			
		||||
                              move_async_progress_in_main,
 | 
			
		||||
                              g_steal_pointer (&progress),
 | 
			
		||||
                              g_free);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
move_async_thread (GTask        *task,
 | 
			
		||||
                   gpointer      source,
 | 
			
		||||
                   gpointer      task_data,
 | 
			
		||||
                   GCancellable *cancellable)
 | 
			
		||||
{
 | 
			
		||||
  MoveAsyncData *data = task_data;
 | 
			
		||||
  gboolean result;
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
 | 
			
		||||
  result = g_file_move (data->source,
 | 
			
		||||
                        data->destination,
 | 
			
		||||
                        data->flags,
 | 
			
		||||
                        cancellable,
 | 
			
		||||
                        (data->progress_cb != NULL) ? move_async_progress_callback : NULL,
 | 
			
		||||
                        task,
 | 
			
		||||
                        &error);
 | 
			
		||||
  if (result)
 | 
			
		||||
    g_task_return_boolean (task, TRUE);
 | 
			
		||||
  else
 | 
			
		||||
    g_task_return_error (task, g_steal_pointer (&error));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
g_file_real_move_async (GFile                  *source,
 | 
			
		||||
                        GFile                  *destination,
 | 
			
		||||
                        GFileCopyFlags          flags,
 | 
			
		||||
                        int                     io_priority,
 | 
			
		||||
                        GCancellable           *cancellable,
 | 
			
		||||
                        GFileProgressCallback   progress_callback,
 | 
			
		||||
                        gpointer                progress_callback_data,
 | 
			
		||||
                        GAsyncReadyCallback     callback,
 | 
			
		||||
                        gpointer                user_data)
 | 
			
		||||
{
 | 
			
		||||
  GTask *task;
 | 
			
		||||
  MoveAsyncData *data;
 | 
			
		||||
 | 
			
		||||
  data = g_slice_new0 (MoveAsyncData);
 | 
			
		||||
  data->source = g_object_ref (source);
 | 
			
		||||
  data->destination = g_object_ref (destination);
 | 
			
		||||
  data->flags = flags;
 | 
			
		||||
  data->progress_cb = progress_callback;
 | 
			
		||||
  data->progress_cb_data = progress_callback_data;
 | 
			
		||||
 | 
			
		||||
  task = g_task_new (source, cancellable, callback, user_data);
 | 
			
		||||
  g_task_set_source_tag (task, g_file_real_move_async);
 | 
			
		||||
  g_task_set_task_data (task, g_steal_pointer (&data), (GDestroyNotify) move_async_data_free);
 | 
			
		||||
  g_task_set_priority (task, io_priority);
 | 
			
		||||
  g_task_run_in_thread (task, move_async_thread);
 | 
			
		||||
  g_object_unref (task);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
g_file_real_move_finish (GFile        *file,
 | 
			
		||||
                         GAsyncResult *result,
 | 
			
		||||
                         GError      **error)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (g_task_is_valid (result, file), FALSE);
 | 
			
		||||
 | 
			
		||||
  return g_task_propagate_boolean (G_TASK (result), error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
make_directory_async_thread (GTask        *task,
 | 
			
		||||
                             gpointer      object,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								gio/gfile.h
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								gio/gfile.h
									
									
									
									
									
								
							@@ -121,8 +121,8 @@ typedef struct _GFileIface    		GFileIface;
 | 
			
		||||
 * @copy_async: Asynchronously copies a file.
 | 
			
		||||
 * @copy_finish: Finishes an asynchronous copy operation.
 | 
			
		||||
 * @move: Moves a file.
 | 
			
		||||
 * @_move_async: Asynchronously moves a file.
 | 
			
		||||
 * @_move_finish: Finishes an asynchronous move operation.
 | 
			
		||||
 * @move_async: Asynchronously moves a file. Since: 2.72
 | 
			
		||||
 * @move_finish: Finishes an asynchronous move operation. Since: 2.72
 | 
			
		||||
 * @mount_mountable: Mounts a mountable object.
 | 
			
		||||
 * @mount_mountable_finish: Finishes a mounting operation.
 | 
			
		||||
 * @unmount_mountable: Unmounts a mountable object.
 | 
			
		||||
@@ -424,8 +424,18 @@ struct _GFileIface
 | 
			
		||||
                                                       GFileProgressCallback progress_callback,
 | 
			
		||||
                                                       gpointer              progress_callback_data,
 | 
			
		||||
                                                       GError              **error);
 | 
			
		||||
  void                (* _move_async)                 (void);
 | 
			
		||||
  void                (* _move_finish)                (void);
 | 
			
		||||
  void                (* move_async)                  (GFile                *source,
 | 
			
		||||
                                                       GFile                *destination,
 | 
			
		||||
                                                       GFileCopyFlags        flags,
 | 
			
		||||
                                                       int                   io_priority,
 | 
			
		||||
                                                       GCancellable         *cancellable,
 | 
			
		||||
                                                       GFileProgressCallback progress_callback,
 | 
			
		||||
                                                       gpointer              progress_callback_data,
 | 
			
		||||
                                                       GAsyncReadyCallback   callback,
 | 
			
		||||
                                                       gpointer              user_data);
 | 
			
		||||
  gboolean            (* move_finish)                 (GFile                *file,
 | 
			
		||||
                                                       GAsyncResult         *result,
 | 
			
		||||
                                                       GError              **error);
 | 
			
		||||
 | 
			
		||||
  void                (* mount_mountable)             (GFile                *file,
 | 
			
		||||
                                                       GMountMountFlags      flags,
 | 
			
		||||
@@ -926,6 +936,20 @@ gboolean                g_file_move                       (GFile
 | 
			
		||||
							   GFileProgressCallback       progress_callback,
 | 
			
		||||
							   gpointer                    progress_callback_data,
 | 
			
		||||
							   GError                    **error);
 | 
			
		||||
GLIB_AVAILABLE_IN_2_72
 | 
			
		||||
void                    g_file_move_async                 (GFile                      *source,
 | 
			
		||||
							                                             GFile                      *destination,
 | 
			
		||||
							                                             GFileCopyFlags              flags,
 | 
			
		||||
							                                             int                         io_priority,
 | 
			
		||||
							                                             GCancellable               *cancellable,
 | 
			
		||||
							                                             GFileProgressCallback       progress_callback,
 | 
			
		||||
							                                             gpointer                    progress_callback_data,
 | 
			
		||||
							                                             GAsyncReadyCallback         callback,
 | 
			
		||||
							                                             gpointer                    user_data);
 | 
			
		||||
GLIB_AVAILABLE_IN_2_72
 | 
			
		||||
gboolean                g_file_move_finish                (GFile                      *file,
 | 
			
		||||
							                                             GAsyncResult               *result,
 | 
			
		||||
							                                             GError                    **error);
 | 
			
		||||
GLIB_AVAILABLE_IN_ALL
 | 
			
		||||
gboolean                g_file_make_directory             (GFile                      *file,
 | 
			
		||||
							   GCancellable               *cancellable,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user