[nautilus/undo-manager] undostack: split the code into logical modules



commit f3def1c4f2b193b077e0ffd20fdf7e3808caff3c
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Mon Nov 29 11:15:18 2010 +0100

    undostack: split the code into logical modules
    
    undostack-actions: action-related code
    undostack-types: type definitions

 libnautilus-private/Makefile.am                  |    3 +
 libnautilus-private/nautilus-file-private.h      |    2 +-
 libnautilus-private/nautilus-file.c              |    2 +
 libnautilus-private/nautilus-undostack-actions.c | 1068 +++++++++++++++++++++
 libnautilus-private/nautilus-undostack-actions.h |   39 +
 libnautilus-private/nautilus-undostack-manager.c | 1119 +---------------------
 libnautilus-private/nautilus-undostack-manager.h |   32 +-
 libnautilus-private/nautilus-undostack-types.h   |  138 +++
 8 files changed, 1262 insertions(+), 1141 deletions(-)
---
diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am
index 6401073..12d25d4 100644
--- a/libnautilus-private/Makefile.am
+++ b/libnautilus-private/Makefile.am
@@ -189,8 +189,11 @@ libnautilus_private_la_SOURCES = \
 	nautilus-window-info.h \
 	nautilus-window-slot-info.c \
 	nautilus-window-slot-info.h \
+	nautilus-undostack-actions.c \
+	nautilus-undostack-actions.h \
 	nautilus-undostack-manager.c \
 	nautilus-undostack-manager.h \
+	nautilus-undostack-types.h \
 	$(NULL)
 
 nodist_libnautilus_private_la_SOURCES =\
diff --git a/libnautilus-private/nautilus-file-private.h b/libnautilus-private/nautilus-file-private.h
index e22f800..84a2f88 100644
--- a/libnautilus-private/nautilus-file-private.h
+++ b/libnautilus-private/nautilus-file-private.h
@@ -28,9 +28,9 @@
 #include <libnautilus-private/nautilus-directory.h>
 #include <libnautilus-private/nautilus-file.h>
 #include <libnautilus-private/nautilus-monitor.h>
+#include <libnautilus-private/nautilus-undostack-types.h>
 #include <eel/eel-glib-extensions.h>
 #include <eel/eel-string.h>
-#include <libnautilus-private/nautilus-undostack-manager.h>
 
 #define NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE 80
 #define NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES               24
diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c
index 959ceaf..4a9cc89 100644
--- a/libnautilus-private/nautilus-file.c
+++ b/libnautilus-private/nautilus-file.c
@@ -43,6 +43,8 @@
 #include "nautilus-search-directory.h"
 #include "nautilus-search-directory-file.h"
 #include "nautilus-thumbnails.h"
+#include "nautilus-undostack-actions.h"
+#include "nautilus-undostack-manager.h"
 #include "nautilus-users-groups-cache.h"
 #include "nautilus-vfs-file.h"
 #include "nautilus-saved-search-file.h"
