[nautilus] undo: rework undo for the trash operation to be asynchronous
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus] undo: rework undo for the trash operation to be asynchronous
- Date: Sun, 22 Jan 2012 00:03:01 +0000 (UTC)
commit 362fb6464b62d6fed896d1bc53f6fc763f8fa6fb
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Sat Jan 21 19:00:10 2012 -0500
undo: rework undo for the trash operation to be asynchronous
Also, make the mtime checks actually useful; we need to check the
trash::deletion-date attribute and match it with the time we trashed the
file (which we can easily know using g_get_current_time()).
libnautilus-private/nautilus-file-operations.c | 20 +--
.../nautilus-file-undo-operations.c | 215 +++++++++++++-------
.../nautilus-file-undo-operations.h | 3 +-
3 files changed, 140 insertions(+), 98 deletions(-)
---
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c
index 1f355f0..5cb83cb 100644
--- a/libnautilus-private/nautilus-file-operations.c
+++ b/libnautilus-private/nautilus-file-operations.c
@@ -1762,8 +1762,6 @@ trash_files (CommonJob *job, GList *files, int *files_skipped)
int total_files, files_trashed;
char *primary, *secondary, *details;
int response;
- GFileInfo *info;
- guint64 mtime;
if (job_aborted (job)) {
return;
@@ -1781,19 +1779,6 @@ trash_files (CommonJob *job, GList *files, int *files_skipped)
file = l->data;
error = NULL;
- mtime = 0;
-
- if (job->undo_info != NULL) {
- info = g_file_query_info (file,
- G_FILE_ATTRIBUTE_TIME_MODIFIED,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL, NULL);
-
- if (info != NULL) {
- mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
- g_object_unref (info);
- }
- }
if (!g_file_trash (file, job->cancellable, &error)) {
if (job->skip_all_error) {
@@ -1842,9 +1827,8 @@ trash_files (CommonJob *job, GList *files, int *files_skipped)
} else {
nautilus_file_changes_queue_file_removed (file);
- if (job->undo_info != NULL && mtime != 0) {
- nautilus_file_undo_info_trash_add_file (NAUTILUS_FILE_UNDO_INFO_TRASH (job->undo_info),
- file, mtime);
+ if (job->undo_info != NULL) {
+ nautilus_file_undo_info_trash_add_file (NAUTILUS_FILE_UNDO_INFO_TRASH (job->undo_info), file);
}
files_trashed++;
diff --git a/libnautilus-private/nautilus-file-undo-operations.c b/libnautilus-private/nautilus-file-undo-operations.c
index 4b8fa1f..d2d1f76 100644
--- a/libnautilus-private/nautilus-file-undo-operations.c
+++ b/libnautilus-private/nautilus-file-undo-operations.c
@@ -72,67 +72,6 @@ uri_list_to_gfile_list (GList * urilist)
return file_list;
}
-/* TODO: Synch-I/O, error handling */
-static GHashTable *
-retrieve_files_to_restore (GHashTable * trashed)
-{
- GFileEnumerator *enumerator;
- GHashTable *to_restore;
- GFile *trash;
-
- to_restore = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, g_free);
-
- trash = g_file_new_for_uri ("trash:///");
-
- enumerator = g_file_enumerate_children (trash,
- G_FILE_ATTRIBUTE_STANDARD_NAME","
- G_FILE_ATTRIBUTE_TIME_MODIFIED","
- G_FILE_ATTRIBUTE_TRASH_ORIG_PATH,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL, NULL);
-
- if (enumerator) {
- GFileInfo *info;
- guint64 *mtime;
- gpointer lookupvalue;
- GFile *item;
- guint64 mtime_item;
- char *origpath;
- GFile *origfile;
- char *origuri;
-
- mtime = 0;
- while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL) {
- /* Retrieve the original file uri */
- origpath = g_file_info_get_attribute_as_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH);
- origfile = g_file_new_for_path (origpath);
- origuri = g_file_get_uri (origfile);
- g_object_unref (origfile);
- g_free (origpath);
-
- lookupvalue = g_hash_table_lookup (trashed, origuri);
-
- if (lookupvalue) {
- mtime = (guint64 *)lookupvalue;
- mtime_item = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
- if (*mtime == mtime_item) {
- /* File in the trash */
- item = g_file_get_child (trash, g_file_info_get_name (info));
- g_hash_table_insert (to_restore, item, origuri);
- }
- } else {
- g_free (origuri);
- }
-
- }
- g_file_enumerator_close (enumerator, FALSE, NULL);
- g_object_unref (enumerator);
- }
- g_object_unref (trash);
-
- return to_restore;
-}
-
/* description helpers */
static void
nautilus_file_undo_info_init (NautilusFileUndoInfo *self)
@@ -1062,19 +1001,123 @@ trash_redo_func (NautilusFileUndoInfo *info,
}
}
+static GHashTable *
+trash_retrieve_files_to_restore_finish (NautilusFileUndoInfoTrash *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ GHashTable *retval = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+
+ if (retval == NULL) {
+ g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+ }
+
+ return retval;
+}
+
static void
-trash_undo_func (NautilusFileUndoInfo *info,
- GtkWindow *parent_window)
+trash_retrieve_files_to_restore_thread (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable)
{
- NautilusFileUndoInfoTrash *self = NAUTILUS_FILE_UNDO_INFO_TRASH (info);
- GHashTable *files_to_restore;
+ NautilusFileUndoInfoTrash *self = NAUTILUS_FILE_UNDO_INFO_TRASH (object);
+ GFileEnumerator *enumerator;
+ GHashTable *to_restore;
+ GFile *trash;
+ GError *error = NULL;
- /* Internally managed op, pop flag. */
- nautilus_file_undo_manager_pop_flag ();
+ to_restore = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, g_free);
+
+ trash = g_file_new_for_uri ("trash:///");
- files_to_restore = retrieve_files_to_restore (self->priv->trashed);
+ enumerator = g_file_enumerate_children (trash,
+ G_FILE_ATTRIBUTE_STANDARD_NAME","
+ G_FILE_ATTRIBUTE_TRASH_DELETION_DATE","
+ G_FILE_ATTRIBUTE_TRASH_ORIG_PATH,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, &error);
+
+ if (enumerator) {
+ GFileInfo *info;
+ gpointer lookupvalue;
+ GFile *item;
+ GTimeVal timeval;
+ glong trash_time, orig_trash_time;
+ char *origpath;
+ GFile *origfile;
+ char *origuri;
+ const char *time_string;
+
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL) {
+ /* Retrieve the original file uri */
+ origpath = g_file_info_get_attribute_as_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH);
+ origfile = g_file_new_for_path (origpath);
+ origuri = g_file_get_uri (origfile);
+ g_object_unref (origfile);
+ g_free (origpath);
+
+ lookupvalue = g_hash_table_lookup (self->priv->trashed, origuri);
- if (g_hash_table_size (files_to_restore) > 0) {
+ if (lookupvalue) {
+ orig_trash_time = GPOINTER_TO_SIZE (lookupvalue);
+ time_string = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_TRASH_DELETION_DATE);
+ if (time_string != NULL) {
+ g_time_val_from_iso8601 (time_string, &timeval);
+ trash_time = timeval.tv_sec;
+ } else {
+ trash_time = 0;
+ }
+
+ if (trash_time == orig_trash_time) {
+ /* File in the trash */
+ item = g_file_get_child (trash, g_file_info_get_name (info));
+ g_hash_table_insert (to_restore, item, origuri);
+ }
+ } else {
+ g_free (origuri);
+ }
+
+ }
+ g_file_enumerator_close (enumerator, FALSE, NULL);
+ g_object_unref (enumerator);
+ }
+ g_object_unref (trash);
+
+ if (error != NULL) {
+ g_simple_async_result_take_error (res, error);
+ g_hash_table_destroy (to_restore);
+ } else {
+ g_simple_async_result_set_op_res_gpointer (res, to_restore, NULL);
+ }
+}
+
+static void
+trash_retrieve_files_to_restore_async (NautilusFileUndoInfoTrash *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *async_op;
+
+ async_op = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ trash_retrieve_files_to_restore_async);
+ g_simple_async_result_run_in_thread (async_op, trash_retrieve_files_to_restore_thread,
+ G_PRIORITY_DEFAULT, NULL);
+
+ g_object_unref (async_op);
+}
+
+static void
+trash_retrieve_files_ready (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ NautilusFileUndoInfoTrash *self = NAUTILUS_FILE_UNDO_INFO_TRASH (source);
+ GHashTable *files_to_restore;
+ GError *error = NULL;
+
+ files_to_restore = trash_retrieve_files_to_restore_finish (self, res, &error);
+
+ if (error == NULL && g_hash_table_size (files_to_restore) > 0) {
GList *gfiles_in_trash, *l;
GFile *item;
GFile *dest;
@@ -1086,6 +1129,7 @@ trash_undo_func (NautilusFileUndoInfo *info,
item = l->data;
value = g_hash_table_lookup (files_to_restore, item);
dest = g_file_new_for_uri (value);
+
g_file_move (item, dest, G_FILE_COPY_NOFOLLOW_SYMLINKS, NULL, NULL, NULL, NULL);
g_object_unref (dest);
}
@@ -1093,10 +1137,25 @@ trash_undo_func (NautilusFileUndoInfo *info,
g_list_free (gfiles_in_trash);
}
- g_hash_table_destroy (files_to_restore);
+ if (files_to_restore != NULL) {
+ g_hash_table_destroy (files_to_restore);
+ }
/* Here we must do what's necessary for the callback */
- file_undo_info_transfer_callback (NULL, TRUE, self);
+ file_undo_info_transfer_callback (NULL, (error != NULL), self);
+ g_clear_error (&error);
+}
+
+static void
+trash_undo_func (NautilusFileUndoInfo *info,
+ GtkWindow *parent_window)
+{
+ NautilusFileUndoInfoTrash *self = NAUTILUS_FILE_UNDO_INFO_TRASH (info);
+
+ /* Internally managed op, pop flag. */
+ nautilus_file_undo_manager_pop_flag ();
+
+ trash_retrieve_files_to_restore_async (self, trash_retrieve_files_ready, NULL);
}
static void
@@ -1143,17 +1202,17 @@ nautilus_file_undo_info_trash_new (gint item_count)
void
nautilus_file_undo_info_trash_add_file (NautilusFileUndoInfoTrash *self,
- GFile *file,
- guint64 mtime)
+ GFile *file)
{
- guint64 *modification_time;
+ GTimeVal current_time;
+ gsize orig_trash_time;
gchar *original_uri;
- modification_time = g_new (guint64, 1);
- *modification_time = mtime;
-
+ g_get_current_time (¤t_time);
+ orig_trash_time = current_time.tv_sec;
original_uri = g_file_get_uri (file);
- g_hash_table_insert (self->priv->trashed, original_uri, modification_time);
+
+ g_hash_table_insert (self->priv->trashed, original_uri, GSIZE_TO_POINTER (orig_trash_time));
}
/* recursive permissions */
diff --git a/libnautilus-private/nautilus-file-undo-operations.h b/libnautilus-private/nautilus-file-undo-operations.h
index fdecf98..0c8fd2e 100644
--- a/libnautilus-private/nautilus-file-undo-operations.h
+++ b/libnautilus-private/nautilus-file-undo-operations.h
@@ -207,8 +207,7 @@ struct _NautilusFileUndoInfoTrashClass {
GType nautilus_file_undo_info_trash_get_type (void) G_GNUC_CONST;
NautilusFileUndoInfo *nautilus_file_undo_info_trash_new (gint item_count);
void nautilus_file_undo_info_trash_add_file (NautilusFileUndoInfoTrash *self,
- GFile *file,
- guint64 mtime);
+ GFile *file);
/* recursive permissions */
#define NAUTILUS_TYPE_FILE_UNDO_INFO_REC_PERMISSIONS (nautilus_file_undo_info_rec_permissions_get_type ())
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]