Commit 5b1660bf authored by Paolo Bacchilega's avatar Paolo Bacchilega
Browse files

Execute the gth_file_source_copy operation as a task; Implemented

"past into folder" command; Show an error dialog if a background
task fails;  Added a progress callback to the gth_file_source_copy
function.
parent 28cfcf44
......@@ -309,9 +309,10 @@ gth_file_source_catalogs_list (GthFileSource *file_source,
typedef struct {
GthFileSourceVfs *file_source;
GFile *destination;
GthFileData *destination;
GList *file_list;
ReadyCallback callback;
ProgressCallback progress_callback;
ReadyCallback ready_callback;
gpointer user_data;
GList *files;
GthCatalog *catalog;
......@@ -343,11 +344,11 @@ catalog_save_done_cb (void *buffer,
if (error == NULL)
gth_monitor_folder_changed (gth_main_get_default_monitor (),
cod->destination,
cod->destination->file,
cod->files,
GTH_MONITOR_EVENT_CREATED);
cod->callback (G_OBJECT (cod->file_source), error, cod->user_data);
cod->ready_callback (G_OBJECT (cod->file_source), error, cod->user_data);
copy_op_data_free (cod);
}
......@@ -362,7 +363,7 @@ catalog_ready_cb (GObject *catalog,
GFile *gio_file;
if (error != NULL) {
cod->callback (G_OBJECT (cod->file_source), error, cod->user_data);
cod->ready_callback (G_OBJECT (cod->file_source), error, cod->user_data);
copy_op_data_free (cod);
return;
}
......@@ -373,7 +374,7 @@ catalog_ready_cb (GObject *catalog,
gth_catalog_insert_file (cod->catalog, -1, (GFile *) scan->data);
cod->buffer = gth_catalog_to_data (cod->catalog, &cod->length);
gio_file = gth_catalog_file_to_gio_file (cod->destination);
gio_file = gth_catalog_file_to_gio_file (cod->destination->file);
g_write_file_async (gio_file,
cod->buffer,
cod->length,
......@@ -408,16 +409,17 @@ copy__file_list_info_ready_cb (GList *files,
}
cod->files = g_list_reverse (cod->files);
gth_catalog_load_from_file (cod->destination, catalog_ready_cb, cod);
gth_catalog_load_from_file (cod->destination->file, catalog_ready_cb, cod);
}
static void
gth_file_source_catalogs_copy (GthFileSource *file_source,
GFile *destination,
GList *file_list, /* GFile * list */
ReadyCallback callback,
gpointer data)
gth_file_source_catalogs_copy (GthFileSource *file_source,
GthFileData *destination,
GList *file_list, /* GFile * list */
ProgressCallback progress_callback,
ReadyCallback ready_callback,
gpointer data)
{
CopyOpData *cod;
......@@ -425,9 +427,19 @@ gth_file_source_catalogs_copy (GthFileSource *file_source,
cod->file_source = g_object_ref (file_source);
cod->destination = g_object_ref (destination);
cod->file_list = _g_object_list_ref (file_list);
cod->callback = callback;
cod->progress_callback = progress_callback;
cod->ready_callback = ready_callback;
cod->user_data = data;
if (cod->progress_callback != NULL) {
char *message;
message = g_strdup_printf (_("Copying files to '%s'"), g_file_info_get_display_name (destination->info));
(cod->progress_callback) (G_OBJECT (file_source), message, NULL, TRUE, 0.0, cod->user_data);
g_free (message);
}
g_query_info_async (cod->file_list,
G_FILE_ATTRIBUTE_STANDARD_TYPE,
gth_file_source_get_cancellable (file_source),
......
......@@ -40,7 +40,7 @@ GthMetadataInfo comments_metadata_info[] = {
{ "comment::note", N_("Comment"), "comment", 1, GTH_METADATA_ALLOW_NOWHERE },
{ "comment::place", N_("Place"), "comment", 2, GTH_METADATA_ALLOW_EVERYWHERE },
{ "comment::time", N_("Date"), "comment", 3, GTH_METADATA_ALLOW_EVERYWHERE },
{ "comment::categories", N_("Categories"), "comment", 4, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
{ "comment::categories", N_("Tags"), "comment", 4, GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW },
{ "comment::rating", N_("Rating"), "comment", 5, GTH_METADATA_ALLOW_EVERYWHERE },
{ NULL, NULL, NULL, 0, 0 }
};
......@@ -100,7 +100,7 @@ gthumb_extension_activate (void)
NULL);
gth_main_register_test ("comment::category",
GTH_TYPE_TEST_CATEGORY,
"display-name", _("Category"),
"display-name", _("Tag"),
NULL);
gth_hook_add_callback ("add-sidecars", 10, G_CALLBACK (comments__add_sidecars_cb), NULL);
}
......
......@@ -6,6 +6,8 @@ libfile_manager_la_SOURCES = \
actions.h \
callbacks.c \
callbacks.h \
gth-copy-task.c \
gth-copy-task.h \
gth-duplicate-task.c \
gth-duplicate-task.h \
main.c
......
......@@ -24,6 +24,7 @@
#include <config.h>
#include <glib/gi18n.h>
#include <gthumb.h>
#include "gth-copy-task.h"
#include "gth-duplicate-task.h"
......@@ -246,7 +247,7 @@ gth_browser_activate_action_edit_copy_files (GtkAction *action,
typedef struct {
GthBrowser *browser;
GFile *destination;
GthFileData *destination;
GthFileSource *file_source;
GList *files;
gboolean cut;
......@@ -264,58 +265,31 @@ paste_data_free (PasteData *paste_data)
}
static void
paste_done_cb (GObject *object,
GError *error,
gpointer user_data)
{
PasteData *paste_data = user_data;
GthBrowser *browser = paste_data->browser;
if (error != NULL) {
_gtk_error_dialog_from_gerror_show (GTK_WINDOW (browser), _("Could not copy the files"), &error);
paste_data_free (paste_data);
return;
}
if (paste_data->cut) {
if (! _g_delete_files (paste_data->files, TRUE, &error))
_gtk_error_dialog_from_gerror_show (GTK_WINDOW (browser), _("Could not delete the files"), &error);
}
paste_data_free (paste_data);
}
static void
clipboard_received_cb (GtkClipboard *clipboard,
GtkSelectionData *selection_data,
gpointer user_data)
{
GthBrowser *browser = user_data;
PasteData *paste_data = user_data;
GthBrowser *browser = paste_data->browser;
char **clipboard_data;
PasteData *paste_data;
int i;
GthTask *task;
clipboard_data = g_strsplit_set ((const char *) gtk_selection_data_get_data (selection_data), "\n\r", -1);
if (clipboard_data[0] == NULL) {
g_strfreev (clipboard_data);
paste_data_free (paste_data);
return;
}
paste_data = g_new0 (PasteData, 1);
paste_data->browser = g_object_ref (browser);
paste_data->destination = g_object_ref (gth_browser_get_location (browser));
paste_data->cut = strcmp (clipboard_data[0], "cut") == 0;
paste_data->files = NULL;
for (i = 1; clipboard_data[i] != NULL; i++)
if (strcmp (clipboard_data[i], "") != 0)
paste_data->files = g_list_prepend (paste_data->files, g_file_new_for_uri (clipboard_data[i]));
paste_data->files = g_list_reverse (paste_data->files);
paste_data->file_source = gth_main_get_file_source (gth_browser_get_location (browser));
paste_data->file_source = gth_main_get_file_source (paste_data->destination->file);
if (paste_data->cut && ! gth_file_source_can_cut (paste_data->file_source)) {
GtkWidget *dialog;
......@@ -340,11 +314,14 @@ clipboard_received_cb (GtkClipboard *clipboard,
paste_data->cut = FALSE;
}
gth_file_source_copy (paste_data->file_source,
paste_data->destination,
paste_data->files,
paste_done_cb,
paste_data);
task = gth_copy_task_new (paste_data->file_source,
paste_data->destination,
paste_data->cut,
paste_data->files);
gth_browser_exec_task (browser, task, FALSE);
g_object_unref (task);
paste_data_free (paste_data);
}
......@@ -352,10 +329,16 @@ void
gth_browser_activate_action_edit_paste (GtkAction *action,
GthBrowser *browser)
{
PasteData *paste_data;
paste_data = g_new0 (PasteData, 1);
paste_data->browser = g_object_ref (browser);
paste_data->destination = g_object_ref (gth_browser_get_location (browser));
gtk_clipboard_request_contents (gtk_widget_get_clipboard (GTK_WIDGET (browser), GDK_SELECTION_CLIPBOARD),
GNOME_COPIED_FILES,
clipboard_received_cb,
browser);
paste_data);
}
......@@ -576,7 +559,7 @@ gth_browser_activate_action_folder_copy (GtkAction *action,
file_list = g_list_prepend (NULL, file_data);
_gth_browser_clipboard_copy_or_cut (browser, file_list, FALSE);
g_list_free (file_list);
_g_object_list_unref (file_list);
}
......@@ -584,7 +567,23 @@ void
gth_browser_activate_action_folder_paste (GtkAction *action,
GthBrowser *browser)
{
GthFileData *file_data;
PasteData *paste_data;
file_data = gth_folder_tree_get_selected (GTH_FOLDER_TREE (gth_browser_get_folder_tree (browser)));
if (file_data == NULL)
return;
paste_data = g_new0 (PasteData, 1);
paste_data->browser = g_object_ref (browser);
paste_data->destination = gth_file_data_dup (file_data);
gtk_clipboard_request_contents (gtk_widget_get_clipboard (GTK_WIDGET (browser), GDK_SELECTION_CLIPBOARD),
GNOME_COPIED_FILES,
clipboard_received_cb,
paste_data);
g_object_unref (file_data);
}
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* GThumb
*
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
*/
#include <config.h>
#include "gth-copy-task.h"
struct _GthCopyTaskPrivate {
GthFileData *destination;
GthFileSource *file_source;
GList *files;
gboolean move;
};
static gpointer parent_class = NULL;
static void
gth_copy_task_finalize (GObject *object)
{
GthCopyTask *self;
self = GTH_COPY_TASK (object);
_g_object_list_unref (self->priv->files);
_g_object_unref (self->priv->file_source);
_g_object_unref (self->priv->destination);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
copy_done_cb (GObject *object,
GError *error,
gpointer user_data)
{
gth_task_completed (GTH_TASK (user_data), error);
}
static void
copy_progress_cb (GObject *object,
const char *description,
const char *details,
gboolean pulse,
double fraction,
gpointer user_data)
{
GthCopyTask *self = user_data;
gth_task_progress (GTH_TASK (self), description, details, pulse, fraction);
}
static void
gth_copy_task_exec (GthTask *task)
{
GthCopyTask *self;
g_return_if_fail (GTH_IS_COPY_TASK (task));
self = GTH_COPY_TASK (task);
gth_file_source_copy (self->priv->file_source,
self->priv->destination,
self->priv->files,
copy_progress_cb,
copy_done_cb,
self);
}
static void
gth_copy_task_cancel (GthTask *task)
{
gth_file_source_cancel (GTH_COPY_TASK (task)->priv->file_source);
}
static void
gth_copy_task_class_init (GthCopyTaskClass *klass)
{
GObjectClass *object_class;
GthTaskClass *task_class;
parent_class = g_type_class_peek_parent (klass);
g_type_class_add_private (klass, sizeof (GthCopyTaskPrivate));
object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gth_copy_task_finalize;
task_class = GTH_TASK_CLASS (klass);
task_class->exec = gth_copy_task_exec;
task_class->cancel = gth_copy_task_cancel;
}
static void
gth_copy_task_init (GthCopyTask *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_COPY_TASK, GthCopyTaskPrivate);
}
GType
gth_copy_task_get_type (void)
{
static GType type = 0;
if (! type) {
GTypeInfo type_info = {
sizeof (GthCopyTaskClass),
NULL,
NULL,
(GClassInitFunc) gth_copy_task_class_init,
NULL,
NULL,
sizeof (GthCopyTask),
0,
(GInstanceInitFunc) gth_copy_task_init
};
type = g_type_register_static (GTH_TYPE_TASK,
"GthCopyTask",
&type_info,
0);
}
return type;
}
GthTask *
gth_copy_task_new (GthFileSource *file_source,
GthFileData *destination,
gboolean move,
GList *files)
{
GthCopyTask *self;
self = GTH_COPY_TASK (g_object_new (GTH_TYPE_COPY_TASK, NULL));
self->priv->file_source = g_object_ref (file_source);
self->priv->destination = g_object_ref (destination);
self->priv->move = move;
self->priv->files = _g_object_list_ref (files);
return (GthTask *) self;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* GThumb
*
* Copyright (C) 2009 The Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
*/
#ifndef GTH_COPY_TASK_H
#define GTH_COPY_TASK_H
#include <glib.h>
#include <gthumb.h>
G_BEGIN_DECLS
#define GTH_TYPE_COPY_TASK (gth_copy_task_get_type ())
#define GTH_COPY_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_COPY_TASK, GthCopyTask))
#define GTH_COPY_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_COPY_TASK, GthCopyTaskClass))
#define GTH_IS_COPY_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_COPY_TASK))
#define GTH_IS_COPY_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_COPY_TASK))
#define GTH_COPY_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_COPY_TASK, GthCopyTaskClass))
typedef struct _GthCopyTask GthCopyTask;
typedef struct _GthCopyTaskClass GthCopyTaskClass;
typedef struct _GthCopyTaskPrivate GthCopyTaskPrivate;
struct _GthCopyTask {
GthTask __parent;
GthCopyTaskPrivate *priv;
};
struct _GthCopyTaskClass {
GthTaskClass __parent;
};
GType gth_copy_task_get_type (void);
GthTask * gth_copy_task_new (GthFileSource *file_source,
GthFileData *destination,
gboolean move,
GList *file_list);
G_END_DECLS
#endif /* GTH_COPY_TASK_H */
......@@ -272,7 +272,7 @@ gth-marshal.h: gth-marshal.list $(GLIB_GENMARSHAL)
gth-marshal.c: gth-marshal.h gth-marshal.list $(GLIB_GENMARSHAL)
echo "#include \"gth-marshal.h\"" > $@ \
&& $(GLIB_GENMARSHAL) $(srcdir)/gth-marshal.list --body --prefix=gth_marshal >> $@
&& $(GLIB_GENMARSHAL) $(srcdir)/gth-marshal.list --body --prefix=gth_marshal >> $@
gthumb.h: make-header.sh gthumb.h.template Makefile.am
$(srcdir)/make-header.sh $(srcdir)/gthumb.h.template $(PUBLIC_HEADER_FILES) > xgen-$(@F) \
......
......@@ -1218,12 +1218,11 @@ g_directory_copy_done (gpointer user_data)
{
DirectoryCopyData *dcd = user_data;
g_source_remove (dcd->source_id);
if (dcd->source_id != 0)
g_source_remove (dcd->source_id);
if (dcd->callback)
dcd->callback (dcd->error, dcd->user_data);
if (dcd->error != NULL)
g_clear_error (&(dcd->error));
directory_copy_data_free (dcd);
return FALSE;
......@@ -1250,7 +1249,6 @@ get_destination_for_file (DirectoryCopyData *dcd,
destination_file = _g_file_append_path (dcd->destination, path);
g_free (path);
g_free (partial_uri);
g_free (source_uri);
g_free (uri);
......@@ -1279,7 +1277,7 @@ g_directory_copy_next_child (gpointer user_data)
static void
g_directory_copy_child_done_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
gpointer user_data)
{
DirectoryCopyData *dcd = user_data;
......@@ -1457,6 +1455,52 @@ g_directory_copy_start_dir (GFile *directory,
}
static void
g_directory_copy_qdestination_info_ready_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
DirectoryCopyData *dcd = user_data;
GFileInfo *info;
info = g_file_query_info_finish (G_FILE (source_object), result, &dcd->error);
if (info == NULL) {
if (! g_error_matches (dcd->error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
g_directory_copy_done (dcd);
return;
}
}
g_clear_error (&dcd->error);
if ((info != NULL) && (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY)) {
dcd->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY, "");
g_directory_copy_done (dcd);
return;
}
if (! g_file_make_directory (dcd->destination,
dcd->cancellable,
&dcd->error))
{
g_directory_copy_done (dcd);
return;
}
g_clear_error (&dcd->error);
g_directory_foreach_child (dcd->source,
TRUE,
TRUE,
"standard::name,standard::type",
dcd->cancellable,
g_directory_copy_start_dir,
g_directory_copy_for_each_file,
g_directory_copy_list_ready,
dcd);
}
void
g_directory_copy_async (GFile *source,
GFile *destination,
......@@ -1475,21 +1519,19 @@ g_directory_copy_async (GFile *source,
dcd->destination = g_file_dup (destination);
dcd->flags = flags;
dcd->io_priority = io_priority;
dcd->cancellable = cancellable;
dcd->cancellable = g_object_ref (cancellable);
dcd->progress_callback = progress_callback;
dcd->progress_callback_data = progress_callback_data;
dcd->callback = callback;
dcd->user_data = user_data;
g_directory_foreach_child (dcd->source,
TRUE,
TRUE,
"standard::name,standard::type",
dcd->cancellable,
g_directory_copy_start_dir,
g_directory_copy_for_each_file,
g_directory_copy_list_ready,
dcd);
g_file_query_info_async (dcd->destination,
"standard::name,standard::type",
0,
G_PRIORITY_DEFAULT,
dcd->cancellable,
g_directory_copy_qdestination_info_ready_cb,
dcd);