From cf9d3778748c701d115c9a1c213a13e16b50c4c5 Mon Sep 17 00:00:00 2001
From: Cosimo Cecchi <cosimoc@gnome.org>
Date: Tue, 15 May 2012 16:12:37 -0400
Subject: [PATCH] places-sidebar: add a notification while ejecting volumes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is a workarond solution until we come up with something better
designed for GNOME 3.6 (by that time we'll also have a proper API in GIO
for this, see [1].
Based on an initial patch by Tomáš Bžatek <tbzatek@redhat.com>
[1] https://bugzilla.gnome.org/show_bug.cgi?id=676111
https://bugzilla.redhat.com/show_bug.cgi?id=819492
https://bugzilla.gnome.org/show_bug.cgi?id=619665
---
src/nautilus-places-sidebar.c | 194 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 172 insertions(+), 22 deletions(-)
diff --git a/src/nautilus-places-sidebar.c b/src/nautilus-places-sidebar.c
index 26dd93e..ddcaeae 100644
--- a/src/nautilus-places-sidebar.c
+++ b/src/nautilus-places-sidebar.c
@@ -53,6 +53,8 @@
#include "nautilus-window.h"
#include "nautilus-window-slot.h"
+#include <libnotify/notify.h>
+
#define DEBUG_FLAG NAUTILUS_DEBUG_PLACES
#include <libnautilus-private/nautilus-debug.h>
@@ -2128,22 +2130,107 @@ unmount_shortcut_cb (GtkMenuItem *item,
do_unmount_selection (sidebar);
}
+typedef struct {
+ NautilusWindow *window;
+ GMountOperation *mount_op;
+ guint timeout_id;
+ NotifyNotification *notify;
+ gchar *device_name;
+ gboolean should_display;
+} EjectOpData;
+
+static void
+eject_notification_pop_down (EjectOpData *data)
+{
+ if (data->timeout_id > 0) {
+ g_source_remove (data->timeout_id);
+ data->timeout_id = 0;
+ }
+
+ if (data->notify != NULL) {
+ notify_notification_close (data->notify, NULL);
+ g_clear_object (&data->notify);
+ }
+}
+
+static void
+free_eject_op_data (EjectOpData *data)
+{
+ gchar *header;
+ NotifyNotification *unplug;
+
+ if (data->timeout_id > 0)
+ g_source_remove (data->timeout_id);
+
+ if (data->notify != NULL) {
+ eject_notification_pop_down (data);
+
+ if (data->should_display) {
+ /* Notification was shown, let's update it we're finished */
+ header = g_strdup_printf (_("You can now unplug %s"), data->device_name);
+ unplug = notify_notification_new (header, NULL, "media-removable");
+
+ notify_notification_show (unplug, NULL);
+ g_object_unref (unplug);
+ }
+ }
+
+ g_free (data->device_name);
+ g_clear_object (&data->window);
+ g_object_unref (data->mount_op);
+
+ g_slice_free (EjectOpData, data);
+}
+
+static void
+eject_notification_pop_up (EjectOpData *data)
+{
+ gchar *header;
+
+ if (!data->should_display) {
+ return;
+ }
+
+ header = g_strdup_printf (_("Writing data to %s"), data->device_name);
+ data->notify = notify_notification_new (header, _("Don't unplug until finished"),
+ "media-removable");
+ g_free (header);
+
+ notify_notification_set_hint (data->notify, "transient", g_variant_new_boolean (TRUE));
+ notify_notification_set_urgency (data->notify, NOTIFY_URGENCY_CRITICAL);
+
+ notify_notification_show (data->notify, NULL);
+}
+
+static void
+eject_mount_op_reply (GMountOperation *op,
+ GMountOperationResult result,
+ gpointer user_data)
+{
+ EjectOpData *data = user_data;
+ gint choice;
+
+ g_object_get (op, "choice", &choice, NULL);
+ if (choice == 0) {
+ eject_notification_pop_up (data);
+ }
+}
+
static void
drive_eject_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
- NautilusWindow *window;
+ EjectOpData *data = user_data;
GError *error;
char *primary;
char *name;
- window = user_data;
- g_object_unref (window);
-
error = NULL;
if (!g_drive_eject_with_operation_finish (G_DRIVE (source_object), res, &error)) {
if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ eject_notification_pop_down (data);
+
name = g_drive_get_name (G_DRIVE (source_object));
primary = g_strdup_printf (_("Unable to eject %s"), name);
g_free (name);
@@ -2154,6 +2241,8 @@ drive_eject_cb (GObject *source_object,
}
g_error_free (error);
}
+
+ free_eject_op_data (data);
}
static void
@@ -2161,17 +2250,16 @@ volume_eject_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
- NautilusWindow *window;
+ EjectOpData *data = user_data;
GError *error;
char *primary;
char *name;
- window = user_data;
- g_object_unref (window);
-
error = NULL;
if (!g_volume_eject_with_operation_finish (G_VOLUME (source_object), res, &error)) {
if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ eject_notification_pop_down (data);
+
name = g_volume_get_name (G_VOLUME (source_object));
primary = g_strdup_printf (_("Unable to eject %s"), name);
g_free (name);
@@ -2182,6 +2270,8 @@ volume_eject_cb (GObject *source_object,
}
g_error_free (error);
}
+
+ free_eject_op_data (data);
}
static void
@@ -2189,17 +2279,16 @@ mount_eject_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
- NautilusWindow *window;
+ EjectOpData *data = user_data;
GError *error;
char *primary;
char *name;
- window = user_data;
- g_object_unref (window);
-
error = NULL;
if (!g_mount_eject_with_operation_finish (G_MOUNT (source_object), res, &error)) {
if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ eject_notification_pop_down (data);
+
name = g_mount_get_name (G_MOUNT (source_object));
primary = g_strdup_printf (_("Unable to eject %s"), name);
g_free (name);
@@ -2210,6 +2299,51 @@ mount_eject_cb (GObject *source_object,
}
g_error_free (error);
}
+
+ free_eject_op_data (data);
+}
+
+static gboolean
+eject_timeout (gpointer user_data)
+{
+ EjectOpData *data = user_data;
+
+ data->timeout_id = 0;
+ eject_notification_pop_up (data);
+
+ return FALSE;
+}
+
+static gboolean
+eject_notification_should_display (GMount *mount,
+ GVolume *volume,
+ GDrive *drive)
+{
+ gchar *device_id = NULL;
+ gboolean retval = TRUE;
+
+ if (mount != NULL) {
+ volume = g_mount_get_volume (mount);
+ } else if (volume != NULL) {
+ volume = g_object_ref (volume);
+ }
+
+ if (volume != NULL) {
+ device_id = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
+ } else if (drive != NULL) {
+ device_id = g_drive_get_identifier (drive, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
+ }
+
+ if (device_id != NULL) {
+ retval = !g_str_has_prefix (device_id, "/dev/sr");
+ g_free (device_id);
+ }
+
+ if (volume != NULL) {
+ g_object_unref (volume);
+ }
+
+ return retval;
}
static void
@@ -2218,20 +2352,36 @@ do_eject (GMount *mount,
GDrive *drive,
NautilusPlacesSidebar *sidebar)
{
- GMountOperation *mount_op;
+ EjectOpData *data;
+
+ if (mount == NULL && drive == NULL && volume == NULL) {
+ return;
+ }
+
+ data = g_slice_new0 (EjectOpData);
+ data->window = g_object_ref (sidebar->window);
+ data->mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
+ data->should_display = eject_notification_should_display (mount, volume, drive);
- mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
if (mount != NULL) {
- g_mount_eject_with_operation (mount, 0, mount_op, NULL, mount_eject_cb,
- g_object_ref (sidebar->window));
+ data->device_name = g_mount_get_name (mount);
+ g_mount_eject_with_operation (mount, 0, data->mount_op, NULL, mount_eject_cb, data);
} else if (volume != NULL) {
- g_volume_eject_with_operation (volume, 0, mount_op, NULL, volume_eject_cb,
- g_object_ref (sidebar->window));
+ data->device_name = g_volume_get_name (volume);
+ g_volume_eject_with_operation (volume, 0, data->mount_op, NULL, volume_eject_cb, data);
} else if (drive != NULL) {
- g_drive_eject_with_operation (drive, 0, mount_op, NULL, drive_eject_cb,
- g_object_ref (sidebar->window));
- }
- g_object_unref (mount_op);
+ data->device_name = g_drive_get_name (drive);
+ g_drive_eject_with_operation (drive, 0, data->mount_op, NULL, drive_eject_cb, data);
+ }
+
+ /* Display a notification of ongoing operation after a timeout */
+ data->timeout_id = g_timeout_add_seconds (1, eject_timeout, data);
+ g_signal_connect_swapped (data->mount_op, "show-processes",
+ G_CALLBACK (eject_notification_pop_down), data);
+ g_signal_connect_swapped (data->mount_op, "aborted",
+ G_CALLBACK (eject_notification_pop_down), data);
+ g_signal_connect (data->mount_op, "reply",
+ G_CALLBACK (eject_mount_op_reply), data);
}
static void
--
1.7.10.2