diff --git a/libnautilus-private/nautilus-undostack-actions.c b/libnautilus-private/nautilus-undostack-actions.c
new file mode 100644
index 0000000..8c81d5a
--- /dev/null
+++ b/libnautilus-private/nautilus-undostack-actions.c
@@ -0,0 +1,1068 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-undostack-manager.h - Manages undo/redo of file operations
+ *
+ * Copyright (C) 2007-2010 Amos Brocco
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Amos Brocco <amos brocco unifr ch>
+ *          Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#include <config.h>
+
+#include "nautilus-undostack-actions.h"
+
+#include <glib/gi18n.h>
+
+#include "nautilus-file-operations.h"
+#include "nautilus-file.h"
+#include "nautilus-undostack-manager.h"
+#include "nautilus-undostack-types.h"
+
+void
+nautilus_undo_stack_action_data_free (NautilusUndoStackActionData *action)
+{
+	g_return_if_fail (action != NULL);
+
+	g_free (action->template);
+
+	g_free (action->undo_label);
+	g_free (action->undo_description);
+	g_free (action->redo_label);
+	g_free (action->redo_description);
+
+	g_free (action->original_name);
+	g_free (action->new_name);
+
+	if (action->sources) {
+		g_list_free_full (action->sources, g_free);
+	}
+
+	if (action->destinations) {
+		g_list_free_full (action->destinations, g_free);
+	}
+
+	if (action->trashed) {
+		g_hash_table_destroy (action->trashed);
+	}
+
+	if (action->original_permissions) {
+		g_hash_table_destroy (action->original_permissions);
+	}
+
+	g_clear_object (&action->old_file);
+	g_clear_object (&action->target_file);
+	g_clear_object (&action->src_dir);
+	g_clear_object (&action->dest_dir);
+
+	g_free (action->new_file);
+
+	g_slice_free (NautilusUndoStackActionData, action);
+}
+
+static char *
+get_first_target_short_name (NautilusUndoStackActionData *action)
+{
+	GList *targets_first;
+	char *file_name;
+
+	g_assert (action != NULL);
+
+	targets_first = g_list_first (action->destinations);
+	file_name = g_strdup (targets_first->data);
+
+	return file_name;
+}
+
+static GList *
+uri_list_to_gfile_list (GList * urilist)
+{
+	const GList *l;
+	GList *file_list = NULL;
+	GFile *file;
+
+	for (l = urilist; l != NULL; l = l->next) {
+		file = g_file_new_for_uri (l->data);
+		file_list = g_list_append (file_list, file);
+	}
+
+	return file_list;
+}
+
+static GList *
+construct_gfile_list_from_uri (char *uri)
+{
+	GList *file_list = NULL;
+	GFile *file;
+
+	file = g_file_new_for_uri (uri);
+	file_list = g_list_append (file_list, file);
+
+	return file_list;
+}
+
+static GList *
+construct_gfile_list (const GList * urilist, GFile * parent)
+{
+	const GList *l;
+	GList *file_list = NULL;
+	GFile *file;
+
+	for (l = urilist; l != NULL; l = l->next) {
+		file = g_file_get_child (parent, l->data);
+		file_list = g_list_append (file_list, file);
+	}
+
+	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;
+}
+
+static void
+undo_redo_done_transfer_callback (GHashTable * debuting_uris,
+                                  gpointer data)
+{
+	NautilusUndoStackActionData *action;
+
+	action = (NautilusUndoStackActionData *) data;
+
+	/* If the action needed to be freed but was locked, free now */
+	if (action->freed) {
+		nautilus_undo_stack_action_data_free (action);
+	} else {
+		action->locked = FALSE;
+	}
+
+	/* Update menus */
+	nautilus_undo_stack_manager_request_menu_update (action->manager);
+}
+
+static void
+undo_redo_done_rename_callback (NautilusFile * file,
+				GFile * result_location,
+				GError * error,
+				gpointer callback_data)
+{
+	undo_redo_done_transfer_callback (NULL, callback_data);
+}
+
+static void
+undo_redo_done_create_callback (GFile * new_file,
+				gpointer callback_data)
+{
+	undo_redo_done_transfer_callback (NULL, callback_data);
+}
+
+static void
+undo_redo_done_delete_callback (GHashTable *debuting_uris,
+                                gboolean user_cancel,
+                                gpointer callback_data)
+{
+	undo_redo_done_transfer_callback (debuting_uris, callback_data);
+}
+
+static void
+undo_redo_op_callback (gpointer callback_data)
+{
+	undo_redo_done_transfer_callback (NULL, callback_data);
+}
+
+/* undo helpers */
+
+static void
+delete_uris (NautilusUndoStackManager *self,
+	     GList *uris,
+	     UndoData *action)
+{
+	if (self->priv->confirm_delete) {
+		nautilus_file_operations_delete (uris, NULL,
+						 undo_redo_done_delete_callback, action);
+	} else {
+		self->priv->undo_redo_flag = FALSE;
+
+		/* We skip the confirmation message */
+		GList *f;
+		for (f = uris; f != NULL; f = f->next) {
+			g_file_delete (f->data, NULL, NULL);
+		}
+
+		/* Here we must do what's necessary for the callback */
+		undo_redo_done_transfer_callback (NULL, action);
+	}
+}
+
+static void
+create_undo_func (UndoData *action)
+{
+	GList *uris;
+	gchar *uri;
+
+	uri = g_file_get_uri (action->target_file);
+	uris = construct_gfile_list_from_uri (uri);
+
+	delete_uris (action->manager, uris, action);
+
+	g_free (uri);
+	g_list_free_full (uris, g_object_unref);
+}
+
+static void
+copy_or_link_undo_func (UndoData *action)
+{
+	GList *uris;
+
+	uris = construct_gfile_list (action->destinations, action->dest_dir);
+	uris = g_list_reverse (uris); /* Deleting must be done in reverse */
+
+	delete_uris (action->manager, uris, action);
+
+	g_list_free_full (uris, g_object_unref);
+}
+
+static void
+restore_undo_func (UndoData *action)
+{
+	GList *uris;
+
+	uris = construct_gfile_list (action->destinations, action->dest_dir);
+	nautilus_file_operations_trash_or_delete (uris, NULL,
+						  undo_redo_done_delete_callback, action);
+
+	g_list_free_full (uris, g_object_unref);
+}
+
+static void
+trash_undo_func (UndoData *action)
+{
+	NautilusUndoStackManagerPrivate *priv = action->manager->priv;
+	GHashTable *files_to_restore;
+
+	/* Internally managed op, clear the undo_redo_flag.
+	 * Same as calling nautilus_undo_stack_manager_is_undo_redo()
+	 * minus the function call and unused return val.
+	 */
+
+	priv->undo_redo_flag = FALSE;
+	files_to_restore = retrieve_files_to_restore (action->trashed);
+
+	if (g_hash_table_size (files_to_restore) > 0) {
+		GList *gfiles_in_trash, *l;
+		GFile *item;
+		GFile *dest;
+		char *value;
+
+		gfiles_in_trash = g_hash_table_get_keys (files_to_restore);
+
+		for (l = gfiles_in_trash; l != NULL; l = l->next) {
+			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);
+		}
+
+		g_list_free (gfiles_in_trash);
+	}
+
+	g_hash_table_destroy (files_to_restore);
+
+	/* Here we must do what's necessary for the callback */
+	undo_redo_done_transfer_callback (NULL, action);
+}
+
+static void
+move_undo_func (UndoData *action)
+{
+	GList *uris;
+
+	uris = construct_gfile_list (action->destinations, action->dest_dir);
+	nautilus_file_operations_move (uris, NULL,
+				       action->src_dir, NULL,
+				       undo_redo_done_transfer_callback, action);
+
+	g_list_free_full (uris, g_object_unref);
+}
+
+static void
+rename_undo_func (UndoData *action)
+{
+	gchar *new_name;
+	NautilusFile *file;
+
+	new_name = g_file_get_basename (action->old_file);
+	file = nautilus_file_get (action->new_file);
+
+	nautilus_file_rename (file, new_name,
+			      undo_redo_done_rename_callback, action);
+
+	nautilus_file_unref (file);
+	g_free (new_name);
+}
+
+static void
+set_permissions_undo_func (UndoData *action)
+{
+	NautilusFile *file;
+
+	file = nautilus_file_get (action->target_file);
+
+	nautilus_file_set_permissions (file,
+				       action->current_permissions,
+				       undo_redo_done_rename_callback, action);
+
+	nautilus_file_unref (file);
+}
+
+static void
+recursive_permissions_undo_func (UndoData *action)
+{
+	NautilusUndoStackManagerPrivate *priv = action->manager->priv;
+
+	/* Internally managed op, clear the undo_redo_flag. */
+	priv->undo_redo_flag = FALSE;
+
+	if (g_hash_table_size (action->original_permissions) > 0) {
+		GList *gfiles_list;
+		guint32 *perm;
+		GList *l;
+		GFile *dest;
+		char *item;
+
+		gfiles_list = g_hash_table_get_keys (action->original_permissions);
+		for (l = gfiles_list; l != NULL; l = l->next) {
+			item = l->data;
+			perm = g_hash_table_lookup (action->original_permissions, item);
+			dest = g_file_new_for_uri (item);
+			g_file_set_attribute_uint32 (dest,
+						     G_FILE_ATTRIBUTE_UNIX_MODE,
+						     *perm, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
+			g_object_unref (dest);
+		}
+
+		g_list_free (gfiles_list);
+		/* Here we must do what's necessary for the callback */
+		undo_redo_done_transfer_callback (NULL, action);
+	}
+}
+
+static void
+change_group_undo_func (UndoData *action)
+{
+	NautilusFile *file;
+
+	file = nautilus_file_get (action->target_file);
+
+	nautilus_file_set_group (file,
+				 action->original_name,
+				 undo_redo_done_rename_callback, action);
+
+	nautilus_file_unref (file);
+}
+
+static void
+change_owner_undo_func (UndoData *action)
+{
+	NautilusFile *file;
+
+	file = nautilus_file_get (action->target_file);
+
+	nautilus_file_set_owner (file,
+				 action->original_name,
+				 undo_redo_done_rename_callback, action);
+
+	nautilus_file_unref (file);
+}
+
+/* redo helpers */
+
+static void
+copy_redo_func (UndoData *action)
+{
+	GList *locations;
+
+	locations = construct_gfile_list (action->sources, action->src_dir);
+	nautilus_file_operations_copy (locations, NULL,
+				       action->dest_dir, NULL,
+				       undo_redo_done_transfer_callback, action);
+
+	g_list_free_full (locations, g_object_unref);
+}
+
+static void
+create_from_template_redo_func (UndoData *action)
+{
+	GFile *parent;
+	gchar *parent_uri, *new_name;
+
+	parent = g_file_get_parent (action->target_file);
+	parent_uri = g_file_get_uri (parent);
+	new_name = g_file_get_parse_name (action->target_file);
+	nautilus_file_operations_new_file_from_template (NULL, NULL,
+							 parent_uri, new_name,
+							 action->template,
+							 undo_redo_done_create_callback, action);
+
+	g_free (parent_uri);
+	g_free (new_name);
+	g_object_unref (parent);
+}
+
+static void
+duplicate_redo_func (UndoData *action)
+{
+	GList *locations;
+
+	locations = construct_gfile_list (action->sources, action->src_dir);
+	nautilus_file_operations_duplicate (locations, NULL, NULL,
+					    undo_redo_done_transfer_callback, action);
+
+	g_list_free_full (locations, g_object_unref);
+}
+
+static void
+move_restore_redo_func (UndoData *action)
+{
+	GList *locations;
+
+	locations = construct_gfile_list (action->sources, action->src_dir);
+	nautilus_file_operations_move (locations, NULL,
+				       action->dest_dir, NULL,
+				       undo_redo_done_transfer_callback, action);
+
+	g_list_free_full (locations, g_object_unref);
+}
+
+static void
+rename_redo_func (UndoData *action)
+{
+	gchar *new_name;
+	NautilusFile *file;
+
+	new_name = g_file_get_basename (action->new_file);
+	file = nautilus_file_get (action->old_file);
+	nautilus_file_rename (file, new_name,
+			      undo_redo_done_rename_callback, action);
+
+	nautilus_file_unref (file);
+	g_free (new_name);
+}
+
+static void
+create_empty_redo_func (UndoData *action)
+{
+	GFile *parent;
+	gchar *parent_uri;
+	gchar *new_name;
+
+	parent = g_file_get_parent (action->target_file);
+	parent_uri = g_file_get_uri (parent);
+	new_name = g_file_get_parse_name (action->target_file);
+	nautilus_file_operations_new_file (NULL, NULL, parent_uri,
+					   new_name,
+					   action->template,
+					   action->count, undo_redo_done_create_callback, action);
+
+	g_free (parent_uri);
+	g_free (new_name);
+	g_object_unref (parent);
+}
+
+static void
+create_folder_redo_func (UndoData *action)
+{
+	GFile *parent;
+	gchar *parent_uri;
+
+	parent = g_file_get_parent (action->target_file);
+	parent_uri = g_file_get_uri (parent);
+	nautilus_file_operations_new_folder (NULL, NULL, parent_uri,
+					     undo_redo_done_create_callback, action);
+
+	g_free (parent_uri);
+	g_object_unref (parent);
+}
+
+static void
+trash_redo_func (UndoData *action)
+{
+	if (g_hash_table_size (action->trashed) > 0) {
+		GList *uri_to_trash, *locations;
+
+		uri_to_trash = g_hash_table_get_keys (action->trashed);
+		locations = uri_list_to_gfile_list (uri_to_trash);
+		nautilus_file_operations_trash_or_delete (locations, NULL,
+							  undo_redo_done_delete_callback, action);
+		g_list_free (uri_to_trash);
+		g_list_free_full (locations, g_object_unref);
+	}
+}
+
+static void
+create_link_redo_func (UndoData *action)
+{
+	GList *locations;
+
+	locations = construct_gfile_list (action->sources, action->src_dir);
+	nautilus_file_operations_link (locations, NULL,
+				       action->dest_dir, NULL,
+				       undo_redo_done_transfer_callback, action);
+	g_list_free_full (locations, g_object_unref);
+}
+
+static void
+set_permissions_redo_func (UndoData *action)
+{
+	NautilusFile *file;
+
+	file = nautilus_file_get (action->target_file);
+	nautilus_file_set_permissions (file, action->new_permissions,
+				       undo_redo_done_rename_callback, action);
+
+	nautilus_file_unref (file);
+}
+
+static void
+recursive_permissions_redo_func (UndoData *action)
+{
+	gchar *parent_uri;
+
+	parent_uri = g_file_get_uri (action->dest_dir);
+	nautilus_file_set_permissions_recursive (parent_uri,
+						 action->file_permissions,
+						 action->file_mask,
+						 action->dir_permissions,
+						 action->dir_mask,
+						 undo_redo_op_callback,
+						 action);
+	g_free (parent_uri);
+}
+
+static void
+change_group_redo_func (UndoData *action)
+{
+	NautilusFile *file;
+
+	file = nautilus_file_get (action->target_file);
+	nautilus_file_set_group (file,
+				 action->new_name,
+				 undo_redo_done_rename_callback,
+				 action);
+
+	nautilus_file_unref (file);
+}
+
+static void
+change_owner_redo_func (UndoData *action)
+{
+	NautilusFile *file;
+
+	file = nautilus_file_get (action->target_file);
+	nautilus_file_set_owner (file,
+				 action->new_name,
+				 undo_redo_done_rename_callback,
+				 action);
+
+	nautilus_file_unref (file);
+}
+
+/* description helpers */
+
+static void
+copy_description_func (UndoData *action,
+		       guint count,
+		       gchar **labels,
+		       gchar **descriptions)
+{
+	gchar *destination;
+
+	destination = g_file_get_path (action->dest_dir);
+
+	if (count != 1) {
+		descriptions[0] = g_strdup_printf (_("Delete %d copied items"), count);
+		descriptions[1] = g_strdup_printf (_("Copy %d items to '%s'"), count, destination);
+
+		labels[0] = g_strdup_printf (_("_Undo Copy %d items"), count);
+		labels[1] = g_strdup_printf (_("_Redo Copy %d items"), count);
+	} else {
+		gchar *name;
+
+		name = get_first_target_short_name (action);
+		descriptions[0] = g_strdup_printf (_("Delete '%s'"), name);
+		descriptions[1] = g_strdup_printf (_("Copy '%s' to '%s'"), name, destination);
+
+		labels[0] = g_strdup (_("_Undo Copy"));
+		labels[1] = g_strdup (_("_Redo Copy"));
+
+		g_free (name);
+	}
+}
+
+static void
+duplicate_description_func (UndoData *action,
+			    guint count,
+			    gchar **labels,
+			    gchar **descriptions)
+{
+	gchar *destination;
+
+	destination = g_file_get_path (action->dest_dir);
+
+	if (count != 1) {
+		descriptions[0] = g_strdup_printf (_("Delete %d duplicated items"), count);
+		descriptions[1] = g_strdup_printf (_("Duplicate of %d items in '%s'"),
+						   count, destination);
+
+		labels[0] = g_strdup_printf (_("_Undo Duplicate %d items"), count);
+		labels[1] = g_strdup_printf (_("_Redo Duplicate %d items"), count);
+	} else {
+		char *name;
+
+		name = get_first_target_short_name (action);
+		descriptions[0] = g_strdup_printf (_("Delete '%s'"), name);
+		descriptions[1] = g_strdup_printf (_("Duplicate '%s' in '%s'"),
+						   name, destination);
+
+		labels[0] = g_strdup (_("_Undo Duplicate"));
+		labels[1] = g_strdup (_("_Redo Duplicate"));
+
+		g_free (name);
+	}
+
+}
+
+static void
+move_description_func (UndoData *action,
+		       guint count,
+		       gchar **labels,
+		       gchar **descriptions)
+{
+	gchar *source, *destination;
+
+        source = g_file_get_path (action->src_dir);
+	destination = g_file_get_path (action->dest_dir);
+
+	if (count != 1) {
+		descriptions[0] = g_strdup_printf (_("Move %d items back to '%s'"), count, source);
+		descriptions[1] = g_strdup_printf (_("Move %d items to '%s'"), count, destination);
+
+		labels[0] = g_strdup_printf (_("_Undo Move %d items"), count);
+		labels[1] = g_strdup_printf (_("_Redo Move %d items"), count);
+	} else {
+		char *name;
+
+		name = get_first_target_short_name (action);
+		descriptions[0] = g_strdup_printf (_("Move '%s' back to '%s'"), name, source);
+		descriptions[1] = g_strdup_printf (_("Move '%s' to '%s'"), name, destination);
+
+		labels[0] = g_strdup (_("_Undo Move"));
+		labels[1] = g_strdup (_("_Redo Move"));
+
+		g_free (name);
+	}
+}
+
+static void
+rename_description_func (UndoData *action,
+			 guint count,
+			 gchar **labels,
+			 gchar **descriptions)
+{
+	gchar *new_name, *old_name;
+
+	new_name = g_file_get_parse_name (action->new_file);
+	old_name = g_file_get_parse_name (action->old_file);
+
+	descriptions[0] = g_strdup_printf (_("Rename '%s' as '%s'"), new_name, old_name);
+	descriptions[1] = g_strdup_printf (_("Rename '%s' as '%s'"), old_name, new_name);
+
+	labels[0] = g_strdup (_("_Undo Rename"));
+	labels[1] = g_strdup (_("_Redo Rename"));
+
+	g_free (old_name);
+	g_free (new_name);
+}
+
+static void
+create_undo_common (UndoData *action,
+		    guint count,
+		    gchar **descriptions)
+{
+            char *name;
+
+	    name = g_file_get_parse_name (action->target_file);
+	    descriptions[0] = g_strdup_printf (_("Delete '%s'"), name);
+
+	    g_free (name);
+}
+
+static void
+create_empty_description_func (UndoData *action,
+			       guint count,
+			       gchar **labels,
+			       gchar **descriptions)
+{
+	gchar *name;
+
+	create_undo_common (action, count, descriptions);
+
+	name = g_file_get_parse_name (action->target_file);
+	descriptions[1] = g_strdup_printf (_("Create an empty file '%s'"), name);
+
+	labels[0] = g_strdup (_("_Undo Create Empty File"));
+	labels[1] = g_strdup (_("_Redo Create Empty File"));
+
+	g_free (name);
+}
+
+static void
+create_from_template_description_func (UndoData *action,
+				       guint count,
+				       gchar **labels,
+				       gchar **descriptions)
+{
+	char *name;
+
+	create_undo_common (action, count, descriptions);
+
+	name = g_file_get_parse_name (action->target_file);
+	descriptions[1] = g_strdup_printf (_("Create new file '%s' from template "), name);
+	g_free (name);
+
+	labels[0] = g_strdup (_("_Undo Create from Template"));
+	labels[1] = g_strdup (_("_Redo Create from Template"));
+}
+
+static void
+create_folder_description_func (UndoData *action,
+				guint count,
+				gchar **labels,
+				gchar **descriptions)
+{
+	char *name;
+
+	create_undo_common (action, count, descriptions);
+
+	name = g_file_get_parse_name (action->target_file);
+	descriptions[1] = g_strdup_printf (_("Create a new folder '%s'"), name);
+
+	labels[0] = g_strdup (_("_Undo Create Folder"));
+	labels[1] = g_strdup (_("_Redo Create Folder"));
+
+	g_free (name);
+}
+
+static void
+trash_description_func (UndoData *action,
+			guint count,
+			gchar **labels,
+			gchar **descriptions)
+{
+	count = g_hash_table_size (action->trashed);
+
+	if (count != 1) {
+		descriptions[0] = g_strdup_printf (_("Restore %d items from trash"), count);
+		descriptions[1] = g_strdup_printf (_("Move %d items to trash"), count);
+	} else {
+		GList *keys;
+		char *name, *orig_path;
+		GFile *file;
+
+		keys = g_hash_table_get_keys (action->trashed);
+		file = g_file_new_for_commandline_arg (keys->data);
+		name = g_file_get_basename (file);
+		orig_path = g_file_get_path (file);
+		descriptions[0] = g_strdup_printf (_("Restore '%s' to '%s'"), name, orig_path);
+
+		g_free (name);
+		g_free (orig_path);
+		g_list_free (keys);
+		g_object_unref (file);
+
+		name = g_file_get_parse_name (action->target_file);
+		descriptions[1] = g_strdup_printf (_("Move '%s' to trash"), name);
+
+		g_free (name);
+
+		labels[0] = g_strdup (_("_Undo Trash"));
+		labels[1] = g_strdup (_("_Redo Trash"));
+	}
+}
+
+static void
+restore_description_func (UndoData *action,
+			  guint count,
+			  gchar **labels,
+			  gchar **descriptions)
+{
+	if (count != 1) {
+		descriptions[0] = g_strdup_printf (_("Move %d items back to trash"), count);
+		descriptions[1] = g_strdup_printf (_("Restore %d items from trash"), count);
+	} else {
+		char *name;
+
+		name = get_first_target_short_name (action);
+		descriptions[0] = g_strdup_printf (_("Move '%s' back to trash"), name);
+		descriptions[1] = g_strdup_printf (_("Restore '%s' from trash"), name);
+		
+		g_free (name);
+
+		labels[0] = g_strdup (_("_Undo Restore from Trash"));
+		labels[1] = g_strdup (_("_Redo Restore from Trash"));
+	}
+}
+
+static void
+create_link_description_func (UndoData *action,
+			      guint count,
+			      gchar **labels,
+			      gchar **descriptions)
+{
+	if (count != 1) {
+		descriptions[0] = g_strdup_printf (_("Delete links to %d items"), count);
+		descriptions[1] = g_strdup_printf (_("Create links to %d items"), count);
+	} else {
+		char *name;
+
+		name = get_first_target_short_name (action);
+		descriptions[0] = g_strdup_printf (_("Delete link to '%s'"), name);
+		descriptions[1] = g_strdup_printf (_("Create link to '%s'"), name);
+
+		labels[0] = g_strdup (_("_Undo Create Link"));
+		labels[1] = g_strdup (_("_Redo Create Link"));
+ 
+		g_free (name);
+	}
+}
+
+static void
+recursive_permissions_description_func (UndoData *action,
+					guint count,
+					gchar **labels,
+					gchar **descriptions)
+{
+	char *name;
+
+	name = g_file_get_path (action->dest_dir);
+
+	descriptions[0] = g_strdup_printf (_("Restore original permissions of items enclosed in '%s'"), name);
+	descriptions[1] = g_strdup_printf (_("Set permissions of items enclosed in '%s'"), name);
+
+	labels[0] = g_strdup (_("_Undo Change Permissions"));
+	labels[1] = g_strdup (_("_Redo Change Permissions"));
+	
+	g_free (name);
+}
+
+static void
+set_permissions_description_func (UndoData *action,
+				  guint count,
+				  gchar **labels,
+				  gchar **descriptions)
+{
+	char *name;
+
+	name = g_file_get_parse_name (action->target_file);
+	descriptions[0] = g_strdup_printf (_("Restore original permissions of '%s'"), name);
+	descriptions[1] = g_strdup_printf (_("Set permissions of '%s'"), name);
+
+	labels[0] = g_strdup (_("_Undo Change Permissions"));
+	labels[1] = g_strdup (_("_Redo Change Permissions"));
+	
+	g_free (name);
+}
+
+static void
+change_group_description_func (UndoData *action,
+			       guint count,
+			       gchar **labels,
+			       gchar **descriptions)
+{
+	gchar *name;
+
+	name = g_file_get_parse_name (action->target_file);
+	descriptions[0] = g_strdup_printf (_("Restore group of '%s' to '%s'"),
+					   name, action->original_name);
+	descriptions[1] = g_strdup_printf (_("Set group of '%s' to '%s'"),
+					   name, action->new_name);
+
+	labels[0] = g_strdup (_("_Undo Change Group"));
+	labels[1] = g_strdup (_("_Redo Change Group"));
+
+	g_free (name);
+}
+
+static void
+change_owner_description_func (UndoData *action,
+			       guint count,
+			       gchar **labels,
+			       gchar **descriptions)
+{
+	gchar *name;
+
+	name = g_file_get_parse_name (action->target_file);
+	descriptions[0] = g_strdup_printf (_("Restore owner of '%s' to '%s'"),
+					   name, action->original_name);
+	descriptions[1] = g_strdup_printf (_("Set owner of '%s' to '%s'"),
+					   name, action->new_name);
+
+	labels[0] = g_strdup (_("_Undo Change Owner"));
+	labels[1] = g_strdup (_("_Redo Change Owner"));
+
+	g_free (name);
+}
+
+static UndoData *
+create_from_type (NautilusUndoStackActionType type)
+{
+	struct {
+		void (* undo_func)               (NautilusUndoStackActionData *data);
+		void (* redo_func)               (NautilusUndoStackActionData *data);
+		void (* strings_func)            (NautilusUndoStackActionData *data,
+						  guint count,
+						  gchar **labels,
+						  gchar **descriptions);
+
+	} const mappings[NAUTILUS_UNDO_STACK_NUM_TYPES] = {
+		/* copy action */
+		{ copy_or_link_undo_func, copy_redo_func,
+		  copy_description_func },
+		/* duplicate action */
+		{ copy_or_link_undo_func, duplicate_redo_func,
+		  duplicate_description_func },
+		/* move action */
+		{ move_undo_func, move_restore_redo_func,
+		  move_description_func },
+		/* rename action */
+		{ rename_undo_func, rename_redo_func,
+		  rename_description_func },
+		/* create empty action */
+		{ create_undo_func, create_empty_redo_func,
+		  create_empty_description_func },
+		/* create from template action */
+		{ create_undo_func, create_from_template_redo_func,
+		  create_from_template_description_func },
+		/* create folder action */
+		{ create_undo_func, create_folder_redo_func,
+		  create_folder_description_func },
+		/* move to trash action */
+		{ trash_undo_func, trash_redo_func,
+		  trash_description_func },
+		/* restore from trash action */
+		{ restore_undo_func, move_restore_redo_func,
+		  restore_description_func },
+		/* create link action */
+		{ create_undo_func, create_link_redo_func,
+		  create_link_description_func },
+		/* recursive permissions action */
+		{ recursive_permissions_undo_func, recursive_permissions_redo_func,
+		  recursive_permissions_description_func },
+		/* set permissions action */
+		{ set_permissions_undo_func, set_permissions_redo_func,
+		  set_permissions_description_func },
+		/* change group action */
+		{ change_group_undo_func, change_group_redo_func,
+		  change_group_description_func },
+		/* change owner action */
+		{ change_owner_undo_func, change_owner_redo_func,
+		  change_owner_description_func },
+	};
+
+	UndoData *retval;
+
+	retval = g_slice_new0 (UndoData);
+	retval->undo_func = mappings[type].undo_func;
+	retval->redo_func = mappings[type].redo_func;
+	retval->strings_func = mappings[type].strings_func;
+
+	return retval;
+}
+
+NautilusUndoStackActionData *
+nautilus_undo_stack_action_data_new (NautilusUndoStackActionType type,
+                                     gint                        items_count)
+{
+	NautilusUndoStackActionData *data;
+
+	data = create_from_type (type);
+	data->type = type;
+	data->count = items_count;
+
+	return data;
+}
+
diff --git a/libnautilus-private/nautilus-undostack-actions.h b/libnautilus-private/nautilus-undostack-actions.h
new file mode 100644
index 0000000..4fa83e4
--- /dev/null
+++ b/libnautilus-private/nautilus-undostack-actions.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-undostack-manager.h - Manages undo/redo of file operations
+ *
+ * Copyright (C) 2007-2010 Amos Brocco
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Amos Brocco <amos brocco unifr ch>
+ *          Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#ifndef __NAUTILUS_UNDOSTACK_ACTIONS_H__
+#define __NAUTILUS_UNDOSTACK_ACTIONS_H__
+
+#include <glib.h>
+#include <libnautilus-private/nautilus-undostack-types.h>
+
+NautilusUndoStackActionData * nautilus_undo_stack_action_data_new (NautilusUndoStackActionType type,
+                                                                   gint items_count);
+
+void nautilus_undo_stack_action_data_free (NautilusUndoStackActionData *action);
+
+#endif /* __NAUTILUS_UNDOSTACK_ACTIONS_H__ */
diff --git a/libnautilus-private/nautilus-undostack-manager.c b/libnautilus-private/nautilus-undostack-manager.c
index 88beb9c..4cb2d3c 100644
--- a/libnautilus-private/nautilus-undostack-manager.c
+++ b/libnautilus-private/nautilus-undostack-manager.c
@@ -1,4 +1,5 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
 /* nautilus-undostack-manager.h - Manages undo/redo of file operations
  *
  * Copyright (C) 2007-2010 Amos Brocco
@@ -23,11 +24,15 @@
  *          Cosimo Cecchi <cosimoc redhat com>
  *
  */
+
 #include <config.h>
 
 #include "nautilus-undostack-manager.h"
+
 #include "nautilus-file-operations.h"
 #include "nautilus-file.h"
+#include "nautilus-undostack-actions.h"
+#include "nautilus-undostack-types.h"
 
 #include <gio/gio.h>
 #include <glib.h>
@@ -39,80 +44,6 @@
 /* Default depth of the undo/redo stack. */
 #define DEFAULT_UNDO_DEPTH 32
 
-struct _NautilusUndoStackActionData {
-	/* Common stuff */
-	NautilusUndoStackActionType type;
-
-	void (* undo_func) (NautilusUndoStackActionData *data);
-	void (* redo_func) (NautilusUndoStackActionData *data);
-
-	NautilusUndoStackFinishCallback callback;
-	gpointer callback_user_data;
-
-	NautilusUndoStackManager *manager;
-	eel_boolean_bit is_valid : 1;
-	eel_boolean_bit locked : 1;	/* True if the action is being undone/redone */
-	eel_boolean_bit freed : 1;	/* True if the action must be freed after undo/redo */
-	guint count;			/* Number of items */
-
-	void    (* strings_func) (NautilusUndoStackActionData *data,
-				  guint count,
-				  gchar **labels,
-				  gchar **descriptions);
-
-	gchar *undo_label;
-	gchar *redo_label;
-	gchar *undo_description;
-	gchar *redo_description;
-
-	/* Copy / Move stuff */
-	GFile *src_dir;
-	GFile *dest_dir;
-	GList *sources;	     /* Relative to src_dir */
-	GList *destinations; /* Relative to dest_dir */
-
-	/* Create new file/folder stuff/set permissions */
-	char *template;
-	GFile *target_file;
-
-	/* Rename stuff */
-	GFile *old_file;
-	GFile *new_file;
-
-	/* Trash stuff */
-	GHashTable *trashed;
-
-	/* Recursive change permissions stuff */
-	GHashTable *original_permissions;
-	guint32 dir_mask;
-	guint32 dir_permissions;
-	guint32 file_mask;
-	guint32 file_permissions;
-
-	/* Single file change permissions stuff */
-	guint32 current_permissions;
-	guint32 new_permissions;
-
-	/* Group */
-	char *original_name;
-	char *new_name;
-};
-
-typedef struct _NautilusUndoStackActionData UndoData;
-
-struct _NautilusUndoStackManagerPrivate
-{
-	GQueue *stack;
-
-	/* Used to protect access to stack (because of async file ops) */
-	GMutex *mutex;
-
-	guint undo_levels;
-	guint index;
-	guint undo_redo_flag : 1;
-	guint confirm_delete : 1;
-};
-
 #define NAUTILUS_UNDO_STACK_MANAGER_GET_PRIVATE(o)	\
 	 (G_TYPE_INSTANCE_GET_PRIVATE ((o), NAUTILUS_TYPE_UNDO_STACK_MANAGER, NautilusUndoStackManagerPrivate))
 
@@ -138,17 +69,7 @@ static NautilusUndoStackActionData * get_next_redo_action (NautilusUndoStackMana
 static NautilusUndoStackActionData * get_next_undo_action (NautilusUndoStackManagerPrivate *priv);
 
 static void do_menu_update (NautilusUndoStackManager * manager);
-static void undo_redo_done_transfer_callback (GHashTable * debuting_uris, gpointer data);
-static void undo_redo_op_callback (gpointer callback_data);
-static void undo_redo_done_rename_callback (NautilusFile * file, GFile * result_location, GError * error, gpointer callback_data);
-static void undo_redo_done_delete_callback (GHashTable * debuting_uris, gboolean user_cancel, gpointer callback_data);
-static void undo_redo_done_create_callback (GFile * new_file, gpointer callback_data);
 static void clear_redo_actions (NautilusUndoStackManagerPrivate *priv);
-static char *get_first_target_short_name (NautilusUndoStackActionData *action);
-static GList *construct_gfile_list (const GList * urilist, GFile * parent);
-static GList *construct_gfile_list_from_uri (char *uri);
-static GList *uri_list_to_gfile_list (GList * urilist);
-static GHashTable *retrieve_files_to_restore (GHashTable * trashed);
 
 static NautilusUndoStackManager *singleton = NULL;
 
@@ -170,47 +91,6 @@ nautilus_undo_stack_manager_init (NautilusUndoStackManager * self)
 }
 
 static void
-undo_stack_action_data_free (NautilusUndoStackActionData *action)
-{
-	g_return_if_fail (action != NULL);
-
-	g_free (action->template);
-
-	g_free (action->undo_label);
-	g_free (action->undo_description);
-	g_free (action->redo_label);
-	g_free (action->redo_description);
-
-	g_free (action->original_name);
-	g_free (action->new_name);
-
-	if (action->sources) {
-		g_list_free_full (action->sources, g_free);
-	}
-
-	if (action->destinations) {
-		g_list_free_full (action->destinations, g_free);
-	}
-
-	if (action->trashed) {
-		g_hash_table_destroy (action->trashed);
-	}
-
-	if (action->original_permissions) {
-		g_hash_table_destroy (action->original_permissions);
-	}
-
-	g_clear_object (&action->old_file);
-	g_clear_object (&action->target_file);
-	g_clear_object (&action->src_dir);
-	g_clear_object (&action->dest_dir);
-
-	g_free (action->new_file);
-
-	g_slice_free (NautilusUndoStackActionData, action);
-}
-
-static void
 nautilus_undo_stack_manager_finalize (GObject * object)
 {
 	NautilusUndoStackManager *self = NAUTILUS_UNDO_STACK_MANAGER (object);
@@ -218,7 +98,7 @@ nautilus_undo_stack_manager_finalize (GObject * object)
 
 	g_mutex_lock (priv->mutex);
 	
-	g_queue_foreach (priv->stack, (GFunc) undo_stack_action_data_free, NULL);
+	g_queue_foreach (priv->stack, (GFunc) nautilus_undo_stack_action_data_free, NULL);
 	g_queue_free (priv->stack);
 
 	g_mutex_unlock (priv->mutex);
@@ -462,405 +342,6 @@ nautilus_undo_stack_manager_request_menu_update (NautilusUndoStackManager *manag
 	do_menu_update (manager);
 }
 
-
-/* undo helpers */
-
-static void
-delete_uris (NautilusUndoStackManager *self,
-	     GList *uris,
-	     UndoData *action)
-{
-	if (self->priv->confirm_delete) {
-		nautilus_file_operations_delete (uris, NULL,
-						 undo_redo_done_delete_callback, action);
-	} else {
-		self->priv->undo_redo_flag = FALSE;
-
-		/* We skip the confirmation message */
-		GList *f;
-		for (f = uris; f != NULL; f = f->next) {
-			g_file_delete (f->data, NULL, NULL);
-		}
-
-		/* Here we must do what's necessary for the callback */
-		undo_redo_done_transfer_callback (NULL, action);
-	}
-}
-
-static void
-create_undo_func (UndoData *action)
-{
-	GList *uris;
-	gchar *uri;
-
-	uri = g_file_get_uri (action->target_file);
-	uris = construct_gfile_list_from_uri (uri);
-
-	delete_uris (action->manager, uris, action);
-
-	g_free (uri);
-	g_list_free_full (uris, g_object_unref);
-}
-
-static void
-copy_or_link_undo_func (UndoData *action)
-{
-	GList *uris;
-
-	uris = construct_gfile_list (action->destinations, action->dest_dir);
-	uris = g_list_reverse (uris); /* Deleting must be done in reverse */
-
-	delete_uris (action->manager, uris, action);
-
-	g_list_free_full (uris, g_object_unref);
-}
-
-static void
-restore_undo_func (UndoData *action)
-{
-	GList *uris;
-
-	uris = construct_gfile_list (action->destinations, action->dest_dir);
-	nautilus_file_operations_trash_or_delete (uris, NULL,
-						  undo_redo_done_delete_callback, action);
-
-	g_list_free_full (uris, g_object_unref);
-}
-
-static void
-trash_undo_func (UndoData *action)
-{
-	NautilusUndoStackManagerPrivate *priv = action->manager->priv;
-	GHashTable *files_to_restore;
-
-	/* Internally managed op, clear the undo_redo_flag.
-	 * Same as calling nautilus_undo_stack_manager_is_undo_redo()
-	 * minus the function call and unused return val.
-	 */
-
-	priv->undo_redo_flag = FALSE;
-	files_to_restore = retrieve_files_to_restore (action->trashed);
-
-	if (g_hash_table_size (files_to_restore) > 0) {
-		GList *gfiles_in_trash, *l;
-		GFile *item;
-		GFile *dest;
-		char *value;
-
-		gfiles_in_trash = g_hash_table_get_keys (files_to_restore);
-
-		for (l = gfiles_in_trash; l != NULL; l = l->next) {
-			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);
-		}
-
-		g_list_free (gfiles_in_trash);
-	}
-
-	g_hash_table_destroy (files_to_restore);
-
-	/* Here we must do what's necessary for the callback */
-	undo_redo_done_transfer_callback (NULL, action);
-}
-
-static void
-move_undo_func (UndoData *action)
-{
-	GList *uris;
-
-	uris = construct_gfile_list (action->destinations, action->dest_dir);
-	nautilus_file_operations_move (uris, NULL,
-				       action->src_dir, NULL,
-				       undo_redo_done_transfer_callback, action);
-
-	g_list_free_full (uris, g_object_unref);
-}
-
-static void
-rename_undo_func (UndoData *action)
-{
-	gchar *new_name;
-	NautilusFile *file;
-
-	new_name = g_file_get_basename (action->old_file);
-	file = nautilus_file_get (action->new_file);
-
-	nautilus_file_rename (file, new_name,
-			      undo_redo_done_rename_callback, action);
-
-	nautilus_file_unref (file);
-	g_free (new_name);
-}
-
-static void
-set_permissions_undo_func (UndoData *action)
-{
-	NautilusFile *file;
-
-	file = nautilus_file_get (action->target_file);
-
-	nautilus_file_set_permissions (file,
-				       action->current_permissions,
-				       undo_redo_done_rename_callback, action);
-
-	nautilus_file_unref (file);
-}
-
-static void
-recursive_permissions_undo_func (UndoData *action)
-{
-	NautilusUndoStackManagerPrivate *priv = action->manager->priv;
-
-	/* Internally managed op, clear the undo_redo_flag. */
-	priv->undo_redo_flag = FALSE;
-
-	if (g_hash_table_size (action->original_permissions) > 0) {
-		GList *gfiles_list;
-		guint32 *perm;
-		GList *l;
-		GFile *dest;
-		char *item;
-
-		gfiles_list = g_hash_table_get_keys (action->original_permissions);
-		for (l = gfiles_list; l != NULL; l = l->next) {
-			item = l->data;
-			perm = g_hash_table_lookup (action->original_permissions, item);
-			dest = g_file_new_for_uri (item);
-			g_file_set_attribute_uint32 (dest,
-						     G_FILE_ATTRIBUTE_UNIX_MODE,
-						     *perm, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
-			g_object_unref (dest);
-		}
-
-		g_list_free (gfiles_list);
-		/* Here we must do what's necessary for the callback */
-		undo_redo_done_transfer_callback (NULL, action);
-	}
-}
-
-static void
-change_group_undo_func (UndoData *action)
-{
-	NautilusFile *file;
-
-	file = nautilus_file_get (action->target_file);
-
-	nautilus_file_set_group (file,
-				 action->original_name,
-				 undo_redo_done_rename_callback, action);
-
-	nautilus_file_unref (file);
-}
-
-static void
-change_owner_undo_func (UndoData *action)
-{
-	NautilusFile *file;
-
-	file = nautilus_file_get (action->target_file);
-
-	nautilus_file_set_owner (file,
-				 action->original_name,
-				 undo_redo_done_rename_callback, action);
-
-	nautilus_file_unref (file);
-}
-
-/* redo helpers */
-
-static void
-copy_redo_func (UndoData *action)
-{
-	GList *locations;
-
-	locations = construct_gfile_list (action->sources, action->src_dir);
-	nautilus_file_operations_copy (locations, NULL,
-				       action->dest_dir, NULL,
-				       undo_redo_done_transfer_callback, action);
-
-	g_list_free_full (locations, g_object_unref);
-}
-
-static void
-create_from_template_redo_func (UndoData *action)
-{
-	GFile *parent;
-	gchar *parent_uri, *new_name;
-
-	parent = g_file_get_parent (action->target_file);
-	parent_uri = g_file_get_uri (parent);
-	new_name = g_file_get_parse_name (action->target_file);
-	nautilus_file_operations_new_file_from_template (NULL, NULL,
-							 parent_uri, new_name,
-							 action->template,
-							 undo_redo_done_create_callback, action);
-
-	g_free (parent_uri);
-	g_free (new_name);
-	g_object_unref (parent);
-}
-
-static void
-duplicate_redo_func (UndoData *action)
-{
-	GList *locations;
-
-	locations = construct_gfile_list (action->sources, action->src_dir);
-	nautilus_file_operations_duplicate (locations, NULL, NULL,
-					    undo_redo_done_transfer_callback, action);
-
-	g_list_free_full (locations, g_object_unref);
-}
-
-static void
-move_restore_redo_func (UndoData *action)
-{
-	GList *locations;
-
-	locations = construct_gfile_list (action->sources, action->src_dir);
-	nautilus_file_operations_move (locations, NULL,
-				       action->dest_dir, NULL,
-				       undo_redo_done_transfer_callback, action);
-
-	g_list_free_full (locations, g_object_unref);
-}
-
-static void
-rename_redo_func (UndoData *action)
-{
-	gchar *new_name;
-	NautilusFile *file;
-
-	new_name = g_file_get_basename (action->new_file);
-	file = nautilus_file_get (action->old_file);
-	nautilus_file_rename (file, new_name,
-			      undo_redo_done_rename_callback, action);
-
-	nautilus_file_unref (file);
-	g_free (new_name);
-}
-
-static void
-create_empty_redo_func (UndoData *action)
-{
-	GFile *parent;
-	gchar *parent_uri;
-	gchar *new_name;
-
-	parent = g_file_get_parent (action->target_file);
-	parent_uri = g_file_get_uri (parent);
-	new_name = g_file_get_parse_name (action->target_file);
-	nautilus_file_operations_new_file (NULL, NULL, parent_uri,
-					   new_name,
-					   action->template,
-					   action->count, undo_redo_done_create_callback, action);
-
-	g_free (parent_uri);
-	g_free (new_name);
-	g_object_unref (parent);
-}
-
-static void
-create_folder_redo_func (UndoData *action)
-{
-	GFile *parent;
-	gchar *parent_uri;
-
-	parent = g_file_get_parent (action->target_file);
-	parent_uri = g_file_get_uri (parent);
-	nautilus_file_operations_new_folder (NULL, NULL, parent_uri,
-					     undo_redo_done_create_callback, action);
-
-	g_free (parent_uri);
-	g_object_unref (parent);
-}
-
-static void
-trash_redo_func (UndoData *action)
-{
-	if (g_hash_table_size (action->trashed) > 0) {
-		GList *uri_to_trash, *locations;
-
-		uri_to_trash = g_hash_table_get_keys (action->trashed);
-		locations = uri_list_to_gfile_list (uri_to_trash);
-		nautilus_file_operations_trash_or_delete (locations, NULL,
-							  undo_redo_done_delete_callback, action);
-		g_list_free (uri_to_trash);
-		g_list_free_full (locations, g_object_unref);
-	}
-}
-
-static void
-create_link_redo_func (UndoData *action)
-{
-	GList *locations;
-
-	locations = construct_gfile_list (action->sources, action->src_dir);
-	nautilus_file_operations_link (locations, NULL,
-				       action->dest_dir, NULL,
-				       undo_redo_done_transfer_callback, action);
-	g_list_free_full (locations, g_object_unref);
-}
-
-static void
-set_permissions_redo_func (UndoData *action)
-{
-	NautilusFile *file;
-
-	file = nautilus_file_get (action->target_file);
-	nautilus_file_set_permissions (file, action->new_permissions,
-				       undo_redo_done_rename_callback, action);
-
-	nautilus_file_unref (file);
-}
-
-static void
-recursive_permissions_redo_func (UndoData *action)
-{
-	gchar *parent_uri;
-
-	parent_uri = g_file_get_uri (action->dest_dir);
-	nautilus_file_set_permissions_recursive (parent_uri,
-						 action->file_permissions,
-						 action->file_mask,
-						 action->dir_permissions,
-						 action->dir_mask,
-						 undo_redo_op_callback,
-						 action);
-	g_free (parent_uri);
-}
-
-static void
-change_group_redo_func (UndoData *action)
-{
-	NautilusFile *file;
-
-	file = nautilus_file_get (action->target_file);
-	nautilus_file_set_group (file,
-				 action->new_name,
-				 undo_redo_done_rename_callback,
-				 action);
-
-	nautilus_file_unref (file);
-}
-
-static void
-change_owner_redo_func (UndoData *action)
-{
-	NautilusFile *file;
-
-	file = nautilus_file_get (action->target_file);
-	nautilus_file_set_owner (file,
-				 action->new_name,
-				 undo_redo_done_rename_callback,
-				 action);
-
-	nautilus_file_unref (file);
-}
-
 static void
 do_undo_redo (NautilusUndoStackManager *self,
 	      gboolean undo,
@@ -936,7 +417,7 @@ nautilus_undo_stack_manager_add_action (NautilusUndoStackManager    *manager,
 	priv = manager->priv;
 
 	if (!(action && action->is_valid)) {
-		undo_stack_action_data_free (action);
+		nautilus_undo_stack_action_data_free (action);
 		return;
 	}
 
@@ -1302,7 +783,7 @@ stack_clear_n_oldest (GQueue * stack, guint n)
 		if (action->locked) {
 			action->freed = TRUE;
 		} else {
-			undo_stack_action_data_free (action);
+			nautilus_undo_stack_action_data_free (action);
 		}
 	}
 }
@@ -1330,7 +811,7 @@ clear_redo_actions (NautilusUndoStackManagerPrivate *priv)
 	while (priv->index > 0) {
 		NautilusUndoStackActionData *head;
 		head = (NautilusUndoStackActionData *)g_queue_pop_head (priv->stack);
-		undo_stack_action_data_free (head);
+		nautilus_undo_stack_action_data_free (head);
 		priv->index--;
 	}
 }
@@ -1351,62 +832,6 @@ stack_push_action (NautilusUndoStackManagerPrivate *priv,
 	}
 }
 
