Index: libgthumb/file-utils.c
===================================================================
--- libgthumb/file-utils.c	(revisão 2394)
+++ libgthumb/file-utils.c	(cópia de trabalho)
@@ -68,7 +68,195 @@
 #define CHUNK_SIZE 128
 #define MAX_SYMLINKS_FOLLOWED 32
 
+struct _AsyncXferData {
+	guint ref_count;
+	GList *source_list;
+	GList *destination_list;
+	GFileCopyFlags flags;
+	GFileProgressCallback progress_callback;
+	gpointer progress_data;
+	GDestroyNotify progress_data_free;
+	AsyncXferEachFileFunc each_file_callback;
+	gpointer each_file_data;
+	GCancellable *cancel;
+	GSourceFunc done_func;
+	gpointer done_data;
+	GDestroyNotify done_free;
+	gboolean move_files;
+};
 
+struct _AsyncXferEachFile {
+	AsyncXferEachFileFunc callback;
+	GFile *src;
+	GFile *dest;
+	GError *error;
+	AsyncXferData *data;
+	gpointer each_file_data;
+};
+static AsyncXferData *_async_xfer_data_ref (AsyncXferData *data);
+static void _async_xfer_data_try_destroy (gpointer data);
+static gboolean _async_xfer_data_unref (AsyncXferData *data, gboolean try_free);
+static gboolean _async_xfer_job_do (GIOSchedulerJob *job, GCancellable *cancellable, gpointer user_data);
+
+static AsyncXferData *
+_async_xfer_data_new ()
+{
+	AsyncXferData *data;
+	data = g_new0(AsyncXferData, 1);
+	data->ref_count = 1;
+	data->source_list = NULL;
+	data->destination_list = NULL;
+	data->flags = 0;
+	data->progress_callback = NULL;
+	data->progress_data = NULL;
+	data->progress_data_free = NULL;
+	data->cancel = NULL;
+	data->done_func = NULL;
+	data->done_data = NULL;
+	data->done_free = NULL;
+	data->move_files = FALSE;
+	return data;
+}
+
+static AsyncXferData *
+_async_xfer_data_ref (AsyncXferData *data)
+{
+	data->ref_count++;
+	return data;
+}
+
+static void
+_async_xfer_data_try_destroy (gpointer data)
+{
+	AsyncXferData *axdata = data;
+	_async_xfer_data_unref (axdata, TRUE);
+}
+
+static gboolean
+_async_xfer_data_unref (AsyncXferData *data, gboolean try_free)
+{
+	g_warning ("%d refcounts of AsyncXferData, and decreasing...", data->ref_count -1);
+	if (data->ref_count > 0)
+		data->ref_count--;
+	else
+		{
+			if (try_free)
+				{
+					g_warning ("Liberando listas");
+					g_list_foreach (data->source_list, (GFunc)g_free, NULL);
+					g_list_free (data->source_list);
+					g_list_foreach (data->destination_list, (GFunc)g_free, NULL);
+					g_list_free (data->destination_list);
+					g_warning ("Listas liberadas!");
+					g_object_unref (data->cancel);
+					data->ref_count = 1;
+					data->source_list = NULL;
+					data->destination_list = NULL;
+					data->flags = 0;
+					data->progress_callback = NULL;
+					data->progress_data = NULL;
+					data->progress_data_free = NULL;
+					data->cancel = NULL;
+					data->done_func = NULL;
+					data->done_data = NULL;
+					data->done_free = NULL;
+					data->move_files = FALSE;
+					g_free (data);
+					data = NULL;
+				}
+			return FALSE;
+		}
+	return TRUE;
+}
+
+static gboolean
+_async_xfer_each_file_in_mainloop (gpointer data)
+{
+	AsyncXferEachFile *axef = data;
+	axef->callback 
+		(axef->src,
+		 axef->dest,
+		 axef->error, 
+		 axef->data, 
+		 axef->each_file_data);
+	g_warning ("Each file callback executed");
+	return FALSE;
+}
+
+static gboolean
+_async_xfer_job_do (GIOSchedulerJob *job,
+		    GCancellable *cancellable,
+		    gpointer user_data)
+{
+	AsyncXferData *data = user_data;
+	GFile *src, *dst;
+	GError *error = NULL;
+	guint counter = 0;
+	GList *scan;
+
+	data->source_list = g_list_first(data->source_list);
+	data->destination_list = g_list_first(data->destination_list);
+
+	for(scan = data->source_list; scan != NULL; scan = g_list_next(scan))
+		{
+			if (g_cancellable_is_cancelled (cancellable))
+				return FALSE;
+
+			data->destination_list = g_list_nth (data->destination_list, counter);
+			if ((!data->source_list) || (!data->destination_list))
+				return FALSE;
+			g_message ("Copying %s to %s", data->source_list->data, data->destination_list->data);
+			src = g_file_new_for_commandline_arg (data->source_list->data);
+			dst = g_file_new_for_commandline_arg (data->destination_list->data);
+
+			if (data->move_files)
+				g_file_move (src, dst, data->flags, cancellable, 
+					     data->progress_callback,
+					     data->progress_data, 
+					     &error);
+			else
+				g_file_copy (src, dst, data->flags, cancellable,
+					     data->progress_callback,
+					     data->progress_data,
+					     &error);
+
+			if (data->each_file_callback)
+				{
+					AsyncXferEachFile *axef = g_new0 (AsyncXferEachFile, 1);
+					axef->callback = data->each_file_callback;
+					axef->src = src;
+					axef->dest = dst;
+					axef->error = error;
+					axef->data = data;
+					axef->each_file_data = data->each_file_data;
+					g_io_scheduler_job_send_to_mainloop (job, _async_xfer_each_file_in_mainloop, axef, g_free);
+				}
+
+			g_io_scheduler_job_send_to_mainloop (job, 
+							     data->done_func,
+							     data->done_data,
+							     data->done_free);
+
+			g_object_unref (src);
+			g_object_unref (dst);
+			g_clear_error (&error);
+			counter++; /* must be increased here */
+		}
+
+	if (data->progress_data_free)
+		data->progress_data_free (data->progress_data);
+
+
+	return FALSE;
+}
+
+/* empty functions */
+static void _empty_file_progress_cb  (goffset current_num_bytes,
+				      goffset total_num_bytes,
+				      gpointer user_data)
+{
+}
+
 /* Async directory list */
 
 
