From 3a4e31b5ab5d45df8c44b0e8d2f59dfabfe62981 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Wed, 28 Jan 2009 17:11:46 +0100 Subject: Progress bar --- TODO | 5 +- src/nautilus-gdu-window.c | 176 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 164 insertions(+), 17 deletions(-) diff --git a/TODO b/TODO index aa1bf9f..8270893 100644 --- a/TODO +++ b/TODO @@ -2,10 +2,11 @@ code. Short-term: - refresh after operation succesfully finished, make Revert button work as expected (need to retrieve GduPresentable again) - - progress dialogs - PolicyKit integration + - Stop button (once PolicyKit integration is done) - simple standalone mode - do we need Bootable flag for something? + - make a Fedora package - handle LUKS encrypted volumes @@ -16,9 +17,11 @@ Short-term: - what to do if device is blank (zeroed, no MBR)? - handle read only device - gdu_device_is_read_only() - stay consistent with volume labels in Nautilus and gdu (requires gvfs-devicekit port) +- localization (transifex? -- ask hughsie) Ideas: - allow NTFS formatting and popup a PackageKit window when ntfs-3g is not available (shamelessly stolen from gnome-format discussion) - make standalone executable with a device/volume combo box to format - maybe add a button to unmount the volume so user can close all applications properly? + - mount volume back if we did unmount before formatting? diff --git a/src/nautilus-gdu-window.c b/src/nautilus-gdu-window.c index b12c54e..660ba80 100644 --- a/src/nautilus-gdu-window.c +++ b/src/nautilus-gdu-window.c @@ -56,6 +56,10 @@ typedef struct { GtkWidget *part_flag_required_check_button; GtkWidget *encrypted_check_button; GtkWidget *take_ownership_of_fs_check_button; + GtkWidget *progress_bar; + GtkWidget *progress_bar_box; + GtkWidget *controls_box; + GtkWidget *partition_label; GduPresentable *presentable; GduPool *pool; @@ -71,6 +75,9 @@ typedef struct { GduDevice *device; gboolean take_ownership; char *secure_erase; + + gulong job_handler_id; + guint job_progress_pulse_timer_id; } FormatProcessData; @@ -153,6 +160,106 @@ update_ui_mounted (FormatDialogPrivate *priv) g_object_unref (device); } +static gboolean +job_progress_pulse_timeout_handler (gpointer user_data) +{ + FormatProcessData *data = user_data; + + g_return_val_if_fail (data != NULL, TRUE); + + gtk_progress_bar_pulse (GTK_PROGRESS_BAR (data->priv->progress_bar)); + return TRUE; +} + +static void +presentable_job_changed (GduPresentable *presentable, gpointer user_data) +{ + FormatProcessData *data = user_data; + char *s; + char *job_description; + char *task_description; + double percentage; + + g_return_if_fail (data != NULL); + + if (data->device != NULL && gdu_device_job_in_progress (data->device)) { + job_description = gdu_get_job_description (gdu_device_job_get_id (data->device)); + task_description = gdu_get_task_description (gdu_device_job_get_cur_task_id (data->device)); + + s = g_strdup_printf (_("%s (task %d of %d)"), + (task_description && strlen (task_description) > 0) ? task_description : job_description, + gdu_device_job_get_cur_task (data->device) + 1, + gdu_device_job_get_num_tasks (data->device)); + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (data->priv->progress_bar), s); + g_free (s); + + percentage = gdu_device_job_get_cur_task_percentage (data->device); + if (percentage < 0) { + gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (data->priv->progress_bar), 2.0 / 50); + gtk_progress_bar_pulse (GTK_PROGRESS_BAR (data->priv->progress_bar)); + if (data->job_progress_pulse_timer_id == 0) { + data->job_progress_pulse_timer_id = g_timeout_add ( + 1000 / 50, + job_progress_pulse_timeout_handler, + data); + } + } else { + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (data->priv->progress_bar), + percentage / 100.0); + if (data->job_progress_pulse_timer_id > 0) { + g_source_remove (data->job_progress_pulse_timer_id); + data->job_progress_pulse_timer_id = 0; + } + } + + g_free (job_description); + g_free (task_description); + + } else { + if (data->job_progress_pulse_timer_id > 0) { + g_source_remove (data->job_progress_pulse_timer_id); + data->job_progress_pulse_timer_id = 0; + } + } +} + +static void +update_ui_progress (FormatDialogPrivate *priv, + FormatProcessData *data, + gboolean working) +{ + g_return_if_fail (priv != NULL); + + g_print ("update_ui_progress\n"); + + if (working) { + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progress_bar), NULL); + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progress_bar), 0.0); + gtk_widget_show_all (priv->progress_bar_box); + if (data) { + data->job_handler_id = g_signal_connect (priv->presentable, "job-changed", G_CALLBACK (presentable_job_changed), data); + } + } + else + { + if (data) { + if (data->job_handler_id) + g_signal_handler_disconnect (priv->presentable, data->job_handler_id); + if (data->job_progress_pulse_timer_id > 0) { + g_source_remove (data->job_progress_pulse_timer_id); + data->job_progress_pulse_timer_id = 0; + } + } + gtk_widget_hide_all (priv->progress_bar_box); + } + gtk_widget_set_sensitive (priv->controls_box, ! working); + gtk_widget_set_sensitive (priv->partition_label, ! working); + gtk_dialog_set_response_sensitive (priv->dialog, GTK_RESPONSE_OK, ! working); + gtk_dialog_set_response_sensitive (priv->dialog, GTK_RESPONSE_REJECT, ! working); +// gtk_dialog_set_response_sensitive (priv->dialog, GTK_RESPONSE_CLOSE, ! working); +} + + /* most of the code here was stolen from palimpsest */ static void update_ui (FormatDialogPrivate *priv) @@ -530,6 +637,7 @@ static void free_format_action_data (FormatProcessData *data) { if (data) { + update_ui_progress (data->priv, data, FALSE); if (data->device != NULL) g_object_unref (data->device); if (data->encrypt_passphrase != NULL) @@ -572,6 +680,7 @@ format_action_completed (GduDevice *device, free_format_action_data (data); } +static gboolean unmount_show_busy (gpointer user_data); static void unmount_action_completed (GduDevice *device, @@ -579,31 +688,29 @@ unmount_action_completed (GduDevice *device, gpointer user_data) { FormatProcessData *data = user_data; - gboolean ret; g_return_if_fail (data != NULL); g_print ("unmount_action_completed\n"); update_ui_mounted (data->priv); - if (g_error_matches (error, GDU_ERROR, GDU_ERROR_BUSY)) { - g_error_free (error); - ret = gdu_util_dialog_show_filesystem_busy (GTK_WIDGET (data->priv->dialog), data->priv->presentable); - if (ret) { - /* try unmounting again */ - gdu_device_op_filesystem_unmount (data->device, unmount_action_completed, data); - } - return; - } - if (error != NULL) { + if (g_error_matches (error, GDU_ERROR, GDU_ERROR_BUSY)) { + /* show dialog in idle */ + g_idle_add (unmount_show_busy, data); + } + else + { + free_format_action_data (data); nautilus_gdu_show_error (GTK_WIDGET (data->priv->dialog), data->priv->presentable, error, - _("Error creating partition")); - g_error_free (error); - free_format_action_data (data); - } else { + _("Error unmounting device")); + } + g_error_free (error); + } + else + { /* TODO: maybe perform a refresh? */ g_print (" formatting...\n"); gdu_device_op_filesystem_create (data->device, @@ -617,6 +724,24 @@ unmount_action_completed (GduDevice *device, } } +static gboolean +unmount_show_busy (gpointer user_data) +{ + FormatProcessData *data = user_data; + + if (gdu_util_dialog_show_filesystem_busy (GTK_WIDGET (data->priv->dialog), data->priv->presentable)) { + /* user managed to kill all applications; try again */ + gdu_device_op_filesystem_unmount (data->device, unmount_action_completed, data); + } + else { + /* cancel the whole operation */ + free_format_action_data (data); + } + + return FALSE; +} + + /* taken from palimpsest/gdu-section-unrecognized.c */ static void do_format (FormatDialogPrivate *priv) @@ -702,6 +827,9 @@ do_format (FormatDialogPrivate *priv) } } + + update_ui_progress (priv, data, TRUE); + data->secure_erase = gdu_util_delete_confirmation_dialog (GTK_WIDGET (priv->dialog), "", primary, @@ -723,6 +851,8 @@ do_format (FormatDialogPrivate *priv) } } + + /* unmount the device before formatting */ if (gdu_device_is_mounted (data->device)) { gdu_device_op_filesystem_unmount (data->device, unmount_action_completed, data); @@ -803,7 +933,6 @@ nautilus_gdu_spawn_dialog (GduPresentable *presentable) gtk_dialog_add_buttons (dialog, _("_Format"), GTK_RESPONSE_OK, _("_Revert"), GTK_RESPONSE_REJECT, -// GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); priv->close_button = gtk_dialog_add_button (dialog, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE); gtk_dialog_set_default_response (dialog, GTK_RESPONSE_CLOSE); @@ -824,6 +953,7 @@ nautilus_gdu_spawn_dialog (GduPresentable *presentable) GtkWidget *entry; GtkWidget *combo_box; GtkWidget *check_button; + GtkWidget *progress_bar; int row; hbox = gtk_hbox_new (FALSE, 10); @@ -889,11 +1019,14 @@ nautilus_gdu_spawn_dialog (GduPresentable *presentable) gtk_label_set_markup (GTK_LABEL (label), _("Partition")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (vbox3), label, FALSE, FALSE, 0); + priv->partition_label = label; + vbox2 = gtk_vbox_new (FALSE, 5); align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 24, 0); gtk_container_add (GTK_CONTAINER (align), vbox2); gtk_box_pack_start (GTK_BOX (vbox3), align, FALSE, TRUE, 0); + priv->controls_box = vbox2; /* explanatory text */ label = gtk_label_new (NULL); @@ -983,6 +1116,16 @@ nautilus_gdu_spawn_dialog (GduPresentable *presentable) priv->encrypted_check_button = check_button; row++; + /* progress bar */ + align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); + gtk_alignment_set_padding (GTK_ALIGNMENT (align), 15, 0, 20, 25); + priv->progress_bar_box = align; + + progress_bar = gtk_progress_bar_new (); + priv->progress_bar = progress_bar; + gtk_container_add (GTK_CONTAINER (align), progress_bar); + gtk_box_pack_start (GTK_BOX (vbox3), align, TRUE, TRUE, 0); + // gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, FALSE); @@ -996,4 +1139,5 @@ nautilus_gdu_spawn_dialog (GduPresentable *presentable) gtk_widget_grab_focus (priv->close_button); update_ui (priv); + update_ui_progress (priv, NULL, FALSE); } -- cgit