Summary: Deleted files on removable media remain in the ~/$USER-trash directory after the device is unmounted.
http://bugzilla.gnome.org/show_bug.cgi?id=138058 I've taken a stab at implementing a solution for this. When a volume is unmounted a check is made to see if there is any trash on the volume. If there is the user is asked if they want to empty the trash before unmounting. This is the first time I've done any hacking on Gnome and I only started this morning. It's not yet complete and I'm sure there is plenty of room for improvement but I wanted to get some feedback at this point. TODO: Prevent it from trying to unmount until the trash is deleted. Currently the unmount will fail if there is more than a couple small files in the trash as the delete has the volume locked. I'm thinking the best way would to preform the unmount in the callback of the gnome_vfs_async_xfer. Handle drive unmounts too, no just volumes. A better way to check if the trash is empty. Thanks for taking the time to look at this: Jesse --------------------------- Patch against nautilus-2.16.3 Apply with -p1 at the top of the tree. http://www.rogepost.com/n/0888731783 diff -ru nautilus-2.16.3-orig/libnautilus-private/nautilus-file-operations.c nautilus-2.16.3/libnautilus-private/nautilus-file-operations.c --- nautilus-2.16.3-orig/libnautilus-private/nautilus-file-operations.c 2006-11-06 07:21:46.000000000 -0500 +++ nautilus-2.16.3/libnautilus-private/nautilus-file-operations.c 2007-01-27 16:55:04.000000000 -0500 @@ -2898,6 +2898,121 @@ } } +gchar* +get_trash_uri_for_volume(GnomeVFSVolume *volume) +{ + gchar *uri = 0; + if (gnome_vfs_volume_handles_trash(volume)) { + GnomeVFSURI *trash_uri; + GnomeVFSURI *vol_uri; + gchar *vol_uri_str; + + vol_uri_str = gnome_vfs_volume_get_activation_uri (volume); + vol_uri = gnome_vfs_uri_new (vol_uri_str); + g_free (vol_uri_str); + + if (gnome_vfs_find_directory (vol_uri, + GNOME_VFS_DIRECTORY_KIND_TRASH, + &trash_uri, FALSE, TRUE, 0777) == GNOME_VFS_OK) + { + uri = gnome_vfs_uri_to_string (trash_uri, 0); + gnome_vfs_uri_unref (trash_uri); + } + gnome_vfs_uri_unref (vol_uri); + } + return uri; +} + +gint +num_entries_in_dir (gchar *dir_uri) +{ + gint num_entries = 0; + if (dir_uri) { + GList *entries; + if (gnome_vfs_directory_list_load (&entries, dir_uri, + GNOME_VFS_FILE_INFO_DEFAULT) == GNOME_VFS_OK) + { + num_entries = g_list_length (entries); + } + g_list_free (entries); + } + return num_entries; +} + +void +nautilus_file_operations_unmount_volume (GtkWidget *parent_view, + GnomeVFSVolume *volume, + GnomeVFSVolumeOpCallback callback, + gpointer user_data) +{ + g_return_if_fail (parent_view != NULL); + + gchar *trash_uri; + trash_uri = get_trash_uri_for_volume (volume); + /* It's faster to just check for the existence of the trash directory + * but that would prompt the user to delete an emtpy trash directory + * so check if there is anything other than . and .. in it. */ + if (num_entries_in_dir (trash_uri) > 2) { + gint result; + GtkWidget *dialog; + GdkScreen *screen; + + screen = gtk_widget_get_screen (parent_view); + + /* Do we need to be modal ? */ + dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, + GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, + _("Do you want to empty the trash before you umount?"), NULL); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + _("In order to regain the " + "free space on this device " + "the trash must be emptied. " + "All items in the trash " + "will be permanently lost. ")); + gtk_dialog_add_buttons (GTK_DIALOG (dialog), + _("Don't Empty Trash"), GTK_RESPONSE_REJECT, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + _("Empty Trash"), GTK_RESPONSE_ACCEPT, NULL); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); + gtk_window_set_title (GTK_WINDOW (dialog), ""); /* as per HIG */ + gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE); + gtk_window_set_screen (GTK_WINDOW (dialog), screen); + atk_object_set_role (gtk_widget_get_accessible (dialog), ATK_ROLE_ALERT); + gtk_window_set_wmclass (GTK_WINDOW (dialog), "empty_trash", + "Nautilus"); + + /* Make transient for the window group */ + gtk_widget_realize (dialog); + gdk_window_set_transient_for (GTK_WIDGET (dialog)->window, + gdk_screen_get_root_window (screen)); + + result = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + switch (result) { + case GTK_RESPONSE_ACCEPT: + { + GList *trash_dirs = NULL; + trash_dirs = g_list_prepend (trash_dirs, trash_uri); + /* TODO this needs to be synchronus or only perform the unmount + * when the delete is finished */ + nautilus_file_operations_delete (trash_dirs, parent_view); + g_list_free (trash_dirs); + g_free (trash_uri); + /* fall through and unmount the volume */ + } + case GTK_RESPONSE_REJECT: + gnome_vfs_volume_unmount (volume, callback, user_data); + break; + default: + break; + } + } else { + /* no trash so unmount as usual */ + gnome_vfs_volume_unmount (volume, callback, user_data); + } +} + struct RecursivePermissionsInfo { GnomeVFSAsyncHandle *handle; GnomeVFSURI *current_dir; diff -ru nautilus-2.16.3-orig/libnautilus-private/nautilus-file-operations.h nautilus-2.16.3/libnautilus-private/nautilus-file-operations.h --- nautilus-2.16.3-orig/libnautilus-private/nautilus-file-operations.h 2006-10-02 06:46:28.000000000 -0400 +++ nautilus-2.16.3/libnautilus-private/nautilus-file-operations.h 2007-01-27 16:56:06.000000000 -0500 @@ -30,6 +30,8 @@ #include <gdk/gdkdnd.h> #include <gtk/gtkwidget.h> #include <libgnomevfs/gnome-vfs-types.h> +#include <libgnomevfs/gnome-vfs-utils.h> +#include <libgnomevfs/gnome-vfs-volume-monitor.h> typedef void (* NautilusCopyCallback) (GHashTable *debuting_uris, gpointer callback_data); @@ -79,4 +81,9 @@ NautilusSetPermissionsCallback callback, gpointer callback_data); +void nautilus_file_operations_unmount_volume (GtkWidget *parent_view, + GnomeVFSVolume *volume, + GnomeVFSVolumeOpCallback callback, + gpointer user_data); + #endif /* NAUTILUS_FILE_OPERATIONS_H */ diff -ru nautilus-2.16.3-orig/src/file-manager/fm-directory-view.c nautilus-2.16.3/src/file-manager/fm-directory-view.c --- nautilus-2.16.3-orig/src/file-manager/fm-directory-view.c 2006-10-31 03:25:05.000000000 -0500 +++ nautilus-2.16.3/src/file-manager/fm-directory-view.c 2007-01-27 16:50:56.000000000 -0500 @@ -6328,7 +6328,8 @@ if (nautilus_file_has_volume (file)) { volume = nautilus_file_get_volume (file); if (volume != NULL) { - gnome_vfs_volume_unmount (volume, volume_or_drive_unmounted_callback, NULL); + nautilus_file_operations_unmount_volume (view, volume, + volume_or_drive_unmounted_callback, NULL); } } else if (nautilus_file_has_drive (file)) { drive = nautilus_file_get_drive (file); @@ -6439,7 +6440,8 @@ file_get_volume_and_drive (file, &volume, &drive); if (volume != NULL) { - gnome_vfs_volume_unmount (volume, volume_or_drive_unmounted_callback, NULL); + nautilus_file_operations_unmount_volume (view, volume, + volume_or_drive_unmounted_callback, NULL); } else if (drive != NULL) { gnome_vfs_drive_unmount (drive, volume_or_drive_unmounted_callback, NULL); } diff -ru nautilus-2.16.3-orig/src/file-manager/fm-tree-view.c nautilus-2.16.3/src/file-manager/fm-tree-view.c --- nautilus-2.16.3-orig/src/file-manager/fm-tree-view.c 2006-08-07 06:34:31.000000000 -0400 +++ nautilus-2.16.3/src/file-manager/fm-tree-view.c 2007-01-27 16:49:18.000000000 -0500 @@ -1085,7 +1085,8 @@ if (eject_for_type (gnome_vfs_volume_get_device_type (volume))) { gnome_vfs_volume_eject (volume, volume_or_drive_unmounted_callback, GINT_TO_POINTER (TRUE)); } else { - gnome_vfs_volume_unmount (volume, volume_or_drive_unmounted_callback, GINT_TO_POINTER (FALSE)); + nautilus_file_operations_unmount_volume (view, volume, + volume_or_drive_unmounted_callback, GINT_TO_POINTER (FALSE)); } } } diff -ru nautilus-2.16.3-orig/src/nautilus-places-sidebar.c nautilus-2.16.3/src/nautilus-places-sidebar.c --- nautilus-2.16.3-orig/src/nautilus-places-sidebar.c 2006-09-14 04:24:30.000000000 -0400 +++ nautilus-2.16.3/src/nautilus-places-sidebar.c 2007-01-27 16:48:14.000000000 -0500 @@ -1264,7 +1264,8 @@ -1); if (volume != NULL) { - gnome_vfs_volume_unmount (volume, volume_op_callback, sidebar); + nautilus_file_operations_unmount_volume (GTK_WIDGET (sidebar->tree_view), + volume, volume_op_callback, sidebar); } else if (drive != NULL) { gnome_vfs_drive_unmount (drive, volume_op_callback, sidebar); } -- nautilus-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/nautilus-list
