[nautilus] Bug 587486 – Pass GMountOperation to unmount/eject/stop ops



commit cf5538067776605cb031a58ce2f77271375db498
Author: David Zeuthen <davidz redhat com>
Date:   Tue Jun 30 23:55:37 2009 -0400

    Bug 587486 â?? Pass GMountOperation to unmount/eject/stop ops
    
    - Port everything to use _with_operation() variants of unmount/eject
       methods
    
     - This includes changing the NautilusFile a bit; see the patch
       for details
    
     - Add support for g_drive_can_start_degraded() so we offer
       to start (degraded) drives even when g_drive_can_start()
       returns FALSE
    
     - Also add support for new mountable::* attributes so we can
       have "Detect Media" items in the context menu when right-clicking
       mounts/volumes/drives in computer:/// and on the desktop

 libnautilus-private/nautilus-desktop-icon-file.c |   12 +-
 libnautilus-private/nautilus-file-operations.c   |   32 ++-
 libnautilus-private/nautilus-file-private.h      |    3 +
 libnautilus-private/nautilus-file.c              |  250 ++++++++++++++++++++-
 libnautilus-private/nautilus-file.h              |   42 +++-
 libnautilus-private/nautilus-vfs-file.c          |  117 ++++++++--
 src/file-manager/fm-actions.h                    |    3 +
 src/file-manager/fm-directory-view.c             |  226 ++++++++++++++++++--
 src/file-manager/nautilus-directory-view-ui.xml  |    4 +
 src/nautilus-application.c                       |    8 +-
 src/nautilus-places-sidebar.c                    |   45 +++--
 11 files changed, 646 insertions(+), 96 deletions(-)
---
diff --git a/libnautilus-private/nautilus-desktop-icon-file.c b/libnautilus-private/nautilus-desktop-icon-file.c
index b5b09db..512eb67 100644
--- a/libnautilus-private/nautilus-desktop-icon-file.c
+++ b/libnautilus-private/nautilus-desktop-icon-file.c
@@ -306,7 +306,11 @@ nautilus_desktop_icon_file_get_link (NautilusDesktopIconFile *icon_file)
 }
 
 static void
-nautilus_desktop_icon_file_unmount (NautilusFile *file)
+nautilus_desktop_icon_file_unmount (NautilusFile                   *file,
+				    GMountOperation                *mount_op,
+				    GCancellable                   *cancellable,
+				    NautilusFileOperationCallback   callback,
+				    gpointer                        callback_data)
 {
 	NautilusDesktopIconFile *desktop_file;
 	GMount *mount;
@@ -322,7 +326,11 @@ nautilus_desktop_icon_file_unmount (NautilusFile *file)
 }
 
 static void