@@ -762,7 +950,48 @@
 	return xfer_file (from, to, TRUE);
 }
 
+void
+async_xfer_file_gio (GList *source_list,
+		     GList *destination_list,
+		     gboolean move_files,
+		     GFileCopyFlags flags, 
+		     GCancellable *cancel,
+		     GFileProgressCallback progress_callback,
+		     gpointer progress_data,
+		     GDestroyNotify progress_data_free,
+		     AsyncXferEachFileFunc each_file_callback,
+		     gpointer each_file_data,
+		     gint io_priority,
+		     GSourceFunc done_func,
+		     gpointer done_data,
+		     GDestroyNotify done_free)
+{
+	AsyncXferData *data;
+	g_assert (g_list_length (source_list) == g_list_length (destination_list));
 
+	data = _async_xfer_data_new ();
+	data->source_list = NULL;
+	data->destination_list = NULL;
+	for (source_list; source_list != NULL; source_list = source_list->next)
+		data->source_list = g_list_prepend(data->source_list, g_strdup(source_list->data));
+	for (destination_list; destination_list != NULL; destination_list = destination_list->next)
+		data->destination_list = g_list_prepend(data->destination_list, g_strdup(destination_list->data));
+
+	data->flags = flags;
+	data->progress_callback = progress_callback;
+	data->progress_data = progress_data;
+	data->progress_data_free = progress_data_free;
+	data->each_file_callback = each_file_callback;
+	data->each_file_data = each_file_data;
+	data->done_func = done_func;
+	data->done_data = done_data;
+	data->done_free = done_free;
+
+	g_io_scheduler_push_job (_async_xfer_job_do, data, 
+				 _async_xfer_data_try_destroy,
+				 io_priority, cancel);
+}
+
 gboolean
 local_file_move (const char *from,
 	         const char *to)
@@ -1771,7 +2000,19 @@
 	return uri;
 }
 
+char *
+new_uri_string_from_path (const char *path)
+{
+	char        *uri_txt;
 
+	if (path[0] == '/')
+		uri_txt = g_strconcat ("file://", path, NULL);
+	else
+		uri_txt = g_strdup (path);
+
+	return uri_txt;
+}
+
 char *
 new_path_from_uri (GnomeVFSURI *uri)
 {
@@ -2021,7 +2262,25 @@
 	return FALSE;
 }
 
