Commit 055522da authored by Paolo Bacchilega's avatar Paolo Bacchilega
Browse files

Implemented recursive folder copy and deletion

Ask confirmation when trying to delete a non-empty folder.
parent f9b389f3
......@@ -441,11 +441,13 @@ gth_file_source_catalogs_copy (GthFileSource *file_source,
g_free (message);
}
g_query_info_async (cod->file_list,
G_FILE_ATTRIBUTE_STANDARD_TYPE,
gth_file_source_get_cancellable (file_source),
copy__file_list_info_ready_cb,
cod);
_g_query_info_async (cod->file_list,
FALSE,
TRUE,
GFILE_NAME_TYPE_ATTRIBUTES,
gth_file_source_get_cancellable (file_source),
copy__file_list_info_ready_cb,
cod);
}
......
......@@ -8,6 +8,8 @@ libfile_manager_la_SOURCES = \
callbacks.h \
gth-copy-task.c \
gth-copy-task.h \
gth-delete-task.c \
gth-delete-task.h \
gth-duplicate-task.c \
gth-duplicate-task.h \
main.c
......
......@@ -25,6 +25,7 @@
#include <glib/gi18n.h>
#include <gthumb.h>
#include "gth-copy-task.h"
#include "gth-delete-task.h"
#include "gth-duplicate-task.h"
......@@ -609,16 +610,54 @@ gth_browser_activate_action_folder_paste (GtkAction *action,
/* -- gth_browser_activate_action_folder_trash -- */
typedef struct {
GthBrowser *browser;
GthFileData *file_data;
} DeleteFolderData;
static void
delete_folder_permanently (GtkWindow *window,
GthFileData *file_data)
delete_data_free (DeleteFolderData *delete_data)
{
GList *files;
GError *error = NULL;
_g_object_unref (delete_data->browser);
_g_object_unref (delete_data->file_data);
g_free (delete_data);
}
static void
delete_folder_permanently (GtkWindow *window,
DeleteFolderData *delete_data)
{
GthFileData *file_data = delete_data->file_data;
GError *error = NULL;
GList *files;
files = g_list_prepend (NULL, file_data->file);
if (! _g_delete_files (files, TRUE, &error)) {
_gtk_error_dialog_from_gerror_show (window, _("Could not delete the folder"), &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_EMPTY)) {
GtkWidget *d;
int response;
d = _gtk_yesno_dialog_new (GTK_WINDOW (delete_data->browser),
GTK_DIALOG_MODAL,
_("The folder is not empty, do you want to delete the folder and its content permanently?"),
GTK_STOCK_CANCEL,
GTK_STOCK_DELETE);
response = gtk_dialog_run (GTK_DIALOG (d));
if (response == GTK_RESPONSE_YES) {
GthTask *task;
task = gth_delete_task_new (files);
gth_browser_exec_task (delete_data->browser, task, FALSE);
g_object_unref (task);
}
gtk_widget_destroy (d);
}
else
_gtk_error_dialog_from_gerror_show (window, _("Could not delete the folder"), &error);
}
else {
GFile *parent;
......@@ -633,6 +672,7 @@ delete_folder_permanently (GtkWindow *window,
}
g_list_free (files);
delete_data_free (delete_data);
}
......@@ -641,13 +681,14 @@ delete_folder_permanently_response_cb (GtkDialog *dialog,
int response_id,
gpointer user_data)
{
GthFileData *file_data = user_data;
if (response_id == GTK_RESPONSE_YES)
delete_folder_permanently (gtk_window_get_transient_for (GTK_WINDOW (dialog)), file_data);
DeleteFolderData *delete_data = user_data;
gtk_widget_destroy (GTK_WIDGET (dialog));
_g_object_unref (file_data);
if (response_id == GTK_RESPONSE_YES)
delete_folder_permanently (GTK_WINDOW (delete_data->browser), delete_data);
else
delete_data_free (delete_data);
}
......@@ -664,19 +705,22 @@ gth_browser_activate_action_folder_trash (GtkAction *action,
if (! g_file_trash (file_data->file, NULL, &error)) {
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) {
GtkWidget *d;
DeleteFolderData *delete_data;
GtkWidget *d;
g_clear_error (&error);
delete_data = g_new0 (DeleteFolderData, 1);
delete_data->browser = g_object_ref (browser);
delete_data->file_data = g_object_ref (file_data);
d = _gtk_yesno_dialog_new (GTK_WINDOW (browser),
GTK_DIALOG_MODAL,
_("The folder cannot be moved to the Trash. Do you want to delete it permanently?"),
GTK_STOCK_CANCEL,
GTK_STOCK_DELETE);
g_signal_connect (d, "response", G_CALLBACK (delete_folder_permanently_response_cb), file_data);
g_signal_connect (d, "response", G_CALLBACK (delete_folder_permanently_response_cb), delete_data);
gtk_widget_show (d);
file_data = NULL;
}
else
_gtk_error_dialog_from_gerror_show (GTK_WINDOW (browser), _("Could not move the folder to the Trash"), &error);
......@@ -704,15 +748,21 @@ void
gth_browser_activate_action_folder_delete (GtkAction *action,
GthBrowser *browser)
{
GthFileData *file_data;
char *prompt;
GtkWidget *d;
GthFileData *file_data;
char *prompt;
DeleteFolderData *delete_data;
GtkWidget *d;
file_data = gth_folder_tree_get_selected (GTH_FOLDER_TREE (gth_browser_get_folder_tree (browser)));
if (file_data == NULL)
return;
prompt = g_strdup_printf (_("Are you sure you want to permanently delete \"%s\"?"), g_file_info_get_display_name (file_data->info));
delete_data = g_new0 (DeleteFolderData, 1);
delete_data->browser = g_object_ref (browser);
delete_data->file_data = g_object_ref (file_data);
d = _gtk_message_dialog_new (GTK_WINDOW (browser),
GTK_DIALOG_MODAL,
GTK_STOCK_DIALOG_QUESTION,
......@@ -721,7 +771,7 @@ gth_browser_activate_action_folder_delete (GtkAction *action,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_DELETE, GTK_RESPONSE_YES,
NULL);
g_signal_connect (d, "response", G_CALLBACK (delete_folder_permanently_response_cb), file_data);
g_signal_connect (d, "response", G_CALLBACK (delete_folder_permanently_response_cb), delete_data);
gtk_widget_show (d);
g_free (prompt);
......
/* -*- 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-delete-task.h"
struct _GthDeleteTaskPrivate {
GCancellable *cancellable;
GList *file_list;
};
static gpointer parent_class = NULL;
static void
gth_delete_task_finalize (GObject *object)
{
GthDeleteTask *self;
self = GTH_DELETE_TASK (object);
_g_object_list_unref (self->priv->file_list);
_g_object_unref (self->priv->cancellable);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
delete_ready_cb (GError *error,
gpointer user_data)
{
gth_task_completed (GTH_TASK (user_data), error);
}
static void
gth_delete_task_exec (GthTask *task)
{
GthDeleteTask *self;
self = GTH_DELETE_TASK (task);
gth_task_progress (task, _("Deleting files"), NULL, TRUE, 0.0);
_g_delete_files_async (self->priv->file_list,
TRUE,
TRUE,
self->priv->cancellable,
delete_ready_cb,
self);
}
static void
gth_delete_task_cancel (GthTask *task)
{
GthDeleteTask *self;
g_return_if_fail (GTH_IS_DELETE_TASK (task));
self = GTH_DELETE_TASK (task);
g_cancellable_cancel (self->priv->cancellable);
}
static void
gth_delete_task_class_init (GthDeleteTaskClass *klass)
{
GObjectClass *object_class;
GthTaskClass *task_class;
parent_class = g_type_class_peek_parent (klass);
g_type_class_add_private (klass, sizeof (GthDeleteTaskPrivate));
object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gth_delete_task_finalize;
task_class = GTH_TASK_CLASS (klass);
task_class->exec = gth_delete_task_exec;
task_class->cancel = gth_delete_task_cancel;
}
static void
gth_delete_task_init (GthDeleteTask *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_DELETE_TASK, GthDeleteTaskPrivate);
self->priv->cancellable = g_cancellable_new ();
}
GType
gth_delete_task_get_type (void)
{
static GType type = 0;
if (! type) {
GTypeInfo type_info = {
sizeof (GthDeleteTaskClass),
NULL,
NULL,
(GClassInitFunc) gth_delete_task_class_init,
NULL,
NULL,
sizeof (GthDeleteTask),
0,
(GInstanceInitFunc) gth_delete_task_init
};
type = g_type_register_static (GTH_TYPE_TASK,
"GthDeleteTask",
&type_info,
0);
}
return type;
}
GthTask *
gth_delete_task_new (GList *file_list)
{
GthDeleteTask *self;
self = GTH_DELETE_TASK (g_object_new (GTH_TYPE_DELETE_TASK, NULL));
self->priv->file_list = _g_object_list_ref (file_list);
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_DELETE_TASK_H
#define GTH_DELETE_TASK_H
#include <glib.h>
#include <gthumb.h>
G_BEGIN_DECLS
#define GTH_TYPE_DELETE_TASK (gth_delete_task_get_type ())
#define GTH_DELETE_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_DELETE_TASK, GthDeleteTask))
#define GTH_DELETE_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_DELETE_TASK, GthDeleteTaskClass))
#define GTH_IS_DELETE_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_DELETE_TASK))
#define GTH_IS_DELETE_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_DELETE_TASK))
#define GTH_DELETE_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_DELETE_TASK, GthDeleteTaskClass))
typedef struct _GthDeleteTask GthDeleteTask;
typedef struct _GthDeleteTaskClass GthDeleteTaskClass;
typedef struct _GthDeleteTaskPrivate GthDeleteTaskPrivate;
struct _GthDeleteTask {
GthTask __parent;
GthDeleteTaskPrivate *priv;
};
struct _GthDeleteTaskClass {
GthTaskClass __parent;
};
GType gth_delete_task_get_type (void);
GthTask * gth_delete_task_new (GList *file_list);
G_END_DECLS
#endif /* GTH_DELETE_TASK_H */
......@@ -214,10 +214,10 @@ check_cache_free_space (void)
typedef struct {
CopyDoneCallback done_func;
gpointer done_data;
GFile *cache_file;
gboolean dummy;
ReadyFunc done_func;
gpointer done_data;
GFile *cache_file;
gboolean dummy;
} CopyToCacheData;
......@@ -241,10 +241,10 @@ copy_remote_file_to_cache_ready (GError *error,
void
copy_remote_file_to_cache (GthFileData *file_data,
GCancellable *cancellable,
CopyDoneCallback done_func,
gpointer done_data)
copy_remote_file_to_cache (GthFileData *file_data,
GCancellable *cancellable,
ReadyFunc done_func,
gpointer done_data)
{
CopyToCacheData *copy_data;
GFile *cache_file;
......@@ -310,10 +310,10 @@ obtain_local_file (GthFileData *file_data)
void
update_file_from_cache (GthFileData *file_data,
GCancellable *cancellable,
CopyDoneCallback done_func,
gpointer done_data)
update_file_from_cache (GthFileData *file_data,
GCancellable *cancellable,
ReadyFunc done_func,
gpointer done_data)
{
GFile *cache_file;
GTimeVal cache_mtime;
......
......@@ -27,22 +27,23 @@
#include <gio/gio.h>
#include "gth-file-data.h"
#include "gio-utils.h"
#include "typedefs.h"
G_BEGIN_DECLS
char * get_file_cache_full_path (const char *filename,
char * get_file_cache_full_path (const char *filename,
const char *extension);
GFile * _g_file_get_cache_file (GFile *file);
void free_file_cache (void);
void check_cache_free_space (void);
void copy_remote_file_to_cache (GthFileData *file_data,
GCancellable *cancellable,
CopyDoneCallback done_func,
ReadyFunc done_func,
gpointer done_data);
GFile * obtain_local_file (GthFileData *file_data);
void update_file_from_cache (GthFileData *file_data,
GCancellable *cancellable,
CopyDoneCallback done_func,
ReadyFunc done_func,
gpointer done_data);
G_END_DECLS
......
This diff is collapsed.
......@@ -44,14 +44,10 @@ typedef DirOp (*StartDirCallback) (GFile *directory,
typedef void (*ForEachChildCallback) (GFile *file,
GFileInfo *info,
gpointer user_data);
typedef void (*ForEachDoneCallback) (GError *error,
gpointer data);
typedef void (*ListReadyCallback) (GList *files,
GList *dirs,
GError *error,
gpointer user_data);
typedef void (*CopyDoneCallback) (GError *error,
gpointer user_data);
typedef void (*BufferReadyCallback) (void *buffer,
gsize count,
GError *error,
......@@ -69,7 +65,7 @@ void g_directory_foreach_child (GFile *directory,
GCancellable *cancellable,
StartDirCallback start_dir_func,
ForEachChildCallback for_each_file_func,
ForEachDoneCallback done_func,
ReadyFunc done_func,
gpointer user_data);
void g_directory_list_async (GFile *directory,
const char *base_dir,
......@@ -84,15 +80,17 @@ void g_directory_list_async (GFile *directory,
GCancellable *cancellable,
ListReadyCallback done_func,
gpointer done_data);
void g_query_info_async (GList *files, /* GFile * list */
void _g_query_info_async (GList *file_list, /* GFile * list */
gboolean recursive,
gboolean follow_links,
const char *attributes,
GCancellable *cancellable,
InfoReadyCallback ready_func,
InfoReadyCallback ready_callback,
gpointer user_data);
/* asynchronous copy functions */
void _g_dummy_file_op_async (CopyDoneCallback callback,
void _g_dummy_file_op_async (ReadyFunc callback,
gpointer user_data);
void _g_copy_files_async (GList *sources,
GFile *destination,
......@@ -102,7 +100,7 @@ void _g_copy_files_async (GList *sources,
GCancellable *cancellable,
ProgressCallback progress_callback,
gpointer progress_callback_data,
CopyDoneCallback callback,
ReadyFunc callback,
gpointer user_data);
void _g_copy_file_async (GFile *source,
GFile *destination,
......@@ -112,7 +110,7 @@ void _g_copy_file_async (GFile *source,
GCancellable *cancellable,
ProgressCallback progress_callback,
gpointer progress_callback_data,
CopyDoneCallback callback,
ReadyFunc callback,
gpointer user_data);
gboolean _g_move_file (GFile *source,
GFile *destination,
......@@ -124,8 +122,14 @@ gboolean _g_move_file (GFile *source,
gboolean _g_delete_files (GList *file_list,
gboolean include_metadata,
GError **error);
void _g_delete_files_async (GList *file_list,
gboolean recursive,
gboolean include_metadata,
GCancellable *cancellable,
ReadyFunc callback,
gpointer user_data);
/* -- read/write/create file -- */
/* -- load/write/create file -- */
gboolean g_load_file_in_buffer (GFile *file,
void **buffer,
......
......@@ -35,6 +35,16 @@
/* gobject utils*/
gpointer
_g_object_ref (gpointer object)
{
if (object != NULL)
return g_object_ref (object);
else
return NULL;
}
void
_g_object_unref (gpointer object)
{
......
......@@ -30,8 +30,9 @@
G_BEGIN_DECLS
#define GFILE_NAME_TYPE_ATTRIBUTES "standard::name,standard::type"
#define GFILE_DISPLAY_ATTRIBUTES "standard::display-name,standard::icon"
#define GFILE_BASIC_ATTRIBUTES GFILE_DISPLAY_ATTRIBUTES ",standard::type"
#define GFILE_BASIC_ATTRIBUTES GFILE_DISPLAY_ATTRIBUTES ",standard::name,standard::type"
#define DEFINE_STANDARD_ATTRIBUTES(a) ( \
"standard::type," \
......@@ -74,6 +75,7 @@ G_BEGIN_DECLS
/* gobject utils*/
gpointer _g_object_ref (gpointer object);
void _g_object_unref (gpointer object);
GList * _g_object_list_ref (GList *list);
void _g_object_list_unref (GList *list);
......
......@@ -562,14 +562,15 @@ _g_query_all_metadata_async (GList *files, /* GFile * list */
qam = g_new0 (QueryAllMetadata, 1);
qam->attributes = g_strdup (attributes);
if (cancellable != NULL)
qam->cancellable = g_object_ref (cancellable);
qam->cancellable = _g_object_ref (cancellable);
qam->ready_func = ready_func;
qam->user_data = user_data;
g_query_info_async (files,
qam->attributes,
qam->cancellable,
qam_info_ready_cb,
qam);
_g_query_info_async (files,
FALSE,
TRUE,
qam->attributes,
qam->cancellable,
qam_info_ready_cb,
qam);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment