[gvfs] udisks2: implement show-unmount-progress
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs] udisks2: implement show-unmount-progress
- Date: Thu, 12 Jul 2012 00:01:01 +0000 (UTC)
commit 174f3044f0e741b9c376efe98d41f5f46592b957
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Mon Jul 9 21:01:36 2012 -0400
udisks2: implement show-unmount-progress
https://bugzilla.gnome.org/show_bug.cgi?id=676111
monitor/udisks2/gvfsudisks2drive.c | 22 ++++-
monitor/udisks2/gvfsudisks2mount.c | 9 ++
monitor/udisks2/gvfsudisks2utils.c | 228 ++++++++++++++++++++++++++++++++++++
monitor/udisks2/gvfsudisks2utils.h | 5 +
4 files changed, 263 insertions(+), 1 deletions(-)
---
diff --git a/monitor/udisks2/gvfsudisks2drive.c b/monitor/udisks2/gvfsudisks2drive.c
index 83173a2..2fca96c 100644
--- a/monitor/udisks2/gvfsudisks2drive.c
+++ b/monitor/udisks2/gvfsudisks2drive.c
@@ -505,6 +505,9 @@ unmount_mounts_cb (GObject *source_object,
_("Failed to eject medium; one or more volumes on the medium are busy."));
}
+ if (data->mount_operation != NULL)
+ gvfs_udisks2_unmount_notify_stop (data->mount_operation);
+
/* unmount failed; need to fail the whole eject operation */
simple = g_simple_async_result_new_from_error (G_OBJECT (data->drive),
data->callback,
@@ -566,6 +569,7 @@ typedef struct
GSimpleAsyncResult *simple;
GVfsUDisks2Drive *drive;
+ GMountOperation *mount_operation;
} EjectData;
static void
@@ -573,6 +577,8 @@ eject_data_free (EjectData *data)
{
g_object_unref (data->simple);
g_clear_object (&data->drive);
+ g_clear_object (&data->mount_operation);
+
g_free (data);
}
@@ -591,6 +597,15 @@ eject_cb (GObject *source_object,
g_simple_async_result_take_error (data->simple, error);
}
+ if (data->mount_operation != NULL)
+ {
+ /* If we fail send an ::aborted signal to make any notification go away */
+ if (error != NULL)
+ g_signal_emit_by_name (data->mount_operation, "aborted");
+
+ gvfs_udisks2_unmount_notify_stop (data->mount_operation);
+ }
+
g_simple_async_result_complete (data->simple);
eject_data_free (data);
}
@@ -613,6 +628,8 @@ gvfs_udisks2_drive_eject_on_all_unmounted (GDrive *_drive,
user_data,
gvfs_udisks2_drive_eject_on_all_unmounted);
data->drive = g_object_ref (drive);
+ if (mount_operation != NULL)
+ data->mount_operation = g_object_ref (mount_operation);
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
if (mount_operation == NULL)
@@ -643,7 +660,10 @@ gvfs_udisks2_drive_eject_with_operation (GDrive *_drive,
* be "Unmount Anyway" or "Eject Anyway"
*/
if (mount_operation != NULL)
- g_object_set_data (G_OBJECT (mount_operation), "x-udisks2-is-eject", GINT_TO_POINTER (1));
+ {
+ g_object_set_data (G_OBJECT (mount_operation), "x-udisks2-is-eject", GINT_TO_POINTER (1));
+ gvfs_udisks2_unmount_notify_start (mount_operation, NULL, _drive, FALSE);
+ }
/* first we need to go through all the volumes and unmount their assoicated mounts (if any) */
unmount_mounts (drive,
diff --git a/monitor/udisks2/gvfsudisks2mount.c b/monitor/udisks2/gvfsudisks2mount.c
index 5ce9769..50df9ab 100644
--- a/monitor/udisks2/gvfsudisks2mount.c
+++ b/monitor/udisks2/gvfsudisks2mount.c
@@ -573,6 +573,10 @@ static void
unmount_data_complete (UnmountData *data,
gboolean complete_idle)
{
+ if (data->mount_operation &&
+ !unmount_operation_is_eject (data->mount_operation))
+ gvfs_udisks2_unmount_notify_stop (data->mount_operation);
+
if (complete_idle)
g_simple_async_result_complete_in_idle (data->simple);
else
@@ -884,6 +888,11 @@ unmount_do (UnmountData *data,
{
GVariantBuilder builder;
+ if (data->mount_operation != NULL)
+ gvfs_udisks2_unmount_notify_start (data->mount_operation,
+ G_MOUNT (data->mount), NULL,
+ (data->filesystem == NULL));
+
/* Use the umount(8) command if there is no block device / filesystem */
if (data->filesystem == NULL)
{
diff --git a/monitor/udisks2/gvfsudisks2utils.c b/monitor/udisks2/gvfsudisks2utils.c
index 19c6e28..eee6bcc 100644
--- a/monitor/udisks2/gvfsudisks2utils.c
+++ b/monitor/udisks2/gvfsudisks2utils.c
@@ -587,3 +587,231 @@ gvfs_udisks2_utils_is_drive_on_our_seat (UDisksDrive *drive)
out:
return ret;
}
+
+/* unmount progress notification utilities */
+typedef struct {
+ GMount *mount;
+ GDrive *drive;
+
+ GMountOperation *op;
+ gboolean op_aborted;
+ gboolean generic_text;
+ gboolean show_processes_up;
+
+ guint unmount_timer_id;
+ gboolean unmount_fired;
+} UnmountNotifyData;
+
+static gboolean
+unmount_notify_should_show (UnmountNotifyData *data)
+{
+ GVolume *volume;
+ gchar *identifier = NULL;
+ gboolean retval = TRUE;
+
+ if (data->mount)
+ {
+ volume = g_mount_get_volume (data->mount);
+
+ if (volume)
+ {
+ identifier = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
+ g_object_unref (volume);
+ }
+ }
+ else if (data->drive)
+ {
+ identifier = g_drive_get_identifier (data->drive, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
+ }
+
+ if (identifier && g_str_has_prefix (identifier, "/dev/sr"))
+ retval = FALSE;
+
+ g_free (identifier);
+
+ return retval;
+}
+
+static gchar *
+unmount_notify_get_name (UnmountNotifyData *data)
+{
+ if (data->mount)
+ return g_mount_get_name (data->mount);
+ else
+ return g_drive_get_name (data->drive);
+}
+
+static gboolean
+unmount_notify_timer_cb (gpointer user_data)
+{
+ UnmountNotifyData *data = user_data;
+ gchar *message, *name;
+ const gchar *format;
+
+ data->unmount_timer_id = 0;
+
+ if (data->unmount_fired)
+ goto out;
+
+ /* TODO: it would be nice to include and update the time left and
+ * bytes left fields.
+ */
+ data->unmount_fired = TRUE;
+
+ name = unmount_notify_get_name (data);
+ format = data->generic_text ?
+ _("Unmounting %s\nPlease wait") :
+ _("Writing data to %s\nDon't unplug until finished");
+
+ message = g_strdup_printf (format, name);
+ g_signal_emit_by_name (data->op, "show-unmount-progress",
+ message, -1, -1);
+ g_free (message);
+ g_free (name);
+
+ out:
+ return FALSE;
+}
+
+static void
+unmount_notify_ensure_timer (UnmountNotifyData *data)
+{
+ if (data->unmount_timer_id > 0)
+ return;
+
+ if (!unmount_notify_should_show (data))
+ return;
+
+ data->unmount_timer_id =
+ g_timeout_add (1500, unmount_notify_timer_cb, data);
+}
+
+static void
+unmount_notify_stop_timer (UnmountNotifyData *data)
+{
+ if (data->unmount_timer_id > 0)
+ {
+ g_source_remove (data->unmount_timer_id);
+ data->unmount_timer_id = 0;
+ }
+}
+
+static void
+unmount_notify_op_show_processes (UnmountNotifyData *data)
+{
+ unmount_notify_stop_timer (data);
+ data->show_processes_up = TRUE;
+}
+
+static void
+unmount_notify_op_aborted (UnmountNotifyData *data)
+{
+ unmount_notify_stop_timer (data);
+ data->op_aborted = TRUE;
+}
+
+static void
+unmount_notify_op_reply (UnmountNotifyData *data,
+ GMountOperationResult result)
+{
+ gint choice;
+
+ choice = g_mount_operation_get_choice (data->op);
+
+ if ((result == G_MOUNT_OPERATION_HANDLED && data->show_processes_up && choice == 1) ||
+ result == G_MOUNT_OPERATION_ABORTED)
+ unmount_notify_op_aborted (data);
+ else if (result == G_MOUNT_OPERATION_HANDLED)
+ unmount_notify_ensure_timer (data);
+
+ data->show_processes_up = FALSE;
+}
+
+static void
+unmount_notify_data_free (gpointer user_data)
+{
+ UnmountNotifyData *data = user_data;
+
+ unmount_notify_stop_timer (data);
+
+ g_clear_object (&data->mount);
+ g_clear_object (&data->drive);
+
+ g_slice_free (UnmountNotifyData, data);
+}
+
+static UnmountNotifyData *
+unmount_notify_data_for_operation (GMountOperation *op,
+ GMount *mount,
+ GDrive *drive,
+ gboolean generic_text)
+{
+ UnmountNotifyData *data;
+
+ data = g_object_get_data (G_OBJECT (op), "x-udisks2-notify-data");
+ if (data != NULL)
+ return data;
+
+ data = g_slice_new0 (UnmountNotifyData);
+ data->op = op;
+ data->generic_text = generic_text;
+
+ if (mount)
+ data->mount = g_object_ref (mount);
+ if (drive)
+ data->drive = g_object_ref (drive);
+
+ g_object_set_data_full (G_OBJECT (data->op),
+ "x-udisks2-notify-data", data,
+ unmount_notify_data_free);
+
+ g_signal_connect_swapped (data->op, "aborted",
+ G_CALLBACK (unmount_notify_op_aborted), data);
+ g_signal_connect_swapped (data->op, "show-processes",
+ G_CALLBACK (unmount_notify_op_show_processes), data);
+ g_signal_connect_swapped (data->op, "reply",
+ G_CALLBACK (unmount_notify_op_reply), data);
+
+ return data;
+}
+
+void
+gvfs_udisks2_unmount_notify_start (GMountOperation *op,
+ GMount *mount,
+ GDrive *drive,
+ gboolean generic_text)
+{
+ UnmountNotifyData *data;
+
+ data = unmount_notify_data_for_operation (op, mount, drive, generic_text);
+ unmount_notify_ensure_timer (data);
+}
+
+void
+gvfs_udisks2_unmount_notify_stop (GMountOperation *op)
+{
+ gchar *message, *name;
+ const gchar *format;
+ UnmountNotifyData *data = g_object_get_data (G_OBJECT (op), "x-udisks2-notify-data");
+
+ if (data == NULL)
+ return;
+
+ unmount_notify_stop_timer (data);
+
+ if (data->op_aborted)
+ return;
+ if (!data->unmount_fired)
+ return;
+
+ name = unmount_notify_get_name (data);
+ format = data->generic_text ?
+ _("%s has been unmounted\n") : _("You can now unplug %s\n");
+
+ message = g_strdup_printf (format, name);
+ g_signal_emit_by_name (data->op, "show-unmount-progress",
+ message, 0, 0);
+
+ g_free (message);
+ g_free (name);
+}
diff --git a/monitor/udisks2/gvfsudisks2utils.h b/monitor/udisks2/gvfsudisks2utils.h
index 1965883..b067261 100644
--- a/monitor/udisks2/gvfsudisks2utils.h
+++ b/monitor/udisks2/gvfsudisks2utils.h
@@ -52,6 +52,11 @@ gboolean gvfs_udisks2_utils_spawn_finish (GAsyncResult *res,
gboolean gvfs_udisks2_utils_is_drive_on_our_seat (UDisksDrive *drive);
+void gvfs_udisks2_unmount_notify_start (GMountOperation *op,
+ GMount *mount,
+ GDrive *drive,
+ gboolean generic_text);
+void gvfs_udisks2_unmount_notify_stop (GMountOperation *op);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]