+char *
+get_trash_path ()
+{
+	return g_build_filename (g_get_user_data_dir (), "Trash", NULL);
+}
 
+char *
+get_trash_uri ()
+{
+	gchar *uri, *path;
+
+	path = get_trash_path ();
+	uri = g_build_filename ("file://", path, NULL);
+
+	g_free (path);
+
+	return uri;
+}
+
 /* Catalogs */
 
 
@@ -2453,35 +2712,17 @@
 		(copy_data->done_func) (copy_data->target_uri, copy_data->error, copy_data->done_data);
 	}
 	copy_data_free (copy_data);
-	
-	return FALSE;
+
 }
 
-
-static int
-copy_file_async_progress_update_cb (GnomeVFSAsyncHandle      *handle,
-				    GnomeVFSXferProgressInfo *info,
-				    gpointer                  user_data)
+static void
+copy_file_async_done_gio (GObject *source_object,
+			  GAsyncResult *res,
+			  gpointer data)
 {
-	CopyData *copy_data = user_data;
-
-	if (info->status != GNOME_VFS_XFER_PROGRESS_STATUS_OK) {
-		copy_data->result = info->vfs_status;
-		return FALSE;
-	}
-	else if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) 
-		copy_data->idle_id = g_idle_add (copy_file_async_done, copy_data);
-	/*else if ((info->phase == GNOME_VFS_XFER_PHASE_COPYING)
-		 || (info->phase == GNOME_VFS_XFER_PHASE_MOVING))
-		g_signal_emit (G_OBJECT (copy_data->archive),
-			       fr_archive_signals[PROGRESS],
-			       0,
-			       (double) info->total_bytes_copied / info->bytes_total);*/
-			       
-	return TRUE;
+	copy_file_async_done (data);
 }
 
-
 CopyData *
 copy_file_async (const char   *source_uri,
 		 const char   *target_uri,
@@ -2489,38 +2730,27 @@
 		 gpointer      done_data)
 {
 	CopyData       *copy_data;
-	GList          *source_uri_list, *target_uri_list;
-	GnomeVFSResult  result;
+	GFile          *sfile, *dfile;
 
 	copy_data = copy_data_new (source_uri, target_uri, done_func, done_data);
 
 	if (! path_is_file (source_uri)) {
-		copy_data->result = GNOME_VFS_ERROR_NOT_FOUND;
-		copy_data->idle_id = g_idle_add (copy_file_async_done, copy_data);
+		g_set_error (&copy_data->error, G_IO_ERROR,
+			     G_IO_ERROR_NOT_FOUND, 
+			     "File not found: %s", source_uri);
 		return NULL;
 	}
 
-	source_uri_list = g_list_append (NULL, gnome_vfs_uri_new (source_uri));
-	target_uri_list = g_list_append (NULL, gnome_vfs_uri_new (target_uri));
+	sfile = g_file_new_for_uri (source_uri);
+	dfile = g_file_new_for_uri (target_uri);
 
-	result = gnome_vfs_async_xfer (&copy_data->handle,
-				       source_uri_list,
-				       target_uri_list,
-				       GNOME_VFS_XFER_DEFAULT | GNOME_VFS_XFER_FOLLOW_LINKS,
-				       GNOME_VFS_XFER_ERROR_MODE_ABORT,
-				       GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
-				       GNOME_VFS_PRIORITY_DEFAULT,
-				       copy_file_async_progress_update_cb, copy_data,
-				       NULL, NULL);
+	g_file_copy_async (sfile, dfile,
+			   G_FILE_COPY_OVERWRITE,
+			   G_PRIORITY_DEFAULT,
+			   NULL, NULL, NULL,
+			   copy_file_async_done_gio,
+			   copy_data);
 
-	gnome_vfs_uri_list_free (source_uri_list);
-	gnome_vfs_uri_list_free (target_uri_list);
-
-	if (result != GNOME_VFS_OK) {
-		copy_data->result = result;
-		copy_data->idle_id = g_idle_add (copy_file_async_done, copy_data);
-	}
-	
 	return copy_data;
 }
 
