diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | TODO-gio | 4 | ||||
-rw-r--r-- | libnautilus-private/nautilus-file-changes-queue.c | 36 | ||||
-rw-r--r-- | libnautilus-private/nautilus-file-changes-queue.h | 36 | ||||
-rw-r--r-- | libnautilus-private/nautilus-file-operations.c | 462 | ||||
-rw-r--r-- | libnautilus-private/nautilus-file-operations.h | 12 | ||||
-rw-r--r-- | libnautilus-private/nautilus-monitor.c | 4 | ||||
-rw-r--r-- | src/file-manager/fm-directory-view.c | 275 |
8 files changed, 579 insertions, 264 deletions
@@ -1,5 +1,19 @@ 2007-10-25 Alexander Larsson <alexl@redhat.com> + * libnautilus-private/nautilus-file-changes-queue.[ch]: + * libnautilus-private/nautilus-monitor.c: + Rename some file change queue functions to _by_uri + add GFile based version with the original name + + * libnautilus-private/nautilus-file-operations.[ch]: + Add gio based nautilus_file_operations_trash_or_delete() call. + + * src/file-manager/fm-directory-view.c: + Call nautilus_file_operations_trash_or_delete() + Remove unused code + +2007-10-25 Alexander Larsson <alexl@redhat.com> + * src/file-manager/fm-directory-view.[ch]: Make file activation handle mounting of mountables and non-mounted locations. Also general cleanup of activation. @@ -3,6 +3,10 @@ Monitor for UNMOUNT file change event and close window Break out file activation from fm-directory-view.c File actication cancellation not implemented yet +convert delete to use trash_or_delete code +recursive deletes +progress for trash/delete + Automount location when loading it in a window and its not mounted. "translate" gnome-vfs errors and update error handling diff --git a/libnautilus-private/nautilus-file-changes-queue.c b/libnautilus-private/nautilus-file-changes-queue.c index 0d7d7287c..bff9b9ed7 100644 --- a/libnautilus-private/nautilus-file-changes-queue.c +++ b/libnautilus-private/nautilus-file-changes-queue.c @@ -167,7 +167,7 @@ nautilus_file_changes_queue_file_changed (const char *uri) } void -nautilus_file_changes_queue_file_removed (const char *uri) +nautilus_file_changes_queue_file_removed_by_uri (const char *uri) { NautilusFileChange *new_item; NautilusFileChangesQueue *queue; @@ -181,6 +181,20 @@ nautilus_file_changes_queue_file_removed (const char *uri) } void +nautilus_file_changes_queue_file_removed (GFile *location) +{ + NautilusFileChange *new_item; + NautilusFileChangesQueue *queue; + + queue = nautilus_file_changes_queue_get(); + + new_item = g_new0 (NautilusFileChange, 1); + new_item->kind = CHANGE_FILE_REMOVED; + new_item->from_uri = g_file_get_uri (location); + nautilus_file_changes_queue_add_common (queue, new_item); +} + +void nautilus_file_changes_queue_file_moved (const char *from, const char *to) { NautilusFileChange *new_item; @@ -197,7 +211,7 @@ nautilus_file_changes_queue_file_moved (const char *from, const char *to) void nautilus_file_changes_queue_schedule_metadata_copy (const char *from_uri, - const char *to_uri) + const char *to_uri) { NautilusFileChange *new_item; NautilusFileChangesQueue *queue; @@ -213,7 +227,7 @@ nautilus_file_changes_queue_schedule_metadata_copy (const char *from_uri, void nautilus_file_changes_queue_schedule_metadata_move (const char *from_uri, - const char *to_uri) + const char *to_uri) { NautilusFileChange *new_item; NautilusFileChangesQueue *queue; @@ -228,7 +242,7 @@ nautilus_file_changes_queue_schedule_metadata_move (const char *from_uri, } void -nautilus_file_changes_queue_schedule_metadata_remove (const char *uri) +nautilus_file_changes_queue_schedule_metadata_remove_by_uri (const char *uri) { NautilusFileChange *new_item; NautilusFileChangesQueue *queue; @@ -242,6 +256,20 @@ nautilus_file_changes_queue_schedule_metadata_remove (const char *uri) } void +nautilus_file_changes_queue_schedule_metadata_remove (GFile *location) +{ + NautilusFileChange *new_item; + NautilusFileChangesQueue *queue; + + queue = nautilus_file_changes_queue_get (); + + new_item = g_new (NautilusFileChange, 1); + new_item->kind = CHANGE_METADATA_REMOVED; + new_item->from_uri = g_file_get_uri (location); + nautilus_file_changes_queue_add_common (queue, new_item); +} + +void nautilus_file_changes_queue_schedule_position_set (const char *uri, GdkPoint point, int screen) diff --git a/libnautilus-private/nautilus-file-changes-queue.h b/libnautilus-private/nautilus-file-changes-queue.h index 51b171c11..4f50a14c8 100644 --- a/libnautilus-private/nautilus-file-changes-queue.h +++ b/libnautilus-private/nautilus-file-changes-queue.h @@ -24,22 +24,26 @@ #define NAUTILUS_FILE_CHANGES_QUEUE_H #include <gdk/gdktypes.h> +#include <gio/gfile.h> + +void nautilus_file_changes_queue_file_added (const char *uri); +void nautilus_file_changes_queue_file_changed (const char *uri); +void nautilus_file_changes_queue_file_removed (GFile *location); +void nautilus_file_changes_queue_file_removed_by_uri (const char *uri); +void nautilus_file_changes_queue_file_moved (const char *from_uri, + const char *to_uri); +void nautilus_file_changes_queue_schedule_metadata_copy (const char *from_uri, + const char *to_uri); +void nautilus_file_changes_queue_schedule_metadata_move (const char *from_uri, + const char *to_uri); +void nautilus_file_changes_queue_schedule_metadata_remove (GFile *location); +void nautilus_file_changes_queue_schedule_metadata_remove_by_uri (const char *uri); +void nautilus_file_changes_queue_schedule_position_set (const char *uri, + GdkPoint point, + int screen); +void nautilus_file_changes_queue_schedule_position_remove (const char *uri); + +void nautilus_file_changes_consume_changes (gboolean consume_all); -void nautilus_file_changes_queue_file_added (const char *uri); -void nautilus_file_changes_queue_file_changed (const char *uri); -void nautilus_file_changes_queue_file_removed (const char *uri); -void nautilus_file_changes_queue_file_moved (const char *from_uri, - const char *to_uri); -void nautilus_file_changes_queue_schedule_metadata_copy (const char *from_uri, - const char *to_uri); -void nautilus_file_changes_queue_schedule_metadata_move (const char *from_uri, - const char *to_uri); -void nautilus_file_changes_queue_schedule_metadata_remove (const char *uri); -void nautilus_file_changes_queue_schedule_position_set (const char *uri, - GdkPoint point, - int screen); -void nautilus_file_changes_queue_schedule_position_remove (const char *uri); - -void nautilus_file_changes_consume_changes (gboolean consume_all); #endif /* NAUTILUS_FILE_CHANGES_QUEUE_H */ diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c index 0d1435db5..700f643d5 100644 --- a/libnautilus-private/nautilus-file-operations.c +++ b/libnautilus-private/nautilus-file-operations.c @@ -32,8 +32,10 @@ #include "nautilus-debug-log.h" #include "nautilus-file-operations-progress.h" +#include "nautilus-file-changes-queue.h" #include "nautilus-lib-self-check-functions.h" +#include <eel/eel-alert-dialog.h> #include <eel/eel-glib-extensions.h> #include <eel/eel-pango-extensions.h> #include <eel/eel-gtk-extensions.h> @@ -54,6 +56,9 @@ #include <libgnomevfs/gnome-vfs-utils.h> #include <libgnomevfs/gnome-vfs-volume.h> #include <libgnomevfs/gnome-vfs-volume-monitor.h> +#include <gio/gfile.h> +#include <gio/gurifuncs.h> +#include <gio/gioscheduler.h> #include "nautilus-file-changes-queue.h" #include "nautilus-file-private.h" #include "nautilus-desktop-icon-file.h" @@ -63,6 +68,8 @@ #include "nautilus-trash-monitor.h" #include "nautilus-file-utilities.h" +static gboolean confirm_trash_auto_value; + typedef enum TransferKind TransferKind; typedef struct TransferInfo TransferInfo; typedef struct IconPositionIterator IconPositionIterator; @@ -126,6 +133,17 @@ transfer_info_destroy (TransferInfo *transfer_info) g_free (transfer_info); } +static void +setup_autos (void) +{ + static gboolean setup_autos = FALSE; + if (!setup_autos) { + setup_autos = TRUE; + eel_preferences_add_auto_boolean (NAUTILUS_PREFERENCES_CONFIRM_TRASH, + &confirm_trash_auto_value); + } +} + /* Struct used to control applying icon positions to * top level items during a copy, drag, new folder creation and * link creation @@ -1761,7 +1779,7 @@ sync_transfer_callback (GnomeVFSXferProgressInfo *progress_info, gpointer data) */ if (progress_info->source_name == NULL) { /* remove any old metadata */ - nautilus_file_changes_queue_schedule_metadata_remove + nautilus_file_changes_queue_schedule_metadata_remove_by_uri (progress_info->target_name); } else { nautilus_file_changes_queue_schedule_metadata_copy @@ -1821,10 +1839,10 @@ sync_transfer_callback (GnomeVFSXferProgressInfo *progress_info, gpointer data) case GNOME_VFS_XFER_PHASE_DELETESOURCE: g_assert (progress_info->source_name != NULL); if (progress_info->top_level_item) { - nautilus_file_changes_queue_schedule_metadata_remove + nautilus_file_changes_queue_schedule_metadata_remove_by_uri (progress_info->source_name); } - nautilus_file_changes_queue_file_removed (progress_info->source_name); + nautilus_file_changes_queue_file_removed_by_uri (progress_info->source_name); break; case GNOME_VFS_XFER_PHASE_COMPLETED: @@ -2829,6 +2847,444 @@ nautilus_file_operations_delete (const GList *item_uris, gnome_vfs_uri_list_free (uri_list); } +#if 0 +void +nautilus_file_operations_delete (const GList *files, + GtkWidget *parent_view, + NautilusDeleteCallback done_callback, + gpointer done_callback_data) +{ +} +#endif + +typedef struct { + GList *files; + GtkWindow *parent_window; + gboolean try_trash; + gboolean delete_if_all_already_in_trash; + NautilusDeleteCallback done_callback; + gpointer done_callback_data; +} DeleteJob; + +static gboolean +can_delete_without_confirm (GFile *file) +{ + if (g_file_has_uri_scheme (file, "burn")) { + return TRUE; + } + + return FALSE; +} + +static gboolean +can_trash_file (GFile *file, GCancellable *cancellable) +{ + GFileInfo *info; + gboolean res; + + res = FALSE; + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, + 0, + cancellable, + NULL); + + if (info) { + res = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH); + g_object_unref (info); + } + + return res; +} + +static char * +get_display_name (GFile *file, GCancellable *cancellable) +{ + GFileInfo *info; + char *name, *basename; + + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_STD_DISPLAY_NAME, + 0, cancellable, NULL); + + name = NULL; + if (info) { + name = g_strdup (g_file_info_get_display_name (info)); + g_object_unref (info); + } + + if (name == NULL) { + basename = g_file_get_basename (file); + if (g_utf8_validate (basename, -1, NULL)) { + name = basename; + } else { + name = g_uri_escape_string (basename, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE); + g_free (basename); + } + } + + return name; +} + +static void +delete_files (GList *files, GCancellable *cancellable, GtkWindow *parent_window) +{ + GList *l; + GFile *file; + GError *error; + + for (l = files; l != NULL; l = l->next) { + file = l->data; + + error = NULL; + if (!g_file_delete (file, cancellable, &error)) { + /* TODO-gio */ + g_print ("Error deleting file: %s\n", error->message); + } else { + nautilus_file_changes_queue_schedule_metadata_remove (file); + nautilus_file_changes_queue_file_removed (file); + } + } +} + +static void +trash_files (GList *files, GCancellable *cancellable, GtkWindow *parent_window) +{ + GList *l; + GFile *file; + GError *error; + + for (l = files; l != NULL; l = l->next) { + file = l->data; + + error = NULL; + if (!g_file_trash (file, cancellable, &error)) { + /* TODO-gio */ + g_print ("Error trashing file: %s\n", error->message); + } else { + nautilus_file_changes_queue_schedule_metadata_remove (file); + nautilus_file_changes_queue_file_removed (file); + } + } +} + +typedef struct { + GtkWindow *parent_window; + const char *primary_message; + const char *secondary_message; + const char *ok_label; + int response; +} AlertInfo; + +static void +run_alert (gpointer user_data) +{ + AlertInfo *info = user_data; + GtkDialog *dialog; + + dialog = GTK_DIALOG (eel_alert_dialog_new (info->parent_window, + 0, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, + info->primary_message, + info->secondary_message)); + gtk_dialog_add_button (dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); + gtk_dialog_add_button (dialog, info->ok_label, GTK_RESPONSE_YES); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES); + + info->response = gtk_dialog_run (dialog); + gtk_object_destroy (GTK_OBJECT (dialog)); + + return; +} + +static int +run_alert_in_main (GIOJob *job, + GtkWindow *parent_window, + const char *primary_message, + const char *secondary_message, + const char *ok_label) +{ + AlertInfo info; + + info.parent_window = parent_window; + info.primary_message = primary_message; + info.secondary_message = secondary_message; + info.ok_label = ok_label; + + g_io_job_send_to_mainloop (job, + run_alert, + &info, + NULL, + TRUE); + + return info.response; +} + +typedef struct { + const char *prompt; + const char *detail; + const char *yes_label; + const char *no_label; + GtkWindow *parent_window; + int response; +} YesNoInfo; + +static void +run_yes_no (gpointer data) +{ + YesNoInfo *info = data; + GtkDialog *dialog; + + dialog = eel_show_yes_no_dialog + (info->prompt, + info->detail, + info->yes_label, info->no_label, + info->parent_window); + + info->response = gtk_dialog_run (dialog); + + gtk_object_destroy (GTK_OBJECT (dialog)); +} + +static int +run_yes_no_dialog_in_main (GIOJob *job, + const char *prompt, + const char *detail, + const char *yes_label, + const char *no_label, + GtkWindow *parent_window) +{ + YesNoInfo info; + + info.prompt = prompt; + info.detail = detail; + info.yes_label = yes_label; + info.no_label = no_label; + info.parent_window = parent_window; + + g_io_job_send_to_mainloop (job, + run_yes_no, + &info, + NULL, + TRUE); + + return info.response; +} + +static gboolean +confirm_delete_from_trash (GIOJob *job, + GtkWindow *parent_window, + GList *files) +{ + char *prompt; + char *file_name; + int file_count; + int response; + + /* Just Say Yes if the preference says not to confirm. */ + if (!confirm_trash_auto_value) { + return TRUE; + } + + file_count = g_list_length (files); + g_assert (file_count > 0); + + if (file_count == 1) { + file_name = get_display_name ((GFile *) files->data, NULL); + prompt = g_strdup_printf (_("Are you sure you want to permanently delete \"%s\" " + "from the trash?"), file_name); + g_free (file_name); + } else { + prompt = g_strdup_printf (ngettext("Are you sure you want to permanently delete " + "the %d selected item from the trash?", + "Are you sure you want to permanently delete " + "the %d selected items from the trash?", + file_count), + file_count); + } + + response = run_alert_in_main (job, parent_window, + prompt, + _("If you delete an item, it will be permanently lost."), + GTK_STOCK_DELETE); + + return (response == GTK_RESPONSE_YES); +} + +static gboolean +confirm_deletion (GIOJob *job, + GtkWindow *parent_window, + GList *files, + gboolean all) +{ + char *prompt; + char *detail; + int file_count; + GFile *file; + char *file_name; + int response; + + file_count = g_list_length (files); + g_assert (file_count > 0); + + if (file_count == 1) { + file = files->data; + if (g_file_has_uri_scheme (file, "x-nautilus-desktop")) { + /* Don't ask for desktop icons */ + return TRUE; + } + file_name = get_display_name (file, NULL); + prompt = _("Cannot move file to trash, do you want to delete immediately?"); + detail = g_strdup_printf (_("The file \"%s\" cannot be moved to the trash."), file_name); + g_free (file_name); + } else { + if (all) { + prompt = _("Cannot move items to trash, do you want to delete them immediately?"); + detail = g_strdup_printf (ngettext("The selected item could not be moved to the Trash", + "The %d selected items could not be moved to the Trash", + file_count), + file_count); + } else { + prompt = _("Cannot move some items to trash, do you want to delete these immediately?"); + detail = g_strdup_printf (_("%d of the selected items cannot be moved to the Trash"), file_count); + } + } + + response = run_yes_no_dialog_in_main (job, + prompt, + detail, + GTK_STOCK_DELETE, GTK_STOCK_CANCEL, + parent_window); + + g_free (detail); + + return (response == GTK_RESPONSE_YES); +} + +static void delete_job_done (gpointer data); + +static void +delete_job (GIOJob *io_job, + GCancellable *cancellable, + gpointer user_data) +{ + DeleteJob *job = user_data; + GList *trashable_files; + GList *untrashable_files; + GList *in_trash_files; + GList *no_confirm_files; + GList *l; + GFile *file; + + /* Collect three lists: (1) items that can be moved to trash, + * (2) items that can only be deleted in place, and (3) items that + * are already in trash. + * + * Always move (1) to trash if non-empty. + * Delete (3) only if (1) and (2) are non-empty, otherwise ignore (3). + * Ask before deleting (2) if non-empty. + * Ask before deleting (3) if non-empty. + */ + + trashable_files = NULL; + untrashable_files = NULL; + in_trash_files = NULL; + no_confirm_files = NULL; + + if (job->try_trash) { + for (l = job->files; l != NULL; l = l->next) { + file = l->data; + + if (job->delete_if_all_already_in_trash && g_file_has_uri_scheme (file, "trash")) { + in_trash_files = g_list_prepend (in_trash_files, file); + } else if (can_delete_without_confirm (file)) { + no_confirm_files = g_list_prepend (no_confirm_files, file); + } else if (can_trash_file (file, NULL)) { + trashable_files = g_list_prepend (trashable_files, file); + } else { + untrashable_files = g_list_prepend (untrashable_files, file); + } + } + } else { + no_confirm_files = g_list_copy (job->files); + + } + + if (in_trash_files != NULL && trashable_files == NULL && untrashable_files == NULL) { + if (confirm_delete_from_trash (io_job, job->parent_window, in_trash_files)) { + delete_files (in_trash_files, NULL, job->parent_window); + } + } else { + if (no_confirm_files != NULL) { + delete_files (no_confirm_files, NULL, job->parent_window); + } + if (trashable_files != NULL) { + trash_files (trashable_files, NULL, job->parent_window); + } + if (untrashable_files != NULL) { + if (confirm_deletion (io_job, job->parent_window, untrashable_files, trashable_files == NULL)) { + delete_files (untrashable_files, NULL, job->parent_window); + } + } + } + + g_list_free (in_trash_files); + g_list_free (trashable_files); + g_list_free (untrashable_files); + g_list_free (no_confirm_files); + + g_io_job_send_to_mainloop (io_job, + delete_job_done, + job, + NULL, + FALSE); + +} + +static void +delete_job_done (gpointer user_data) +{ + DeleteJob *job = user_data; + + eel_g_object_list_free (job->files); + if (job->parent_window) { + g_object_unref (job->parent_window); + } + + if (job->done_callback) { + job->done_callback (/* TODO: debuting uris */NULL, job->done_callback_data); + } + g_free (job); + + nautilus_file_changes_consume_changes (TRUE); +} + +void +nautilus_file_operations_trash_or_delete (GList *files, + GtkWindow *parent_window, + NautilusDeleteCallback done_callback, + gpointer done_callback_data) +{ + DeleteJob *job; + + setup_autos (); + + /* TODO: special case desktop icon link files ... */ + + job = g_new0 (DeleteJob, 1); + job->files = eel_g_object_list_copy (files); + job->parent_window = g_object_ref (parent_window); + job->try_trash = TRUE; + job->done_callback = done_callback; + job->done_callback_data = done_callback_data; + + g_schedule_io_job (delete_job, + job, + NULL, + 0, + NULL); +} + static void do_empty_trash (GtkWidget *parent_view) { diff --git a/libnautilus-private/nautilus-file-operations.h b/libnautilus-private/nautilus-file-operations.h index 9400631ce..12cd81972 100644 --- a/libnautilus-private/nautilus-file-operations.h +++ b/libnautilus-private/nautilus-file-operations.h @@ -72,10 +72,14 @@ void nautilus_file_operations_new_file_from_template (GtkWidget *p NautilusNewFileCallback done_callback, gpointer data); -void nautilus_file_operations_delete (const GList *item_uris, - GtkWidget *parent_view, - NautilusDeleteCallback done_callback, - gpointer done_callback_data); +void nautilus_file_operations_delete (const GList *item_uris, + GtkWidget *parent_view, + NautilusDeleteCallback done_callback, + gpointer done_callback_data); +void nautilus_file_operations_trash_or_delete (GList *files, + GtkWindow *parent_window, + NautilusDeleteCallback done_callback, + gpointer done_callback_data); void nautilus_file_set_permissions_recursive (const char *directory, GnomeVFSFilePermissions file_permissions, diff --git a/libnautilus-private/nautilus-monitor.c b/libnautilus-private/nautilus-monitor.c index 4a7911e39..5cb18d48d 100644 --- a/libnautilus-private/nautilus-monitor.c +++ b/libnautilus-private/nautilus-monitor.c @@ -98,8 +98,8 @@ dir_changed (GDirectoryMonitor* monitor, nautilus_file_changes_queue_file_changed (uri); break; case G_FILE_MONITOR_EVENT_DELETED: - nautilus_file_changes_queue_schedule_metadata_remove (uri); - nautilus_file_changes_queue_file_removed (uri); + nautilus_file_changes_queue_schedule_metadata_remove_by_uri (uri); + nautilus_file_changes_queue_file_removed_by_uri (uri); break; case G_FILE_MONITOR_EVENT_CREATED: nautilus_file_changes_queue_file_added (uri); diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c index 29f0cc4a4..f1cc51062 100644 --- a/src/file-manager/fm-directory-view.c +++ b/src/file-manager/fm-directory-view.c @@ -73,14 +73,6 @@ #include <libgnome/gnome-util.h> #include <libgnomeui/gnome-uidefs.h> #include <libgnomeui/gnome-help.h> -#include <libgnomevfs/gnome-vfs-async-ops.h> -#include <libgnomevfs/gnome-vfs-file-info.h> -#include <libgnomevfs/gnome-vfs-mime-handlers.h> -#include <libgnomevfs/gnome-vfs-ops.h> -#include <libgnomevfs/gnome-vfs-result.h> -#include <libgnomevfs/gnome-vfs-uri.h> -#include <libgnomevfs/gnome-vfs-utils.h> -#include <libgnomevfs/gnome-vfs-volume-monitor.h> #include <libnautilus-private/nautilus-recent.h> #include <libnautilus-extension/nautilus-menu-provider.h> #include <libnautilus-private/nautilus-clipboard-monitor.h> @@ -336,14 +328,12 @@ static void fm_directory_view_init (FMDirectoryView static void fm_directory_view_duplicate_selection (FMDirectoryView *view, GList *files, GArray *item_locations); -static gboolean fm_directory_view_confirm_deletion (GtkWindow *parent_window, - GList *uris, - gboolean all); static void fm_directory_view_create_links_for_files (FMDirectoryView *view, GList *files, GArray *item_locations); static void trash_or_delete_files (GtkWindow *parent_window, - const GList *files); + const GList *files, + gboolean delete_if_all_already_in_trash); static void fm_directory_view_activate_file (FMDirectoryView *view, NautilusFile *file, NautilusWindowOpenMode mode, @@ -903,7 +893,7 @@ trash_or_delete_selected_files (FMDirectoryView *view) */ if (!view->details->selection_was_removed) { selection = fm_directory_view_get_selection_for_file_transfer (view); - trash_or_delete_files (fm_directory_view_get_containing_window (view), selection); + trash_or_delete_files (fm_directory_view_get_containing_window (view), selection, TRUE); nautilus_file_list_free (selection); view->details->selection_was_removed = TRUE; } @@ -1762,9 +1752,10 @@ fm_directory_view_get_selection_uris (NautilusView *view) } static GList * -file_list_from_uri_list (GList *uri_list) +file_list_from_uri_list (const GList *uri_list) { - GList *file_list, *node; + GList *file_list; + const GList *node; file_list = NULL; for (node = uri_list; node != NULL; node = node->next) { @@ -1775,6 +1766,22 @@ file_list_from_uri_list (GList *uri_list) return g_list_reverse (file_list); } +static GList * +location_list_from_uri_list (const GList *uris) +{ + const GList *l; + GList *files; + GFile *f; + + files = NULL; + for (l = uris; l != NULL; l = l->next) { + f = g_file_new_for_uri (l->data); + files = g_list_prepend (files, f); + } + + return g_list_reverse (files); +} + static void fm_directory_view_set_selection_uris (NautilusView *nautilus_view, GList *selection_uris) @@ -3664,46 +3671,6 @@ desktop_or_home_dir_in_selection (FMDirectoryView *view) } static gboolean -can_move_uri_to_trash (GtkWindow *parent_window, const char *file_uri_string) -{ - /* Return TRUE if we can get a trash directory on the same volume as this file. */ - GnomeVFSURI *file_uri; - GnomeVFSURI *directory_uri; - GnomeVFSURI *trash_dir_uri; - gboolean result; - - g_return_val_if_fail (file_uri_string != NULL, FALSE); - - file_uri = gnome_vfs_uri_new (file_uri_string); - - if (file_uri == NULL) { - return FALSE; - } - - /* FIXME: Why can't we just pass file_uri to gnome_vfs_find_directory? */ - directory_uri = gnome_vfs_uri_get_parent (file_uri); - gnome_vfs_uri_unref (file_uri); - - if (directory_uri == NULL) { - return FALSE; - } - - /* - * Create a new trash if needed but don't go looking for an old Trash. - * Passing 0 permissions as gnome-vfs would override the permissions - * passed with 700 while creating .Trash directory - */ - result = gnome_vfs_find_directory (directory_uri, GNOME_VFS_DIRECTORY_KIND_TRASH, - &trash_dir_uri, TRUE, FALSE, 0) == GNOME_VFS_OK; - if (result) { - gnome_vfs_uri_unref (trash_dir_uri); - } - gnome_vfs_uri_unref (directory_uri); - - return result; -} - -static gboolean can_delete_uri_without_confirm (const char *file_uri_string) { if (eel_istr_has_prefix (file_uri_string, "burn:") != FALSE) { @@ -3726,193 +3693,28 @@ file_name_from_uri (const char *uri) return file_name; } -static gboolean -fm_directory_view_confirm_deletion (GtkWindow *parent_window, GList *uris, gboolean all) -{ - GtkDialog *dialog; - char *prompt; - char *detail; - int uri_count; - char *uri; - char *file_name; - int response; - - uri_count = g_list_length (uris); - g_assert (uri_count > 0); - - if (uri_count == 1) { - uri = (char *) uris->data; - if (eel_uri_is_desktop (uri)) { - /* Don't ask for desktop icons */ - return TRUE; - } - file_name = file_name_from_uri (uri); - prompt = _("Cannot move file to trash, do you want to delete immediately?"); - detail = g_strdup_printf (_("The file \"%s\" cannot be moved to the trash."), file_name); - g_free (file_name); - } else { - if (all) { - prompt = _("Cannot move items to trash, do you want to delete them immediately?"); - detail = g_strdup_printf (ngettext("The selected item could not be moved to the Trash", - "The %d selected items could not be moved to the Trash", - uri_count), - uri_count); - } else { - prompt = _("Cannot move some items to trash, do you want to delete these immediately?"); - detail = g_strdup_printf (_("%d of the selected items cannot be moved to the Trash"), uri_count); - } - } - - dialog = eel_show_yes_no_dialog - (prompt, - detail, GTK_STOCK_DELETE, GTK_STOCK_CANCEL, - parent_window); - - g_free (detail); - response = gtk_dialog_run (dialog); - gtk_object_destroy (GTK_OBJECT (dialog)); - - return response == GTK_RESPONSE_YES; -} - -static gboolean -confirm_delete_from_trash (GtkWindow *parent_window, GList *uris) -{ - GtkDialog *dialog; - char *prompt; - char *file_name; - int uri_count; - int response; - - /* Just Say Yes if the preference says not to confirm. */ - if (!confirm_trash_auto_value) { - return TRUE; - } - - uri_count = g_list_length (uris); - g_assert (uri_count > 0); - - if (uri_count == 1) { - file_name = file_name_from_uri ((char *) uris->data); - prompt = g_strdup_printf (_("Are you sure you want to permanently delete \"%s\" " - "from the trash?"), file_name); - g_free (file_name); - } else { - prompt = g_strdup_printf (ngettext("Are you sure you want to permanently delete " - "the %d selected item from the trash?", - "Are you sure you want to permanently delete " - "the %d selected items from the trash?", - uri_count), - uri_count); - } - - dialog = GTK_DIALOG (eel_alert_dialog_new (parent_window, - 0, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, - prompt, - _("If you delete an item, it will be permanently lost."))); - gtk_dialog_add_button (dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); - gtk_dialog_add_button (dialog, GTK_STOCK_DELETE, GTK_RESPONSE_YES); - - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES); - - g_free (prompt); - - response = gtk_dialog_run (dialog); - gtk_object_destroy (GTK_OBJECT (dialog)); - - return response == GTK_RESPONSE_YES; -} - -static void -trash_or_delete_files_common (GtkWindow *parent_window, - const GList *file_uris, - GArray *relative_item_points, - gboolean delete_if_all_already_in_trash) -{ - const GList *file_node; - char *file_uri; - GList *moveable_uris; - GList *unmoveable_uris; - GList *in_trash_uris; - GList *no_confirm_uris; - - /* Collect three lists: (1) items that can be moved to trash, - * (2) items that can only be deleted in place, and (3) items that - * are already in trash. - * - * Always move (1) to trash if non-empty. - * Delete (3) only if (1) and (2) are non-empty, otherwise ignore (3). - * Ask before deleting (2) if non-empty. - * Ask before deleting (3) if non-empty. - */ - - moveable_uris = NULL; - unmoveable_uris = NULL; - in_trash_uris = NULL; - no_confirm_uris = NULL; - - for (file_node = file_uris; file_node != NULL; file_node = file_node->next) { - file_uri = (char *) file_node->data; - - if (delete_if_all_already_in_trash && eel_uri_is_trash (file_uri)) { - in_trash_uris = g_list_prepend (in_trash_uris, g_strdup (file_uri)); - } else if (can_delete_uri_without_confirm (file_uri)) { - no_confirm_uris = g_list_prepend (no_confirm_uris, g_strdup (file_uri)); - } else if (can_move_uri_to_trash (parent_window, file_uri)) { - moveable_uris = g_list_prepend (moveable_uris, g_strdup (file_uri)); - } else { - unmoveable_uris = g_list_prepend (unmoveable_uris, g_strdup (file_uri)); - } - } - - if (in_trash_uris != NULL && moveable_uris == NULL && unmoveable_uris == NULL) { - if (confirm_delete_from_trash (parent_window, in_trash_uris)) { - nautilus_file_operations_delete (in_trash_uris, GTK_WIDGET (parent_window), - NULL, NULL); - } - } else { - if (no_confirm_uris != NULL) { - nautilus_file_operations_delete (no_confirm_uris, - GTK_WIDGET (parent_window), NULL, NULL); - } - if (moveable_uris != NULL) { - nautilus_file_operations_copy_move (moveable_uris, relative_item_points, - EEL_TRASH_URI, GDK_ACTION_MOVE, GTK_WIDGET (parent_window), - NULL, NULL); - } - if (unmoveable_uris != NULL) { - if (fm_directory_view_confirm_deletion (parent_window, - unmoveable_uris, - moveable_uris == NULL)) { - nautilus_file_operations_delete (unmoveable_uris, - GTK_WIDGET (parent_window), NULL, NULL); - } - } - } - - eel_g_list_free_deep (in_trash_uris); - eel_g_list_free_deep (moveable_uris); - eel_g_list_free_deep (unmoveable_uris); - eel_g_list_free_deep (no_confirm_uris); -} static void trash_or_delete_files (GtkWindow *parent_window, - const GList *files) + const GList *files, + gboolean delete_if_all_already_in_trash) { - GList *file_uris; + GList *locations; const GList *node; - file_uris = NULL; + locations = NULL; for (node = files; node != NULL; node = node->next) { - file_uris = g_list_prepend (file_uris, - nautilus_file_get_uri ((NautilusFile *) node->data)); + locations = g_list_prepend (locations, + nautilus_file_get_location ((NautilusFile *) node->data)); } - file_uris = g_list_reverse (file_uris); - trash_or_delete_files_common (parent_window, file_uris, NULL, TRUE); - eel_g_list_free_deep (file_uris); + locations = g_list_reverse (locations); + + nautilus_file_operations_trash_or_delete (locations, + parent_window, + NULL, NULL); + eel_g_object_list_free (locations); } static gboolean @@ -6483,7 +6285,7 @@ action_location_trash_callback (GtkAction *action, g_return_if_fail (file != NULL); files = g_list_append (NULL, file); - trash_or_delete_files (fm_directory_view_get_containing_window (view), files); + trash_or_delete_files (fm_directory_view_get_containing_window (view), files, TRUE); g_list_free (files); } @@ -7819,7 +7621,7 @@ report_broken_symbolic_link (GtkWindow *parent_window, NautilusFile *file) file_as_list.data = file; file_as_list.next = NULL; file_as_list.prev = NULL; - trash_or_delete_files (parent_window, &file_as_list); + trash_or_delete_files (parent_window, &file_as_list, TRUE); } out: @@ -9349,7 +9151,10 @@ fm_directory_view_move_copy_items (const GList *item_uris, } if (eel_uri_is_trash (target_uri) && copy_action == GDK_ACTION_MOVE) { - trash_or_delete_files_common (fm_directory_view_get_containing_window (view), item_uris, relative_item_points, FALSE); + GList *locations; + locations = location_list_from_uri_list (item_uris); + trash_or_delete_files (fm_directory_view_get_containing_window (view), locations, FALSE); + eel_g_object_list_free (locations); } else { nautilus_file_operations_copy_move (item_uris, relative_item_points, |