-static char *
-get_first_target_short_name (NautilusUndoStackActionData *action)
-{
-	GList *targets_first;
-	char *file_name;
-
-	g_assert (action != NULL);
-
-	targets_first = g_list_first (action->destinations);
-	file_name = g_strdup (targets_first->data);
-
-	return file_name;
-}
-
-static void
-undo_redo_done_transfer_callback (GHashTable * debuting_uris, gpointer data)
-{
-	NautilusUndoStackActionData *action;
-
-	action = (NautilusUndoStackActionData *) data;
-
-	/* If the action needed to be freed but was locked, free now */
-	if (action->freed) {
-		undo_stack_action_data_free (action);
-	} else {
-		action->locked = FALSE;
-	}
-
-	/* Update menus */
-	do_menu_update (action->manager);
-}
-
-static void
-undo_redo_done_delete_callback (GHashTable *debuting_uris, gboolean user_cancel, gpointer callback_data)
-{
-	undo_redo_done_transfer_callback (debuting_uris, callback_data);
-}
-
-static void
-undo_redo_done_create_callback (GFile * new_file, gpointer callback_data)
-{
-	undo_redo_done_transfer_callback (NULL, callback_data);
-}
-
-static void
-undo_redo_op_callback (gpointer callback_data)
-{
-	undo_redo_done_transfer_callback (NULL, callback_data);
-}
-
-static void
-undo_redo_done_rename_callback (NautilusFile * file, GFile * result_location, GError * error, gpointer callback_data)
-{
-	undo_redo_done_transfer_callback (NULL, callback_data);
-}
-
 static gboolean
 can_undo (NautilusUndoStackManagerPrivate *priv)
 {
@@ -1504,529 +929,3 @@ do_menu_update (NautilusUndoStackManager * manager)
 	/* Note: we do not own labels and descriptions, they are part of the action. */
 	g_slice_free (NautilusUndoStackMenuData, data);
 }