-nautilus_desktop_icon_file_eject (NautilusFile *file)
+nautilus_desktop_icon_file_eject (NautilusFile                   *file,
+				  GMountOperation                *mount_op,
+				  GCancellable                   *cancellable,
+				  NautilusFileOperationCallback   callback,
+				  gpointer                        callback_data)
 {
 	NautilusDesktopIconFile *desktop_file;
 	GMount *mount;
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c
index 9d2d792..70f7308 100644
--- a/libnautilus-private/nautilus-file-operations.c
+++ b/libnautilus-private/nautilus-file-operations.c
@@ -1981,11 +1981,11 @@ unmount_mount_callback (GObject *source_object,
 
 	error = NULL;
 	if (data->eject) {
-		unmounted = g_mount_eject_finish (G_MOUNT (source_object),
-		      							res, &error);
+		unmounted = g_mount_eject_with_operation_finish (G_MOUNT (source_object),
+								 res, &error);
 	} else {
-		unmounted = g_mount_unmount_finish (G_MOUNT (source_object),
-		      							res, &error);
+		unmounted = g_mount_unmount_with_operation_finish (G_MOUNT (source_object),
+								   res, &error);
 	}
 	
 	if (! unmounted) {
@@ -2011,17 +2011,25 @@ unmount_mount_callback (GObject *source_object,
 static void
 do_unmount (UnmountData *data)
 {
+	GMountOperation *mount_op;
+
+	mount_op = gtk_mount_operation_new (data->parent_window);
 	if (data->eject) {
-		g_mount_eject (data->mount,
-				 0, NULL,
-				 unmount_mount_callback,
-				 data);
+		g_mount_eject_with_operation (data->mount,
+					      0,
+					      mount_op,
+					      NULL,
+					      unmount_mount_callback,
+					      data);
 	} else {
-		g_mount_unmount (data->mount,
-				 0, NULL,
-				 unmount_mount_callback,
-				 data);
+		g_mount_unmount_with_operation (data->mount,
+						0,
+						mount_op,
+						NULL,
+						unmount_mount_callback,
+						data);
 	}
+	g_object_unref (mount_op);
 }
 
 static gboolean
diff --git a/libnautilus-private/nautilus-file-private.h b/libnautilus-private/nautilus-file-private.h
index 00fa2fb..1d3b2bf 100644
--- a/libnautilus-private/nautilus-file-private.h
+++ b/libnautilus-private/nautilus-file-private.h
@@ -217,8 +217,11 @@ struct NautilusFileDetails
 	eel_boolean_bit can_unmount                   : 1;
 	eel_boolean_bit can_eject                     : 1;
 	eel_boolean_bit can_start                     : 1;
+	eel_boolean_bit can_start_degraded            : 1;
 	eel_boolean_bit can_stop                      : 1;
 	eel_boolean_bit start_stop_type               : 3; /* GDriveStartStopType */
+	eel_boolean_bit can_poll_for_media            : 1;
+	eel_boolean_bit is_media_check_automatic      : 1;
 
 	eel_boolean_bit filesystem_readonly           : 1;
 	eel_boolean_bit filesystem_use_preview        : 2; /* GFilesystemPreviewType */
diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c
index f263818..6200c75 100644
--- a/libnautilus-private/nautilus-file.c
+++ b/libnautilus-private/nautilus-file.c
@@ -453,8 +453,11 @@ nautilus_file_clear_info (NautilusFile *file)
 	file->details->can_unmount = FALSE;
 	file->details->can_eject = FALSE;
 	file->details->can_start = FALSE;
+	file->details->can_start_degraded = FALSE;
 	file->details->can_stop = FALSE;
 	file->details->start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
+	file->details->can_poll_for_media = FALSE;
+	file->details->is_media_check_automatic = FALSE;
 	file->details->has_permissions = FALSE;
 	file->details->permissions = 0;
 	file->details->size = -1;
@@ -1052,6 +1055,88 @@ nautilus_file_can_start (NautilusFile *file)
 }
 
 gboolean
+nautilus_file_can_start_degraded (NautilusFile *file)
+{
+	gboolean ret;
+	GDrive *drive;
+
+	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
+
+	ret = FALSE;
+
+	if (file->details->can_start_degraded) {
+		ret = TRUE;
+		goto out;
+	}
+
+	if (file->details->mount != NULL) {
+		drive = g_mount_get_drive (file->details->mount);
+		if (drive != NULL) {
+			ret = g_drive_can_start_degraded (drive);
+			g_object_unref (drive);
+		}
+	}
+
+ out:
+	return ret;
+}
+
+gboolean
+nautilus_file_can_poll_for_media (NautilusFile *file)
+{
+	gboolean ret;
+	GDrive *drive;
+
+	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
+
+	ret = FALSE;
+
+	if (file->details->can_poll_for_media) {
+		ret = TRUE;
+		goto out;
+	}
+
+	if (file->details->mount != NULL) {
+		drive = g_mount_get_drive (file->details->mount);
+		if (drive != NULL) {
+			ret = g_drive_can_poll_for_media (drive);
+			g_object_unref (drive);
+		}
+	}
+
+ out:
+	return ret;
+}
+
+gboolean
+nautilus_file_is_media_check_automatic (NautilusFile *file)
+{
+	gboolean ret;
+	GDrive *drive;
+
+	g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
+
+	ret = FALSE;
+
+	if (file->details->is_media_check_automatic) {
+		ret = TRUE;
+		goto out;
+	}
+
+	if (file->details->mount != NULL) {
+		drive = g_mount_get_drive (file->details->mount);
+		if (drive != NULL) {
+			ret = g_drive_is_media_check_automatic (drive);
+			g_object_unref (drive);
+		}
+	}
+
+ out:
+	return ret;
+}
+
+
+gboolean
 nautilus_file_can_stop (NautilusFile *file)
 {
 	gboolean ret;
@@ -1127,11 +1212,25 @@ nautilus_file_mount (NautilusFile                   *file,
 }
 
 void
-nautilus_file_unmount (NautilusFile *file)
+nautilus_file_unmount (NautilusFile                   *file,
+		       GMountOperation                *mount_op,
+		       GCancellable                   *cancellable,
+		       NautilusFileOperationCallback   callback,
+		       gpointer                        callback_data)
 {
+	GError *error;
+
 	if (file->details->can_unmount) {
 		if (NAUTILUS_FILE_GET_CLASS (file)->unmount != NULL) {
-			NAUTILUS_FILE_GET_CLASS (file)->unmount (file);
+			NAUTILUS_FILE_GET_CLASS (file)->unmount (file, mount_op, cancellable, callback, callback_data);
+		} else {
+			if (callback) {
+				error = NULL;
+				g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+						     _("This file cannot be unmounted"));
+				callback (file, NULL, error, callback_data);
+				g_error_free (error);
+			}
 		}
 	} else if (file->details->mount != NULL &&
 		   g_mount_can_unmount (file->details->mount)) {
@@ -1140,11 +1239,25 @@ nautilus_file_unmount (NautilusFile *file)
 }
 
 void
-nautilus_file_eject (NautilusFile *file)
+nautilus_file_eject (NautilusFile                   *file,
+		     GMountOperation                *mount_op,
+		     GCancellable                   *cancellable,
+		     NautilusFileOperationCallback   callback,
+		     gpointer                        callback_data)
 {
+	GError *error;
+
 	if (file->details->can_eject) {
 		if (NAUTILUS_FILE_GET_CLASS (file)->eject != NULL) {
-			NAUTILUS_FILE_GET_CLASS (file)->eject (file);
+			NAUTILUS_FILE_GET_CLASS (file)->eject (file, mount_op, cancellable, callback, callback_data);
+		} else {
+			if (callback) {
+				error = NULL;
+				g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+						     _("This file cannot be ejected"));
+				callback (file, NULL, error, callback_data);
+				g_error_free (error);
+			}
 		}
 	} else if (file->details->mount != NULL &&
 		   g_mount_can_eject (file->details->mount)) {
@@ -1161,7 +1274,10 @@ nautilus_file_start (NautilusFile                   *file,
 {
 	GError *error;
 
-	if (NAUTILUS_FILE_GET_CLASS (file)->start == NULL) {
+	if ((file->details->can_start || file->details->can_start_degraded) &&
+	    NAUTILUS_FILE_GET_CLASS (file)->start != NULL) {
+		NAUTILUS_FILE_GET_CLASS (file)->start (file, start_op, cancellable, callback, callback_data);
+	} else {
 		if (callback) {
 			error = NULL;
 			g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
@@ -1169,23 +1285,112 @@ nautilus_file_start (NautilusFile                   *file,
 			callback (file, NULL, error, callback_data);
 			g_error_free (error);
 		}
+	}
+}
+
+static void
+file_stop_callback (GObject *source_object,
+		    GAsyncResult *res,
+		    gpointer callback_data)
+{
+	NautilusFileOperation *op;
+	gboolean stopped;
+	GError *error;
+
+	op = callback_data;
+
+	error = NULL;
+	stopped = g_drive_stop_finish (G_DRIVE (source_object),
+				       res, &error);
+
+	if (!stopped &&
+	    error->domain == G_IO_ERROR &&
+	    (error->code == G_IO_ERROR_FAILED_HANDLED ||
+	     error->code == G_IO_ERROR_CANCELLED)) {
+		g_error_free (error);
+		error = NULL;
+	}
+
+	nautilus_file_operation_complete (op, NULL, error);
+	if (error) {
+		g_error_free (error);
+	}
+}
+
+void
+nautilus_file_stop (NautilusFile                   *file,
+		    GMountOperation                *mount_op,
+		    GCancellable                   *cancellable,
+		    NautilusFileOperationCallback   callback,
+		    gpointer                        callback_data)
+{
+	GError *error;
+
+	if (NAUTILUS_FILE_GET_CLASS (file)->stop != NULL) {
+		if (file->details->can_stop) {
+			NAUTILUS_FILE_GET_CLASS (file)->stop (file, mount_op, cancellable, callback, callback_data);
+		} else {
+			if (callback) {
+				error = NULL;
+				g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+						     _("This file cannot be stopped"));
+				callback (file, NULL, error, callback_data);
+				g_error_free (error);
+			}
+		}
 	} else {
-		NAUTILUS_FILE_GET_CLASS (file)->start (file, start_op, cancellable, callback, callback_data);
+		GDrive *drive;
+
+		drive = NULL;
+		if (file->details->mount != NULL)
+			drive = g_mount_get_drive (file->details->mount);
+
+		if (drive != NULL && g_drive_can_stop (drive)) {
+			NautilusFileOperation *op;
+
+			op = nautilus_file_operation_new (file, callback, callback_data);
+			if (cancellable) {
+				g_object_unref (op->cancellable);
+				op->cancellable = g_object_ref (cancellable);
+			}
+
+			g_drive_stop (drive,
+				      G_MOUNT_UNMOUNT_NONE,
+				      mount_op,
+				      op->cancellable,
+				      file_stop_callback,
+				      op);
+		} else {
+			if (callback) {
+				error = NULL;
+				g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+						     _("This file cannot be stopped"));
+				callback (file, NULL, error, callback_data);
+				g_error_free (error);
+			}
+		}
+
+		if (drive != NULL) {
+			g_object_unref (drive);
+		}
 	}
 }
 
 void
-nautilus_file_stop (NautilusFile *file)
+nautilus_file_poll_for_media (NautilusFile *file)
 {
-	if (file->details->can_stop) {
+	if (file->details->can_poll_for_media) {
 		if (NAUTILUS_FILE_GET_CLASS (file)->stop != NULL) {
-			NAUTILUS_FILE_GET_CLASS (file)->stop (file);
+			NAUTILUS_FILE_GET_CLASS (file)->poll_for_media (file);
 		}
 	} else if (file->details->mount != NULL) {
 		GDrive *drive;
 		drive = g_mount_get_drive (file->details->mount);
 		if (drive != NULL) {
-			g_drive_stop (drive, 0, NULL, NULL, NULL);
+			g_drive_poll_for_media (drive,
+						NULL,  /* cancellable */
+						NULL,  /* GAsyncReadyCallback */
+						NULL); /* user_data */
 			g_object_unref (drive);
 		}
 	}
@@ -1801,7 +2006,7 @@ update_info_internal (NautilusFile *file,
 	gboolean has_permissions;
 	guint32 permissions;
 	gboolean can_read, can_write, can_execute, can_delete, can_trash, can_rename, can_mount, can_unmount, can_eject;
-	gboolean can_start, can_stop;
+	gboolean can_start, can_start_degraded, can_stop, can_poll_for_media, is_media_check_automatic;
 	GDriveStartStopType start_stop_type;
 	gboolean thumbnailing_failed;
 	int uid, gid;
@@ -1922,7 +2127,10 @@ update_info_internal (NautilusFile *file,
 	can_unmount = FALSE;
 	can_eject = FALSE;
 	can_start = FALSE;
+	can_start_degraded = FALSE;
 	can_stop = FALSE;
+	can_poll_for_media = FALSE;
+	is_media_check_automatic = FALSE;
 	start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) {
 		can_read = g_file_info_get_attribute_boolean (info,
@@ -1964,6 +2172,10 @@ update_info_internal (NautilusFile *file,
 		can_start = g_file_info_get_attribute_boolean (info,
 							       G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START);
 	}
+	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED)) {
+		can_start_degraded = g_file_info_get_attribute_boolean (info,
+							       G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED);
+	}
 	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP)) {
 		can_stop = g_file_info_get_attribute_boolean (info,
 							      G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP);
@@ -1972,6 +2184,14 @@ update_info_internal (NautilusFile *file,
 		start_stop_type = g_file_info_get_attribute_uint32 (info,
 								    G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE);
 	}
+	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL)) {
+		can_poll_for_media = g_file_info_get_attribute_boolean (info,
+									G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL);
+	}
+	if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC)) {
+		is_media_check_automatic = g_file_info_get_attribute_boolean (info,
+									      G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC);
+	}
 	if (file->details->can_read != can_read ||
 	    file->details->can_write != can_write ||
 	    file->details->can_execute != can_execute ||
@@ -1982,8 +2202,11 @@ update_info_internal (NautilusFile *file,
 	    file->details->can_unmount != can_unmount ||
 	    file->details->can_eject != can_eject ||
 	    file->details->can_start != can_start ||
+	    file->details->can_start_degraded != can_start_degraded ||
 	    file->details->can_stop != can_stop ||
-	    file->details->start_stop_type != start_stop_type) {
+	    file->details->start_stop_type != start_stop_type ||
+	    file->details->can_poll_for_media != can_poll_for_media ||
+	    file->details->is_media_check_automatic != is_media_check_automatic) {
 		changed = TRUE;
 	}
 	
@@ -1997,8 +2220,11 @@ update_info_internal (NautilusFile *file,
 	file->details->can_unmount = can_unmount;
 	file->details->can_eject = can_eject;
 	file->details->can_start = can_start;
+	file->details->can_start_degraded = can_start_degraded;
 	file->details->can_stop = can_stop;
 	file->details->start_stop_type = start_stop_type;
+	file->details->can_poll_for_media = can_poll_for_media;
+	file->details->is_media_check_automatic = is_media_check_automatic;
 
 	free_owner = FALSE;
 	owner = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER);
diff --git a/libnautilus-private/nautilus-file.h b/libnautilus-private/nautilus-file.h
index 0ee9367..952a09b 100644
--- a/libnautilus-private/nautilus-file.h
+++ b/libnautilus-private/nautilus-file.h
@@ -256,23 +256,39 @@ gboolean                nautilus_file_can_mount                         (Nautilu
 gboolean                nautilus_file_can_unmount                       (NautilusFile                   *file);
 gboolean                nautilus_file_can_eject                         (NautilusFile                   *file);
 gboolean                nautilus_file_can_start                         (NautilusFile                   *file);
+gboolean                nautilus_file_can_start_degraded                (NautilusFile                   *file);
 gboolean                nautilus_file_can_stop                          (NautilusFile                   *file);
 GDriveStartStopType     nautilus_file_get_start_stop_type               (NautilusFile                   *file);
+gboolean                nautilus_file_can_poll_for_media                (NautilusFile                   *file);
+gboolean                nautilus_file_is_media_check_automatic          (NautilusFile                   *file);
 
 void                    nautilus_file_mount                             (NautilusFile                   *file,
 									 GMountOperation                *mount_op,
 									 GCancellable                   *cancellable,
 									 NautilusFileOperationCallback   callback,
 									 gpointer                        callback_data);
-void                    nautilus_file_unmount                           (NautilusFile                   *file);
-void                    nautilus_file_eject                             (NautilusFile                   *file);
+void                    nautilus_file_unmount                           (NautilusFile                   *file,
+									 GMountOperation                *mount_op,
+									 GCancellable                   *cancellable,
+									 NautilusFileOperationCallback   callback,
+									 gpointer                        callback_data);
+void                    nautilus_file_eject                             (NautilusFile                   *file,
+									 GMountOperation                *mount_op,
+									 GCancellable                   *cancellable,
+									 NautilusFileOperationCallback   callback,
+									 gpointer                        callback_data);
 
 void                    nautilus_file_start                             (NautilusFile                   *file,
 									 GMountOperation                *start_op,
 									 GCancellable                   *cancellable,
 									 NautilusFileOperationCallback   callback,
 									 gpointer                        callback_data);
-void                    nautilus_file_stop                              (NautilusFile                   *file);
+void                    nautilus_file_stop                              (NautilusFile                   *file,
+									 GMountOperation                *mount_op,
+									 GCancellable                   *cancellable,
+									 NautilusFileOperationCallback   callback,
+									 gpointer                        callback_data);
+void                    nautilus_file_poll_for_media                    (NautilusFile                   *file);
 
 /* Basic operations for file objects. */
 void                    nautilus_file_set_owner                         (NautilusFile                   *file,
@@ -525,15 +541,29 @@ typedef struct {
 							  GCancellable                   *cancellable,
 							  NautilusFileOperationCallback   callback,
 							  gpointer                        callback_data);
-	void                 (* unmount)                 (NautilusFile *file);
-	void                 (* eject)                   (NautilusFile *file);
+	void                 (* unmount)                 (NautilusFile                   *file,
+							  GMountOperation                *mount_op,
+							  GCancellable                   *cancellable,
+							  NautilusFileOperationCallback   callback,
+							  gpointer                        callback_data);
+	void                 (* eject)                   (NautilusFile                   *file,
+							  GMountOperation                *mount_op,
+							  GCancellable                   *cancellable,
+							  NautilusFileOperationCallback   callback,
+							  gpointer                        callback_data);
 
 	void                  (* start)                  (NautilusFile                   *file,
 							  GMountOperation                *start_op,
 							  GCancellable                   *cancellable,
 							  NautilusFileOperationCallback   callback,
 							  gpointer                        callback_data);
-	void                 (* stop)                    (NautilusFile *file);
+	void                 (* stop)                    (NautilusFile                   *file,
+							  GMountOperation                *mount_op,
+							  GCancellable                   *cancellable,
+							  NautilusFileOperationCallback   callback,
+							  gpointer                        callback_data);
+
+	void                 (* poll_for_media)          (NautilusFile                   *file);
 } NautilusFileClass;
 
 #endif /* NAUTILUS_FILE_H */
diff --git a/libnautilus-private/nautilus-vfs-file.c b/libnautilus-private/nautilus-vfs-file.c
index c3e9bd3..97faccd 100644
--- a/libnautilus-private/nautilus-vfs-file.c
+++ b/libnautilus-private/nautilus-vfs-file.c
@@ -413,8 +413,8 @@ vfs_file_unmount_callback (GObject *source_object,
 	op = callback_data;
 
 	error = NULL;
-	unmounted = g_file_unmount_mountable_finish (G_FILE (source_object),
-						    res, &error);
+	unmounted = g_file_unmount_mountable_with_operation_finish (G_FILE (source_object),
+								    res, &error);
 	
     if (!unmounted &&
 	error->domain == G_IO_ERROR && 
@@ -431,19 +431,28 @@ vfs_file_unmount_callback (GObject *source_object,
 }
 
 static void
-vfs_file_unmount (NautilusFile *file)
+vfs_file_unmount (NautilusFile                   *file,
+		  GMountOperation                *mount_op,
+		  GCancellable                   *cancellable,
+		  NautilusFileOperationCallback   callback,
+		  gpointer                        callback_data)
 {
 	NautilusFileOperation *op;
 	GFile *location;
 	
-	op = nautilus_file_operation_new (file, NULL, NULL);
+	op = nautilus_file_operation_new (file, callback, callback_data);
+	if (cancellable) {
+		g_object_unref (op->cancellable);
+		op->cancellable = g_object_ref (cancellable);
+	}
 
 	location = nautilus_file_get_location (file);
-	g_file_unmount_mountable (location,
-				G_MOUNT_UNMOUNT_NONE,
-				op->cancellable,
-				vfs_file_unmount_callback,
-				op);
+	g_file_unmount_mountable_with_operation (location,
+						 G_MOUNT_UNMOUNT_NONE,
+						 mount_op,
+						 op->cancellable,
+						 vfs_file_unmount_callback,
+						 op);
 	g_object_unref (location);
 }
 
@@ -459,8 +468,8 @@ vfs_file_eject_callback (GObject *source_object,
 	op = callback_data;
 
 	error = NULL;
-	ejected = g_file_eject_mountable_finish (G_FILE (source_object),
-						    res, &error);
+	ejected = g_file_eject_mountable_with_operation_finish (G_FILE (source_object),
+								res, &error);
 
 	if (!ejected &&
 	    error->domain == G_IO_ERROR &&
@@ -477,19 +486,28 @@ vfs_file_eject_callback (GObject *source_object,
 }
 
 static void
-vfs_file_eject (NautilusFile *file)
+vfs_file_eject (NautilusFile                   *file,
+		GMountOperation                *mount_op,
+		GCancellable                   *cancellable,
+		NautilusFileOperationCallback   callback,
+		gpointer                        callback_data)
 {
 	NautilusFileOperation *op;
 	GFile *location;
 	
-	op = nautilus_file_operation_new (file, NULL, NULL);
+	op = nautilus_file_operation_new (file, callback, callback_data);
+	if (cancellable) {
+		g_object_unref (op->cancellable);
+		op->cancellable = g_object_ref (cancellable);
+	}
 
 	location = nautilus_file_get_location (file);
-	g_file_eject_mountable (location,
-				G_MOUNT_UNMOUNT_NONE,
-				op->cancellable,
-				vfs_file_eject_callback,
-				op);
+	g_file_eject_mountable_with_operation (location,
+					       G_MOUNT_UNMOUNT_NONE,
+					       mount_op,
+					       op->cancellable,
+					       vfs_file_eject_callback,
+					       op);
 	g_object_unref (location);
 }
 
@@ -525,7 +543,7 @@ vfs_file_start_callback (GObject *source_object,
 
 static void
 vfs_file_start (NautilusFile                   *file,
-		GMountOperation                *start_op,
+		GMountOperation                *mount_op,
 		GCancellable                   *cancellable,
 		NautilusFileOperationCallback   callback,
 		gpointer                        callback_data)
@@ -554,7 +572,7 @@ vfs_file_start (NautilusFile                   *file,
 	location = nautilus_file_get_location (file);
 	g_file_start_mountable (location,
 				0,
-				start_op,
+				mount_op,
 				op->cancellable,
 				vfs_file_start_callback,
 				op);
@@ -591,16 +609,25 @@ vfs_file_stop_callback (GObject *source_object,
 }
 
 static void
-vfs_file_stop (NautilusFile *file)
+vfs_file_stop (NautilusFile                   *file,
+	       GMountOperation                *mount_op,
+	       GCancellable                   *cancellable,
+	       NautilusFileOperationCallback   callback,
+	       gpointer                        callback_data)
 {
 	NautilusFileOperation *op;
 	GFile *location;
 
-	op = nautilus_file_operation_new (file, NULL, NULL);
+	op = nautilus_file_operation_new (file, callback, callback_data);
+	if (cancellable) {
+		g_object_unref (op->cancellable);
+		op->cancellable = g_object_ref (cancellable);
+	}
 
 	location = nautilus_file_get_location (file);
 	g_file_stop_mountable (location,
 			       G_MOUNT_UNMOUNT_NONE,
+			       mount_op,
 			       op->cancellable,
 			       vfs_file_stop_callback,
 			       op);
@@ -608,6 +635,51 @@ vfs_file_stop (NautilusFile *file)
 }
 
 static void
+vfs_file_poll_callback (GObject *source_object,
+			GAsyncResult *res,
+			gpointer callback_data)
+{
+	NautilusFileOperation *op;
+	gboolean stopped;
+	GError *error;
+
+	op = callback_data;
+
+	error = NULL;
+	stopped = g_file_poll_mountable_finish (G_FILE (source_object),
+						res, &error);
+
+	if (!stopped &&
+	    error->domain == G_IO_ERROR &&
+	    (error->code == G_IO_ERROR_FAILED_HANDLED ||
+	     error->code == G_IO_ERROR_CANCELLED)) {
+		g_error_free (error);
+		error = NULL;
+	}
+
+	nautilus_file_operation_complete (op, G_FILE (source_object), error);
+	if (error) {
+		g_error_free (error);
+	}
+}
+
+static void
+vfs_file_poll_for_media (NautilusFile *file)
+{
+	NautilusFileOperation *op;
+	GFile *location;
+
+	op = nautilus_file_operation_new (file, NULL, NULL);
+
+	location = nautilus_file_get_location (file);
+	g_file_poll_mountable (location,
+			       op->cancellable,
+			       vfs_file_poll_callback,
+			       op);
+	g_object_unref (location);
+}
+
+static void
 nautilus_vfs_file_init (gpointer object, gpointer klass)
 {
 	NautilusVFSFile *file;
@@ -639,4 +711,5 @@ nautilus_vfs_file_class_init (gpointer klass)
 	file_class->eject = vfs_file_eject;
 	file_class->start = vfs_file_start;
 	file_class->stop = vfs_file_stop;
+	file_class->poll_for_media = vfs_file_poll_for_media;
 }
diff --git a/src/file-manager/fm-actions.h b/src/file-manager/fm-actions.h
index 77dc94f..9bb01f6 100644
--- a/src/file-manager/fm-actions.h
+++ b/src/file-manager/fm-actions.h
@@ -71,18 +71,21 @@
 #define FM_ACTION_FORMAT_VOLUME "Format Volume"
 #define FM_ACTION_START_VOLUME "Start Volume"
 #define FM_ACTION_STOP_VOLUME "Stop Volume"
+#define FM_ACTION_POLL "Poll"
 #define FM_ACTION_SELF_MOUNT_VOLUME "Self Mount Volume"
 #define FM_ACTION_SELF_UNMOUNT_VOLUME "Self Unmount Volume"
 #define FM_ACTION_SELF_EJECT_VOLUME "Self Eject Volume"
 #define FM_ACTION_SELF_FORMAT_VOLUME "Self Format Volume"
 #define FM_ACTION_SELF_START_VOLUME "Self Start Volume"
 #define FM_ACTION_SELF_STOP_VOLUME "Self Stop Volume"
+#define FM_ACTION_SELF_POLL "Self Poll"
 #define FM_ACTION_LOCATION_MOUNT_VOLUME "Location Mount Volume"
 #define FM_ACTION_LOCATION_UNMOUNT_VOLUME "Location Unmount Volume"
 #define FM_ACTION_LOCATION_EJECT_VOLUME "Location Eject Volume"
 #define FM_ACTION_LOCATION_FORMAT_VOLUME "Location Format Volume"
 #define FM_ACTION_LOCATION_START_VOLUME "Location Start Volume"
 #define FM_ACTION_LOCATION_STOP_VOLUME "Location Stop Volume"
+#define FM_ACTION_LOCATION_POLL "Location Poll"
 #define FM_ACTION_SCRIPTS "Scripts"
 #define FM_ACTION_NEW_DOCUMENTS "New Documents"
 #define FM_ACTION_NEW_EMPTY_FILE "New Empty File"
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c
index ee5fde5..3dbf5c3 100644
--- a/src/file-manager/fm-directory-view.c
+++ b/src/file-manager/fm-directory-view.c
@@ -357,6 +357,8 @@ static void action_start_volume_callback           (GtkAction *action,
 						    gpointer   data);
 static void action_stop_volume_callback            (GtkAction *action,
 						    gpointer   data);
+static void action_detect_media_callback           (GtkAction *action,
+						    gpointer   data);
 
 /* location popup-related actions */
 
@@ -5943,6 +5945,51 @@ file_mount_callback (NautilusFile  *file,
 }
 
 static void
+file_unmount_callback (NautilusFile  *file,
+		       GFile         *result_location,
+		       GError        *error,
+		       gpointer       callback_data)
+{
+	if (error != NULL &&
+	    (error->domain != G_IO_ERROR ||
+	     (error->code != G_IO_ERROR_CANCELLED &&
+	      error->code != G_IO_ERROR_FAILED_HANDLED))) {
+		eel_show_error_dialog (_("Unable to unmount location"),
+				       error->message, NULL);
+	}
+}
+
+static void
+file_eject_callback (NautilusFile  *file,
+		     GFile         *result_location,
+		     GError        *error,
+		     gpointer       callback_data)
+{
+	if (error != NULL &&
+	    (error->domain != G_IO_ERROR ||
+	     (error->code != G_IO_ERROR_CANCELLED &&
+	      error->code != G_IO_ERROR_FAILED_HANDLED))) {
+		eel_show_error_dialog (_("Unable to eject location"),
+				       error->message, NULL);
+	}
+}
+
+static void
+file_stop_callback (NautilusFile  *file,
+		    GFile         *result_location,
+		    GError        *error,
+		    gpointer       callback_data)
+{
+	if (error != NULL &&
+	    (error->domain != G_IO_ERROR ||
+	     (error->code != G_IO_ERROR_CANCELLED &&
+	      error->code != G_IO_ERROR_FAILED_HANDLED))) {
+		eel_show_error_dialog (_("Unable to stop drive"),
+				       error->message, NULL);
+	}
+}
+
+static void
 action_mount_volume_callback (GtkAction *action,
 			      gpointer data)
 {
@@ -5982,7 +6029,11 @@ action_unmount_volume_callback (GtkAction *action,
 	for (l = selection; l != NULL; l = l->next) {
 		file = NAUTILUS_FILE (l->data);
 		if (nautilus_file_can_unmount (file)) {
-			nautilus_file_unmount (file);
+			GMountOperation *mount_op;
+			mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
+			nautilus_file_unmount (file, mount_op, NULL,
+					       file_unmount_callback, NULL);
+			g_object_unref (mount_op);
 		}
 	}
 	nautilus_file_list_free (selection);
@@ -6026,7 +6077,11 @@ action_eject_volume_callback (GtkAction *action,
 		file = NAUTILUS_FILE (l->data);
 		
 		if (nautilus_file_can_eject (file)) {
-			nautilus_file_eject (file);
+			GMountOperation *mount_op;
+			mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
+			nautilus_file_eject (file, mount_op, NULL,
+					     file_eject_callback, NULL);
+			g_object_unref (mount_op);
 		}
 	}	
 	nautilus_file_list_free (selection);
@@ -6063,7 +6118,7 @@ action_start_volume_callback (GtkAction *action,
 	for (l = selection; l != NULL; l = l->next) {
 		file = NAUTILUS_FILE (l->data);
 
-		if (nautilus_file_can_start (file)) {
+		if (nautilus_file_can_start (file) || nautilus_file_can_start_degraded (file)) {
 			mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
 			nautilus_file_start (file, mount_op, NULL,
 					     file_start_callback, NULL);
@@ -6088,7 +6143,32 @@ action_stop_volume_callback (GtkAction *action,
 		file = NAUTILUS_FILE (l->data);
 
 		if (nautilus_file_can_stop (file)) {
-			nautilus_file_stop (file);
+			GMountOperation *mount_op;
+			mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
+			nautilus_file_stop (file, mount_op, NULL,
+					    file_stop_callback, NULL);
+			g_object_unref (mount_op);
+		}
+	}
+	nautilus_file_list_free (selection);
+}
+
+static void
+action_detect_media_callback (GtkAction *action,
+			      gpointer   data)
+{
+	NautilusFile *file;
+	GList *selection, *l;
+	FMDirectoryView *view;
+
+        view = FM_DIRECTORY_VIEW (data);
+
+	selection = fm_directory_view_get_selection (view);
+	for (l = selection; l != NULL; l = l->next) {
+		file = NAUTILUS_FILE (l->data);
+
+		if (nautilus_file_can_poll_for_media (file) && !nautilus_file_is_media_check_automatic (file)) {
+			nautilus_file_poll_for_media (file);
 		}
 	}
 	nautilus_file_list_free (selection);
@@ -6120,6 +6200,7 @@ action_self_unmount_volume_callback (GtkAction *action,
 {
 	NautilusFile *file;
 	FMDirectoryView *view;
+	GMountOperation *mount_op;
 
 	view = FM_DIRECTORY_VIEW (data);
 
@@ -6128,7 +6209,9 @@ action_self_unmount_volume_callback (GtkAction *action,
 		return;
 	}
 
-	nautilus_file_unmount (file);
+	mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
+	nautilus_file_unmount (file, mount_op, NULL, file_unmount_callback, NULL);
+	g_object_unref (mount_op);
 }
 
 static void
@@ -6137,6 +6220,7 @@ action_self_eject_volume_callback (GtkAction *action,
 {
 	NautilusFile *file;
 	FMDirectoryView *view;
+	GMountOperation *mount_op;
 
 	view = FM_DIRECTORY_VIEW (data);
 
@@ -6145,7 +6229,9 @@ action_self_eject_volume_callback (GtkAction *action,
 		return;
 	}
 	
-	nautilus_file_eject (file);
+	mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
+	nautilus_file_eject (file, mount_op, NULL, file_eject_callback, NULL);
+	g_object_unref (mount_op);
 }
 
 static void 
@@ -6175,7 +6261,7 @@ action_self_start_volume_callback (GtkAction *action,
 {
 	NautilusFile *file;
 	FMDirectoryView *view;
-	GMountOperation *start_op;
+	GMountOperation *mount_op;
 
 	view = FM_DIRECTORY_VIEW (data);
 
@@ -6184,9 +6270,9 @@ action_self_start_volume_callback (GtkAction *action,
 		return;
 	}
 
-	start_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
-	nautilus_file_start (file, start_op, NULL, file_start_callback, NULL);
-	g_object_unref (start_op);
+	mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
+	nautilus_file_start (file, mount_op, NULL, file_start_callback, NULL);
+	g_object_unref (mount_op);
 }
 
 static void
@@ -6195,6 +6281,27 @@ action_self_stop_volume_callback (GtkAction *action,
 {
 	NautilusFile *file;
 	FMDirectoryView *view;
+	GMountOperation *mount_op;
+
+	view = FM_DIRECTORY_VIEW (data);
+
+	file = fm_directory_view_get_directory_as_file (view);
+	if (file == NULL) {
+		return;
+	}
+
+	mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
+	nautilus_file_stop (file, mount_op, NULL,
+			    file_stop_callback, NULL);
+	g_object_unref (mount_op);
+}
+
+static void
+action_self_detect_media_callback (GtkAction *action,
+				   gpointer   data)
+{
+	NautilusFile *file;
+	FMDirectoryView *view;
 
 	view = FM_DIRECTORY_VIEW (data);
 
@@ -6203,7 +6310,7 @@ action_self_stop_volume_callback (GtkAction *action,
 		return;
 	}
 
-	nautilus_file_stop (file);
+	nautilus_file_poll_for_media (file);
 }
 
 static void
@@ -6232,6 +6339,7 @@ action_location_unmount_volume_callback (GtkAction *action,
 {
 	NautilusFile *file;
 	FMDirectoryView *view;
+	GMountOperation *mount_op;
 
 	view = FM_DIRECTORY_VIEW (data);
 
@@ -6240,7 +6348,10 @@ action_location_unmount_volume_callback (GtkAction *action,
 		return;
 	}
 
-	nautilus_file_unmount (file);
+	mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
+	nautilus_file_unmount (file, mount_op, NULL,
+			       file_unmount_callback, NULL);
+	g_object_unref (mount_op);
 }
 
 static void
@@ -6249,6 +6360,7 @@ action_location_eject_volume_callback (GtkAction *action,
 {
 	NautilusFile *file;
 	FMDirectoryView *view;
+	GMountOperation *mount_op;
 
 	view = FM_DIRECTORY_VIEW (data);
 
@@ -6257,7 +6369,10 @@ action_location_eject_volume_callback (GtkAction *action,
 		return;
 	}
 	
-	nautilus_file_eject (file);
+	mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
+	nautilus_file_eject (file, mount_op, NULL,
+			     file_eject_callback, NULL);
+	g_object_unref (mount_op);
 }
 
 static void 
@@ -6287,7 +6402,7 @@ action_location_start_volume_callback (GtkAction *action,
 {
 	NautilusFile *file;
 	FMDirectoryView *view;
-	GMountOperation *start_op;
+	GMountOperation *mount_op;
 
 	view = FM_DIRECTORY_VIEW (data);
 
@@ -6296,9 +6411,9 @@ action_location_start_volume_callback (GtkAction *action,
 		return;
 	}
 
-	start_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
-	nautilus_file_start (file, start_op, NULL, file_start_callback, NULL);
-	g_object_unref (start_op);
+	mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
+	nautilus_file_start (file, mount_op, NULL, file_start_callback, NULL);
+	g_object_unref (mount_op);
 }
 
 static void
@@ -6307,6 +6422,27 @@ action_location_stop_volume_callback (GtkAction *action,
 {
 	NautilusFile *file;
 	FMDirectoryView *view;
+	GMountOperation *mount_op;
+
+	view = FM_DIRECTORY_VIEW (data);
+
+	file = view->details->location_popup_directory_as_file;
+	if (file == NULL) {
+		return;
+	}
+
+	mount_op = gtk_mount_operation_new (fm_directory_view_get_containing_window (view));
+	nautilus_file_stop (file, mount_op, NULL,
+			    file_stop_callback, NULL);
+	g_object_unref (mount_op);
+}
+
+static void
+action_location_detect_media_callback (GtkAction *action,
+				       gpointer   data)
+{
+	NautilusFile *file;
+	FMDirectoryView *view;
 
 	view = FM_DIRECTORY_VIEW (data);
 
@@ -6315,7 +6451,7 @@ action_location_stop_volume_callback (GtkAction *action,
 		return;
 	}
 
-	nautilus_file_stop (file);
+	nautilus_file_poll_for_media (file);
 }
 
 static void
@@ -6884,6 +7020,10 @@ static const GtkActionEntry directory_view_entries[] = {
   /* label, accelerator */       N_("_Stop"), NULL,
   /* tooltip */                  N_("Stop the selected volume"),
                                  G_CALLBACK (action_stop_volume_callback) },
+  /* name, stock id */         { "Poll", NULL,
+  /* label, accelerator */       N_("_Detect Media"), NULL,
+  /* tooltip */                  N_("Detect media in the selected drive"),
+                                 G_CALLBACK (action_detect_media_callback) },
   /* name, stock id */         { "Self Mount Volume", NULL,
   /* label, accelerator */       N_("_Mount"), NULL,
   /* tooltip */                  N_("Mount the volume associated with the open folder"),
@@ -6908,6 +7048,10 @@ static const GtkActionEntry directory_view_entries[] = {
   /* label, accelerator */       N_("_Stop"), NULL,
   /* tooltip */                  N_("Stop the volume associated with the open folder"),
                                  G_CALLBACK (action_self_stop_volume_callback) },
+  /* name, stock id */         { "Self Poll", NULL,
+  /* label, accelerator */       N_("_Detect Media"), NULL,
+  /* tooltip */                  N_("Detect media in the selected drive"),
+                                 G_CALLBACK (action_self_detect_media_callback) },
   /* name, stock id */         { "OpenCloseParent", NULL,
   /* label, accelerator */       N_("Open File and Close window"), "<alt><shift>Down",
   /* tooltip */                  NULL,
@@ -6985,6 +7129,10 @@ static const GtkActionEntry directory_view_entries[] = {
   /* label, accelerator */       N_("_Stop"), NULL,
   /* tooltip */                  N_("Stop the volume associated with this folder"),
                                  G_CALLBACK (action_location_stop_volume_callback) },
+  /* name, stock id */         { "Location Poll", NULL,
+  /* label, accelerator */       N_("_Detect Media"), NULL,
+  /* tooltip */                  N_("Detect media in the selected drive"),
+                                 G_CALLBACK (action_location_detect_media_callback) },
 
   /* name, stock id */         { "LocationProperties", GTK_STOCK_PROPERTIES,
   /* label, accelerator */       N_("_Properties"), NULL,
@@ -7273,6 +7421,7 @@ file_should_show_foreach (NautilusFile        *file,
 			  gboolean            *show_format,
 			  gboolean            *show_start,
 			  gboolean            *show_stop,
+			  gboolean            *show_poll,
 			  GDriveStartStopType *start_stop_type)
 {
 	char *uri;
@@ -7284,6 +7433,7 @@ file_should_show_foreach (NautilusFile        *file,
 	*show_format = FALSE;
 	*show_start = FALSE;
 	*show_stop = FALSE;
+	*show_poll = FALSE;
 
 	if (nautilus_file_can_eject (file)) {
 		*show_eject = TRUE;
@@ -7304,7 +7454,7 @@ file_should_show_foreach (NautilusFile        *file,
 #endif
 	}
 
-	if (nautilus_file_can_start (file)) {
+	if (nautilus_file_can_start (file) || nautilus_file_can_start_degraded (file)) {
 		*show_start = TRUE;
 	}
 
@@ -7312,6 +7462,10 @@ file_should_show_foreach (NautilusFile        *file,
 		*show_stop = TRUE;
 	}
 
+	if (nautilus_file_can_poll_for_media (file) && !nautilus_file_is_media_check_automatic (file)) {
+		*show_poll = TRUE;
+	}
+
 	*start_stop_type = nautilus_file_get_start_stop_type (file);
 
 	if (nautilus_file_is_nautilus_link (file)) {
@@ -7336,6 +7490,7 @@ file_should_show_self (NautilusFile        *file,
 		       gboolean            *show_format,
 		       gboolean            *show_start,
 		       gboolean            *show_stop,
+		       gboolean            *show_poll,
 		       GDriveStartStopType *start_stop_type)
 {
 	*show_mount = FALSE;
@@ -7344,6 +7499,7 @@ file_should_show_self (NautilusFile        *file,
 	*show_format = FALSE;
 	*show_start = FALSE;
 	*show_stop = FALSE;
+	*show_poll = FALSE;
 
 	if (file == NULL) {
 		return;
@@ -7367,7 +7523,7 @@ file_should_show_self (NautilusFile        *file,
 	}
 #endif
 
-	if (nautilus_file_can_start (file)) {
+	if (nautilus_file_can_start (file) || nautilus_file_can_start_degraded (file)) {
 		*show_start = TRUE;
 	}
 
@@ -7375,6 +7531,10 @@ file_should_show_self (NautilusFile        *file,
 		*show_stop = TRUE;
 	}
 
+	if (nautilus_file_can_poll_for_media (file) && !nautilus_file_is_media_check_automatic (file)) {
+		*show_poll = TRUE;
+	}
+
 	*start_stop_type = nautilus_file_get_start_stop_type (file);
 
 }
@@ -7581,6 +7741,7 @@ real_update_menus_volumes (FMDirectoryView *view,
 	gboolean show_format;
 	gboolean show_start;
 	gboolean show_stop;
+	gboolean show_poll;
 	GDriveStartStopType start_stop_type;
 	gboolean show_self_mount;
 	gboolean show_self_unmount;
@@ -7588,6 +7749,7 @@ real_update_menus_volumes (FMDirectoryView *view,
 	gboolean show_self_format;
 	gboolean show_self_start;
 	gboolean show_self_stop;
+	gboolean show_self_poll;
 	GDriveStartStopType self_start_stop_type;
 	GtkAction *action;
 
@@ -7598,13 +7760,14 @@ real_update_menus_volumes (FMDirectoryView *view,
 	show_format = (selection != NULL && selection_count == 1);
 	show_start = (selection != NULL && selection_count == 1);
 	show_stop = (selection != NULL && selection_count == 1);
+	show_poll = (selection != NULL && selection_count == 1);
 	start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
 	self_start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
 
 	for (l = selection; l != NULL && (show_mount || show_unmount
 					  || show_eject || show_connect
                                           || show_format || show_start
-					  || show_stop);
+					  || show_stop || show_poll);
 	     l = l->next) {
 		gboolean show_mount_one;
 		gboolean show_unmount_one;
@@ -7613,6 +7776,7 @@ real_update_menus_volumes (FMDirectoryView *view,
 		gboolean show_format_one;
 		gboolean show_start_one;
 		gboolean show_stop_one;
+		gboolean show_poll_one;
 
 		file = NAUTILUS_FILE (l->data);
 		file_should_show_foreach (file,
@@ -7623,6 +7787,7 @@ real_update_menus_volumes (FMDirectoryView *view,
                                           &show_format_one,
                                           &show_start_one,
                                           &show_stop_one,
+					  &show_poll_one,
 					  &start_stop_type);
 
 		show_mount &= show_mount_one;
@@ -7632,6 +7797,7 @@ real_update_menus_volumes (FMDirectoryView *view,
 		show_format &= show_format_one;
 		show_start &= show_start_one;
 		show_stop &= show_stop_one;
+		show_poll &= show_poll_one;
 	}
 
 	action = gtk_action_group_get_action (view->details->dir_action_group,
@@ -7712,8 +7878,12 @@ real_update_menus_volumes (FMDirectoryView *view,
 		}
 	}
 
+	action = gtk_action_group_get_action (view->details->dir_action_group,
+					      FM_ACTION_POLL);
+	gtk_action_set_visible (action, show_poll);
+
 	show_self_mount = show_self_unmount = show_self_eject =
-		show_self_format = show_self_start = show_self_stop = FALSE;
+		show_self_format = show_self_start = show_self_stop = show_self_poll = FALSE;
 
 	file = fm_directory_view_get_directory_as_file (view);
 	file_should_show_self (file,
@@ -7723,6 +7893,7 @@ real_update_menus_volumes (FMDirectoryView *view,
 			       &show_self_format,
 			       &show_self_start,
 			       &show_self_stop,
+			       &show_self_poll,
 			       &self_start_stop_type);
 
 	action = gtk_action_group_get_action (view->details->dir_action_group,
@@ -7798,6 +7969,11 @@ real_update_menus_volumes (FMDirectoryView *view,
 			break;
 		}
 	}
+
+	action = gtk_action_group_get_action (view->details->dir_action_group,
+					      FM_ACTION_SELF_POLL);
+	gtk_action_set_visible (action, show_self_poll);
+
 }
 
 static void
@@ -7812,6 +7988,7 @@ real_update_location_menu_volumes (FMDirectoryView *view)
 	gboolean show_format;
 	gboolean show_start;
 	gboolean show_stop;
+	gboolean show_poll;
 	GDriveStartStopType start_stop_type;
 
 	g_assert (FM_IS_DIRECTORY_VIEW (view));
@@ -7826,6 +8003,7 @@ real_update_location_menu_volumes (FMDirectoryView *view)
 				  &show_format,
 				  &show_start,
 				  &show_stop,
+				  &show_poll,
 				  &start_stop_type);
 
 	action = gtk_action_group_get_action (view->details->dir_action_group,
@@ -7901,6 +8079,10 @@ real_update_location_menu_volumes (FMDirectoryView *view)
 			break;
 		}
 	}
+
+	action = gtk_action_group_get_action (view->details->dir_action_group,
+					      FM_ACTION_LOCATION_POLL);
+	gtk_action_set_visible (action, show_poll);
 }
 
 /* TODO: we should split out this routine into two functions:
diff --git a/src/file-manager/nautilus-directory-view-ui.xml b/src/file-manager/nautilus-directory-view-ui.xml
index 09252f0..e4dfb29 100644
--- a/src/file-manager/nautilus-directory-view-ui.xml
+++ b/src/file-manager/nautilus-directory-view-ui.xml
@@ -42,6 +42,7 @@
 			<menuitem name="Self Format Volume" action="Self Format Volume"/>
 			<menuitem name="Self Start Volume" action="Self Start Volume"/>
 			<menuitem name="Self Stop Volume" action="Self Stop Volume"/>
+			<menuitem name="Self Poll" action="Self Poll"/>
 			<separator name="Properties Separator"/>
 			<menuitem name="Properties" action="Properties"/>
 		</placeholder>
@@ -114,6 +115,7 @@
 		<menuitem name="Self Format Volume" action="Self Format Volume"/>
 		<menuitem name="Self Start Volume" action="Self Start Volume"/>
 		<menuitem name="Self Stop Volume" action="Self Stop Volume"/>
+		<menuitem name="Self Poll" action="Self Poll"/>
 		<separator name="Properties separator"/>
 		<menuitem name="SelfProperties" action="SelfProperties"/>
 	</placeholder>
@@ -171,6 +173,7 @@
 		 <menuitem name="Format Volume" action="Format Volume"/>
 		 <menuitem name="Start Volume" action="Start Volume"/>
 		 <menuitem name="Stop Volume" action="Stop Volume"/>
+		 <menuitem name="Poll" action="Poll"/>
         </placeholder>
         <menuitem name="Connect To Server Link" action="Connect To Server Link"/>
         <separator name="Properties Separator"/>
@@ -201,6 +204,7 @@
 	<menuitem name="Location Format Volume" action="Location Format Volume"/>
 	<menuitem name="Location Start Volume" action="Location Start Volume"/>
 	<menuitem name="Location Stop Volume" action="Location Stop Volume"/>
+	<menuitem name="Location Poll" action="Location Poll"/>
 	<separator name="Properties Separator"/>
 	<menuitem name="LocationProperties" action="LocationProperties"/>
 </popup>
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index 23a47c3..7bd4892 100644
--- a/src/nautilus-application.c
+++ b/src/nautilus-application.c
@@ -1479,7 +1479,7 @@ drive_eject_cb (GObject *source_object,
 	char *primary;
 	char *name;
 	error = NULL;
-	if (!g_drive_eject_finish (G_DRIVE (source_object), res, &error)) {
+	if (!g_drive_eject_with_operation_finish (G_DRIVE (source_object), res, &error)) {
 		if (error->code != G_IO_ERROR_FAILED_HANDLED) {
 			name = g_drive_get_name (G_DRIVE (source_object));
 			primary = g_strdup_printf (_("Unable to eject %s"), name);
@@ -1497,7 +1497,11 @@ static void
 drive_eject_button_pressed (GDrive *drive,
 			    NautilusApplication *application)
 {
-	g_drive_eject (drive, 0, NULL, drive_eject_cb, NULL);
+	GMountOperation *mount_op;
+
+	mount_op = gtk_mount_operation_new (NULL);
+	g_drive_eject_with_operation (drive, 0, mount_op, NULL, drive_eject_cb, NULL);
+	g_object_unref (mount_op);
 }
 
 static void
diff --git a/src/nautilus-places-sidebar.c b/src/nautilus-places-sidebar.c
index 24677d2..144dab6 100644
--- a/src/nautilus-places-sidebar.c
+++ b/src/nautilus-places-sidebar.c
@@ -1324,7 +1324,7 @@ check_visibility (GMount           *mount,
 		    g_drive_can_poll_for_media (drive))
 			*show_rescan = TRUE;
 
-		*show_start = g_drive_can_start (drive);
+		*show_start = g_drive_can_start (drive) || g_drive_can_start_degraded (drive);
 		*show_stop  = g_drive_can_stop (drive);
 	}
 
@@ -1587,12 +1587,13 @@ open_selected_bookmark (NautilusPlacesSidebar *sidebar,
 			nautilus_file_operations_mount_volume_full (NULL, volume, FALSE,
 								    volume_mounted_cb,
 								    G_OBJECT (sidebar));
-		} else if (volume == NULL && drive != NULL && g_drive_can_start (drive)) {
-			GMountOperation *start_op;
+		} else if (volume == NULL && drive != NULL &&
+			   (g_drive_can_start (drive) || g_drive_can_start_degraded (drive))) {
+			GMountOperation *mount_op;
 
-			start_op = gtk_mount_operation_new (NULL);
-			g_drive_start (drive, G_DRIVE_START_NONE, start_op, NULL, drive_start_from_bookmark_cb, NULL);
-			g_object_unref (start_op);
+			mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
+			g_drive_start (drive, G_DRIVE_START_NONE, mount_op, NULL, drive_start_from_bookmark_cb, NULL);
+			g_object_unref (mount_op);
 		}
 
 		if (drive != NULL)
@@ -1768,7 +1769,7 @@ drive_eject_cb (GObject *source_object,
 	char *primary;
 	char *name;
 	error = NULL;
-	if (!g_drive_eject_finish (G_DRIVE (source_object), res, &error)) {
+	if (!g_drive_eject_with_operation_finish (G_DRIVE (source_object), res, &error)) {
 		if (error->code != G_IO_ERROR_FAILED_HANDLED) {
 			name = g_drive_get_name (G_DRIVE (source_object));
 			primary = g_strdup_printf (_("Unable to eject %s"), name);
@@ -1791,7 +1792,7 @@ volume_eject_cb (GObject *source_object,
 	char *primary;
 	char *name;
 	error = NULL;
-	if (!g_volume_eject_finish (G_VOLUME (source_object), res, &error)) {
+	if (!g_volume_eject_with_operation_finish (G_VOLUME (source_object), res, &error)) {
 		if (error->code != G_IO_ERROR_FAILED_HANDLED) {
 			name = g_volume_get_name (G_VOLUME (source_object));
 			primary = g_strdup_printf (_("Unable to eject %s"), name);
@@ -1814,7 +1815,7 @@ mount_eject_cb (GObject *source_object,
 	char *primary;
 	char *name;
 	error = NULL;
-	if (!g_mount_eject_finish (G_MOUNT (source_object), res, &error)) {
+	if (!g_mount_eject_with_operation_finish (G_MOUNT (source_object), res, &error)) {
 		if (error->code != G_IO_ERROR_FAILED_HANDLED) {
 			name = g_mount_get_name (G_MOUNT (source_object));
 			primary = g_strdup_printf (_("Unable to eject %s"), name);
@@ -1834,13 +1835,17 @@ do_eject (GMount *mount,
 	  GDrive *drive,
 	  NautilusPlacesSidebar *sidebar)
 {
+	GMountOperation *mount_op;
+
+	mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
 	if (mount != NULL) {
-		g_mount_eject (mount, 0, NULL, mount_eject_cb, NULL);
+		g_mount_eject_with_operation (mount, 0, mount_op, NULL, mount_eject_cb, NULL);
 	} else if (volume != NULL) {
-		g_volume_eject (volume, 0, NULL, volume_eject_cb, NULL);
+		g_volume_eject_with_operation (volume, 0, mount_op, NULL, volume_eject_cb, NULL);
 	} else if (drive != NULL) {
-		g_drive_eject (drive, 0, NULL, drive_eject_cb, NULL);
+		g_drive_eject_with_operation (drive, 0, mount_op, NULL, drive_eject_cb, NULL);
 	}
+	g_object_unref (mount_op);
 }
 
 static void
@@ -2029,13 +2034,13 @@ start_shortcut_cb (GtkMenuItem           *item,
 			    -1);
 
 	if (drive != NULL) {
-		GMountOperation *start_op;
+		GMountOperation *mount_op;
 
-		start_op = gtk_mount_operation_new (NULL);
+		mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
 
-		g_drive_start (drive, G_DRIVE_START_NONE, start_op, NULL, drive_start_cb, NULL);
+		g_drive_start (drive, G_DRIVE_START_NONE, mount_op, NULL, drive_start_cb, NULL);
 
-		g_object_unref (start_op);
+		g_object_unref (mount_op);
 	}
 	g_object_unref (drive);
 }
@@ -2080,7 +2085,11 @@ stop_shortcut_cb (GtkMenuItem           *item,
 			    -1);
 
 	if (drive != NULL) {
-		g_drive_stop (drive, G_MOUNT_UNMOUNT_NONE, NULL, drive_stop_cb, NULL);
+		GMountOperation *mount_op;
+
+		mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
+		g_drive_stop (drive, G_MOUNT_UNMOUNT_NONE, mount_op, NULL, drive_stop_cb, NULL);
+		g_object_unref (mount_op);
 	}
 	g_object_unref (drive);
 }
@@ -2204,7 +2213,7 @@ bookmarks_build_popup_menu (NautilusPlacesSidebar *sidebar)
 	gtk_widget_show (item);
 	gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
 
-	item = gtk_menu_item_new_with_mnemonic (_("_Rescan"));
+	item = gtk_menu_item_new_with_mnemonic (_("_Detect Media"));
 	sidebar->popup_menu_rescan_item = item;
 	g_signal_connect (item, "activate",
 		    G_CALLBACK (rescan_shortcut_cb), sidebar);



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