Trash directory on removable media - Bug 138058



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);
	}



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