-
-static GList *
-construct_gfile_list (const GList * urilist, GFile * parent)
-{
-	const GList *l;
-	GList *file_list = NULL;
-	GFile *file;
-
-	for (l = urilist; l != NULL; l = l->next) {
-		file = g_file_get_child (parent, l->data);
-		file_list = g_list_append (file_list, file);
-	}
-
-	return file_list;
-}
-
-static GList *
-construct_gfile_list_from_uri (char *uri)
-{
-	GList *file_list = NULL;
-	GFile *file;
-
-	file = g_file_new_for_uri (uri);
-	file_list = g_list_append (file_list, file);
-
-	return file_list;
-}
-
-static GList *
-uri_list_to_gfile_list (GList * urilist)
-{
-	const GList *l;
-	GList *file_list = NULL;
-	GFile *file;
-
-	for (l = urilist; l != NULL; l = l->next) {
-		file = g_file_new_for_uri (l->data);
-		file_list = g_list_append (file_list, file);
-	}
-
-	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;
-}
-
-static void
-copy_description_func (UndoData *action,
-		       guint count,
-		       gchar **labels,
-		       gchar **descriptions)
-{
-	gchar *destination;
-
-	destination = g_file_get_path (action->dest_dir);
-
-	if (count != 1) {
-		descriptions[0] = g_strdup_printf (_("Delete %d copied items"), count);
-		descriptions[1] = g_strdup_printf (_("Copy %d items to '%s'"), count, destination);
-
-		labels[0] = g_strdup_printf (_("_Undo Copy %d items"), count);
-		labels[1] = g_strdup_printf (_("_Redo Copy %d items"), count);
-	} else {
-		gchar *name;
-
-		name = get_first_target_short_name (action);
-		descriptions[0] = g_strdup_printf (_("Delete '%s'"), name);
-		descriptions[1] = g_strdup_printf (_("Copy '%s' to '%s'"), name, destination);
-
-		labels[0] = g_strdup (_("_Undo Copy"));
-		labels[1] = g_strdup (_("_Redo Copy"));
-
-		g_free (name);
-	}
-}
-
-static void
-duplicate_description_func (UndoData *action,
-			    guint count,
-			    gchar **labels,
-			    gchar **descriptions)
-{
-	gchar *destination;
-
-	destination = g_file_get_path (action->dest_dir);
-
-	if (count != 1) {
-		descriptions[0] = g_strdup_printf (_("Delete %d duplicated items"), count);
-		descriptions[1] = g_strdup_printf (_("Duplicate of %d items in '%s'"),
-						   count, destination);
-
-		labels[0] = g_strdup_printf (_("_Undo Duplicate %d items"), count);
-		labels[1] = g_strdup_printf (_("_Redo Duplicate %d items"), count);
-	} else {
-		char *name;
-
-		name = get_first_target_short_name (action);
-		descriptions[0] = g_strdup_printf (_("Delete '%s'"), name);
-		descriptions[1] = g_strdup_printf (_("Duplicate '%s' in '%s'"),
-						   name, destination);
-
-		labels[0] = g_strdup (_("_Undo Duplicate"));
-		labels[1] = g_strdup (_("_Redo Duplicate"));
-
-		g_free (name);
-	}
-
-}
-
-static void
-move_description_func (UndoData *action,
-		       guint count,
-		       gchar **labels,
-		       gchar **descriptions)
-{
-	gchar *source, *destination;
-
-        source = g_file_get_path (action->src_dir);
-	destination = g_file_get_path (action->dest_dir);
-
-	if (count != 1) {
-		descriptions[0] = g_strdup_printf (_("Move %d items back to '%s'"), count, source);
-		descriptions[1] = g_strdup_printf (_("Move %d items to '%s'"), count, destination);
-
-		labels[0] = g_strdup_printf (_("_Undo Move %d items"), count);
-		labels[1] = g_strdup_printf (_("_Redo Move %d items"), count);
-	} else {
-		char *name;
-
-		name = get_first_target_short_name (action);
-		descriptions[0] = g_strdup_printf (_("Move '%s' back to '%s'"), name, source);
-		descriptions[1] = g_strdup_printf (_("Move '%s' to '%s'"), name, destination);
-
-		labels[0] = g_strdup (_("_Undo Move"));
-		labels[1] = g_strdup (_("_Redo Move"));
-
-		g_free (name);
-	}
-}
-
-static void
-rename_description_func (UndoData *action,
-			 guint count,
-			 gchar **labels,
-			 gchar **descriptions)
-{
-	gchar *new_name, *old_name;
-
-	new_name = g_file_get_parse_name (action->new_file);
-	old_name = g_file_get_parse_name (action->old_file);
-
-	descriptions[0] = g_strdup_printf (_("Rename '%s' as '%s'"), new_name, old_name);
-	descriptions[1] = g_strdup_printf (_("Rename '%s' as '%s'"), old_name, new_name);
-
-	labels[0] = g_strdup (_("_Undo Rename"));
-	labels[1] = g_strdup (_("_Redo Rename"));
-
-	g_free (old_name);
-	g_free (new_name);
-}
-
-static void
-create_undo_common (UndoData *action,
-		    guint count,
-		    gchar **descriptions)
-{
-            char *name;
-
-	    name = g_file_get_parse_name (action->target_file);
-	    descriptions[0] = g_strdup_printf (_("Delete '%s'"), name);
-
-	    g_free (name);
-}
-
-static void
-create_empty_description_func (UndoData *action,
-			       guint count,
-			       gchar **labels,
-			       gchar **descriptions)
-{
-	gchar *name;
-
-	create_undo_common (action, count, descriptions);
-
-	name = g_file_get_parse_name (action->target_file);
-	descriptions[1] = g_strdup_printf (_("Create an empty file '%s'"), name);
-
-	labels[0] = g_strdup (_("_Undo Create Empty File"));
-	labels[1] = g_strdup (_("_Redo Create Empty File"));
-
-	g_free (name);
-}
-
-static void
-create_from_template_description_func (UndoData *action,
-				       guint count,
-				       gchar **labels,
-				       gchar **descriptions)
-{
-	char *name;
-
-	create_undo_common (action, count, descriptions);
-
-	name = g_file_get_parse_name (action->target_file);
-	descriptions[1] = g_strdup_printf (_("Create new file '%s' from template "), name);
-	g_free (name);
-
-	labels[0] = g_strdup (_("_Undo Create from Template"));
-	labels[1] = g_strdup (_("_Redo Create from Template"));
-}
-
-static void
-create_folder_description_func (UndoData *action,
-				guint count,
-				gchar **labels,
-				gchar **descriptions)
-{
-	char *name;
-
-	create_undo_common (action, count, descriptions);
-
-	name = g_file_get_parse_name (action->target_file);
-	descriptions[1] = g_strdup_printf (_("Create a new folder '%s'"), name);
-
-	labels[0] = g_strdup (_("_Undo Create Folder"));
-	labels[1] = g_strdup (_("_Redo Create Folder"));
-
-	g_free (name);
-}
-
-static void
-trash_description_func (UndoData *action,
-			guint count,
-			gchar **labels,
-			gchar **descriptions)
-{
-	count = g_hash_table_size (action->trashed);
-
-	if (count != 1) {
-		descriptions[0] = g_strdup_printf (_("Restore %d items from trash"), count);
-		descriptions[1] = g_strdup_printf (_("Move %d items to trash"), count);
-	} else {
-		GList *keys;
-		char *name, *orig_path;
-		GFile *file;
-
-		keys = g_hash_table_get_keys (action->trashed);
-		file = g_file_new_for_commandline_arg (keys->data);
-		name = g_file_get_basename (file);
-		orig_path = g_file_get_path (file);
-		descriptions[0] = g_strdup_printf (_("Restore '%s' to '%s'"), name, orig_path);
-
-		g_free (name);
-		g_free (orig_path);
-		g_list_free (keys);
-		g_object_unref (file);
-
-		name = g_file_get_parse_name (action->target_file);
-		descriptions[1] = g_strdup_printf (_("Move '%s' to trash"), name);
-
-		g_free (name);
-
-		labels[0] = g_strdup (_("_Undo Trash"));
-		labels[1] = g_strdup (_("_Redo Trash"));
-	}
-}
-
-static void
-restore_description_func (UndoData *action,
-			  guint count,
-			  gchar **labels,
-			  gchar **descriptions)
-{
-	if (count != 1) {
-		descriptions[0] = g_strdup_printf (_("Move %d items back to trash"), count);
-		descriptions[1] = g_strdup_printf (_("Restore %d items from trash"), count);
-	} else {
-		char *name;
-
-		name = get_first_target_short_name (action);
-		descriptions[0] = g_strdup_printf (_("Move '%s' back to trash"), name);
-		descriptions[1] = g_strdup_printf (_("Restore '%s' from trash"), name);
-		
-		g_free (name);
-
-		labels[0] = g_strdup (_("_Undo Restore from Trash"));
-		labels[1] = g_strdup (_("_Redo Restore from Trash"));
-	}
-}
-
-static void
-create_link_description_func (UndoData *action,
-			      guint count,
-			      gchar **labels,
-			      gchar **descriptions)
-{
-	if (count != 1) {
-		descriptions[0] = g_strdup_printf (_("Delete links to %d items"), count);
-		descriptions[1] = g_strdup_printf (_("Create links to %d items"), count);
-	} else {
-		char *name;
-
-		name = get_first_target_short_name (action);
-		descriptions[0] = g_strdup_printf (_("Delete link to '%s'"), name);
-		descriptions[1] = g_strdup_printf (_("Create link to '%s'"), name);
-
-		labels[0] = g_strdup (_("_Undo Create Link"));
-		labels[1] = g_strdup (_("_Redo Create Link"));
- 
-		g_free (name);
-	}
-}
-
-static void
-recursive_permissions_description_func (UndoData *action,
-					guint count,
-					gchar **labels,
-					gchar **descriptions)
-{
-	char *name;
-
-	name = g_file_get_path (action->dest_dir);
-
-	descriptions[0] = g_strdup_printf (_("Restore original permissions of items enclosed in '%s'"), name);
-	descriptions[1] = g_strdup_printf (_("Set permissions of items enclosed in '%s'"), name);
-
-	labels[0] = g_strdup (_("_Undo Change Permissions"));
-	labels[1] = g_strdup (_("_Redo Change Permissions"));
-	
-	g_free (name);
-}
-
-static void
-set_permissions_description_func (UndoData *action,
-				  guint count,
-				  gchar **labels,
-				  gchar **descriptions)
-{
-	char *name;
-
-	name = g_file_get_parse_name (action->target_file);
-	descriptions[0] = g_strdup_printf (_("Restore original permissions of '%s'"), name);
-	descriptions[1] = g_strdup_printf (_("Set permissions of '%s'"), name);
-
-	labels[0] = g_strdup (_("_Undo Change Permissions"));
-	labels[1] = g_strdup (_("_Redo Change Permissions"));
-	
-	g_free (name);
-}
-
-static void
-change_group_description_func (UndoData *action,
-			       guint count,
-			       gchar **labels,
-			       gchar **descriptions)
-{
-	gchar *name;
-
-	name = g_file_get_parse_name (action->target_file);
-	descriptions[0] = g_strdup_printf (_("Restore group of '%s' to '%s'"),
-					   name, action->original_name);
-	descriptions[1] = g_strdup_printf (_("Set group of '%s' to '%s'"),
-					   name, action->new_name);
-
-	labels[0] = g_strdup (_("_Undo Change Group"));
-	labels[1] = g_strdup (_("_Redo Change Group"));
-
-	g_free (name);
-}
-
-static void
-change_owner_description_func (UndoData *action,
-			       guint count,
-			       gchar **labels,
-			       gchar **descriptions)
-{
-	gchar *name;
-
-	name = g_file_get_parse_name (action->target_file);
-	descriptions[0] = g_strdup_printf (_("Restore owner of '%s' to '%s'"),
-					   name, action->original_name);
-	descriptions[1] = g_strdup_printf (_("Set owner of '%s' to '%s'"),
-					   name, action->new_name);
-
-	labels[0] = g_strdup (_("_Undo Change Owner"));
-	labels[1] = g_strdup (_("_Redo Change Owner"));
-
-	g_free (name);
-}
-
-static UndoData *
-create_from_type (NautilusUndoStackActionType type)
-{
-	struct {
-		void (* undo_func)               (NautilusUndoStackActionData *data);
-		void (* redo_func)               (NautilusUndoStackActionData *data);
-		void (* strings_func)            (NautilusUndoStackActionData *data,
-						  guint count,
-						  gchar **labels,
-						  gchar **descriptions);
-
-	} const mappings[NAUTILUS_UNDO_STACK_NUM_TYPES] = {
-		/* copy action */
-		{ copy_or_link_undo_func, copy_redo_func,
-		  copy_description_func },
-		/* duplicate action */
-		{ copy_or_link_undo_func, duplicate_redo_func,
-		  duplicate_description_func },
-		/* move action */
-		{ move_undo_func, move_restore_redo_func,
-		  move_description_func },
-		/* rename action */
-		{ rename_undo_func, rename_redo_func,
-		  rename_description_func },
-		/* create empty action */
-		{ create_undo_func, create_empty_redo_func,
-		  create_empty_description_func },
-		/* create from template action */
-		{ create_undo_func, create_from_template_redo_func,
-		  create_from_template_description_func },
-		/* create folder action */
-		{ create_undo_func, create_folder_redo_func,
-		  create_folder_description_func },
-		/* move to trash action */
-		{ trash_undo_func, trash_redo_func,
-		  trash_description_func },
-		/* restore from trash action */
-		{ restore_undo_func, move_restore_redo_func,
-		  restore_description_func },
-		/* create link action */
-		{ create_undo_func, create_link_redo_func,
-		  create_link_description_func },
-		/* recursive permissions action */
-		{ recursive_permissions_undo_func, recursive_permissions_redo_func,
-		  recursive_permissions_description_func },
-		/* set permissions action */
-		{ set_permissions_undo_func, set_permissions_redo_func,
-		  set_permissions_description_func },
-		/* change group action */
-		{ change_group_undo_func, change_group_redo_func,
-		  change_group_description_func },
-		/* change owner action */
-		{ change_owner_undo_func, change_owner_redo_func,
-		  change_owner_description_func },
-	};
-
-	UndoData *retval;
-
-	retval = g_slice_new0 (UndoData);
-	retval->undo_func = mappings[type].undo_func;
-	retval->redo_func = mappings[type].redo_func;
-	retval->strings_func = mappings[type].strings_func;
-
-	return retval;
-}
-
-NautilusUndoStackActionData *
-nautilus_undo_stack_action_data_new (NautilusUndoStackActionType type,
-                                     gint                        items_count)
-{
-	NautilusUndoStackActionData *data;
-
-	data = create_from_type (type);
-	data->type = type;
-	data->count = items_count;
-
-	return data;
-}
diff --git a/libnautilus-private/nautilus-undostack-manager.h b/libnautilus-private/nautilus-undostack-manager.h
index b90498b..1cd035e 100644
--- a/libnautilus-private/nautilus-undostack-manager.h
+++ b/libnautilus-private/nautilus-undostack-manager.h
@@ -29,7 +29,8 @@
 #include <gtk/gtk.h>
 #include <gio/gio.h>
 
-typedef struct _NautilusUndoStackManager NautilusUndoStackManager;
+#include <libnautilus-private/nautilus-undostack-types.h>
+
 typedef struct _NautilusUndoStackManagerClass NautilusUndoStackManagerClass;
 typedef struct _NautilusUndoStackManagerPrivate NautilusUndoStackManagerPrivate;
 
@@ -49,35 +50,6 @@ typedef struct _NautilusUndoStackManagerPrivate NautilusUndoStackManagerPrivate;
 	(G_TYPE_INSTANCE_GET_CLASS((object), NAUTILUS_TYPE_UNDO_STACK_MANAGER,\
 				   NautilusUndoStackManagerClass))
 
-typedef enum {
-	NAUTILUS_UNDO_STACK_COPY,
-	NAUTILUS_UNDO_STACK_DUPLICATE,
-	NAUTILUS_UNDO_STACK_MOVE,
-	NAUTILUS_UNDO_STACK_RENAME,
-	NAUTILUS_UNDO_STACK_CREATE_EMPTY_FILE,
-	NAUTILUS_UNDO_STACK_CREATE_FILE_FROM_TEMPLATE,
-	NAUTILUS_UNDO_STACK_CREATE_FOLDER,
-	NAUTILUS_UNDO_STACK_MOVE_TO_TRASH,
-	NAUTILUS_UNDO_STACK_RESTORE_FROM_TRASH,
-	NAUTILUS_UNDO_STACK_CREATE_LINK,
-	NAUTILUS_UNDO_STACK_RECURSIVE_SET_PERMISSIONS,
-	NAUTILUS_UNDO_STACK_SET_PERMISSIONS,
-	NAUTILUS_UNDO_STACK_CHANGE_GROUP,
-	NAUTILUS_UNDO_STACK_CHANGE_OWNER,
-	NAUTILUS_UNDO_STACK_NUM_TYPES,
-} NautilusUndoStackActionType;
-
-typedef struct _NautilusUndoStackActionData NautilusUndoStackActionData;
-
-typedef struct {
-	const char *undo_label;
-	const char *undo_description;
-	const char *redo_label;
-	const char *redo_description;
-} NautilusUndoStackMenuData;
-
-typedef void (*NautilusUndoStackFinishCallback) (gpointer data);
-
 struct _NautilusUndoStackManager {
 	GObject parent_instance;
 
diff --git a/libnautilus-private/nautilus-undostack-types.h b/libnautilus-private/nautilus-undostack-types.h
new file mode 100644
index 0000000..a6bb9a2
--- /dev/null
+++ b/libnautilus-private/nautilus-undostack-types.h
@@ -0,0 +1,138 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-undostack-manager.h - Manages undo/redo of file operations
+ *
+ * Copyright (C) 2007-2010 Amos Brocco
+ * Copyright (C) 2010 Red Hat, 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 Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Amos Brocco <amos brocco unifr ch>
+ *          Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#ifndef __NAUTILUS_UNDOSTACK_TYPES_H__
+#define __NAUTILUS_UNDOSTACK_TYPES_H__
+
+#include <glib.h>
+#include <gio/gio.h>
+
+typedef struct _NautilusUndoStackManager NautilusUndoStackManager;
+typedef void (* NautilusUndoStackFinishCallback) (gpointer data);
+
+typedef enum {
+	NAUTILUS_UNDO_STACK_COPY,
+	NAUTILUS_UNDO_STACK_DUPLICATE,
+	NAUTILUS_UNDO_STACK_MOVE,
+	NAUTILUS_UNDO_STACK_RENAME,
+	NAUTILUS_UNDO_STACK_CREATE_EMPTY_FILE,
+	NAUTILUS_UNDO_STACK_CREATE_FILE_FROM_TEMPLATE,
+	NAUTILUS_UNDO_STACK_CREATE_FOLDER,
+	NAUTILUS_UNDO_STACK_MOVE_TO_TRASH,
+	NAUTILUS_UNDO_STACK_RESTORE_FROM_TRASH,
+	NAUTILUS_UNDO_STACK_CREATE_LINK,
+	NAUTILUS_UNDO_STACK_RECURSIVE_SET_PERMISSIONS,
+	NAUTILUS_UNDO_STACK_SET_PERMISSIONS,
+	NAUTILUS_UNDO_STACK_CHANGE_GROUP,
+	NAUTILUS_UNDO_STACK_CHANGE_OWNER,
+	NAUTILUS_UNDO_STACK_NUM_TYPES,
+} NautilusUndoStackActionType;
+
+typedef struct {
+	const char *undo_label;
+	const char *undo_description;
+	const char *redo_label;
+	const char *redo_description;
+} NautilusUndoStackMenuData;
+
+typedef struct _NautilusUndoStackActionData NautilusUndoStackActionData;
+
+struct _NautilusUndoStackActionData {
+	/* Common stuff */
+	NautilusUndoStackActionType type;
+
+	void (* undo_func) (NautilusUndoStackActionData *data);
+	void (* redo_func) (NautilusUndoStackActionData *data);
+
+	NautilusUndoStackFinishCallback callback;
+	gpointer callback_user_data;
+
+	NautilusUndoStackManager *manager;
+	guint is_valid : 1;
+	guint locked : 1;	/* True if the action is being undone/redone */
+	guint freed : 1;	/* True if the action must be freed after undo/redo */
+	guint count;			/* Number of items */
+
+	void    (* strings_func) (NautilusUndoStackActionData *data,
+				  guint count,
+				  gchar **labels,
+				  gchar **descriptions);
+
+	gchar *undo_label;
+	gchar *redo_label;
+	gchar *undo_description;
+	gchar *redo_description;
+
+	/* Copy / Move stuff */
+	GFile *src_dir;
+	GFile *dest_dir;
+	GList *sources;	     /* Relative to src_dir */
+	GList *destinations; /* Relative to dest_dir */
+
+	/* Create new file/folder stuff/set permissions */
+	char *template;
+	GFile *target_file;
+
+	/* Rename stuff */
+	GFile *old_file;
+	GFile *new_file;
+
+	/* Trash stuff */
+	GHashTable *trashed;
+
+	/* Recursive change permissions stuff */
+	GHashTable *original_permissions;
+	guint32 dir_mask;
+	guint32 dir_permissions;
+	guint32 file_mask;
+	guint32 file_permissions;
+
+	/* Single file change permissions stuff */
+	guint32 current_permissions;
+	guint32 new_permissions;
+
+	/* Group */
+	char *original_name;
+	char *new_name;
+};
+
+typedef struct _NautilusUndoStackActionData UndoData;
+
+struct _NautilusUndoStackManagerPrivate
+{
+	GQueue *stack;
+
+	/* Used to protect access to stack (because of async file ops) */
+	GMutex *mutex;
+
+	guint undo_levels;
+	guint index;
+	guint undo_redo_flag : 1;
+	guint confirm_delete : 1;
+};
+
+#endif /* __NAUTILUS_UNDOSTACK_TYPES_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]