diff options
| author | David Zeuthen <davidz@redhat.com> | 2008-03-30 02:45:39 -0400 |
|---|---|---|
| committer | David Zeuthen <davidz@redhat.com> | 2008-03-30 02:45:39 -0400 |
| commit | de31bdd17325ec77aaa34b6f0bb237dda6d0bbef (patch) | |
| tree | 532d2d4d26a4cc3299da7f19808b32c8397fb3ec /src | |
| parent | b59a540ade48afda4f001235a2e16a5ee9914b21 (diff) | |
add S.M.A.R.T. monitoring and selftest support
http://people.freedesktop.org/~david/gdu-smart-and-failing.png
http://people.freedesktop.org/~david/gdu-smart-and-healthy.png
Diffstat (limited to 'src')
| -rw-r--r-- | src/gdu-device.c | 145 | ||||
| -rw-r--r-- | src/gdu-device.h | 25 | ||||
| -rw-r--r-- | src/gdu-page-drive.c | 351 | ||||
| -rw-r--r-- | src/gdu-shell.c | 9 |
4 files changed, 524 insertions, 6 deletions
diff --git a/src/gdu-device.c b/src/gdu-device.c index 05b98de..2b17d56 100644 --- a/src/gdu-device.c +++ b/src/gdu-device.c @@ -23,6 +23,7 @@ #include <string.h> #include <glib/gi18n.h> #include <dbus/dbus-glib.h> +#include <time.h> #include "gdu-pool.h" #include "gdu-device.h" @@ -314,6 +315,12 @@ struct _GduDevicePrivate char *job_last_error_message; DeviceProperties *props; + + time_t smart_data_cache_timestamp; + gboolean smart_data_cache_passed; + int smart_data_cache_power_on_hours; + int smart_data_cache_temperature; + GError *smart_data_cache_error; }; enum { @@ -347,6 +354,9 @@ gdu_device_finalize (GduDevice *device) device_properties_free (device->priv->props); g_free (device->priv->job_last_error_message); + if (device->priv->smart_data_cache_error != NULL) + g_error_free (device->priv->smart_data_cache_error); + if (G_OBJECT_CLASS (parent_class)->finalize) (* G_OBJECT_CLASS (parent_class)->finalize) (G_OBJECT (device)); } @@ -458,7 +468,7 @@ gdu_device_job_changed (GduDevice *device, const char *job_cur_task_id, double job_cur_task_percentage) { - g_print ("%s: %s\n", __FUNCTION__, device->priv->props->device_file); + g_print ("%s: %s: %s\n", __FUNCTION__, device->priv->props->device_file, job_id); device->priv->props->job_in_progress = job_in_progress; g_free (device->priv->props->job_id); @@ -1271,7 +1281,140 @@ gdu_device_op_change_filesystem_label (GduDevice *device, const char *new_label) op_change_fs_label_cb, g_object_ref (device)); } +/* -------------------------------------------------------------------------------- */ + +typedef struct { + GduDevice *device; + + GduDeviceRetrieveSmartDataCompletedFunc callback; + gpointer user_data; +} RetrieveSmartDataData; + +static void +op_retrieve_smart_data_cb (DBusGProxy *proxy, + gboolean passed, int power_on_hours, int temperature, + GError *error, gpointer user_data) +{ + RetrieveSmartDataData *data = user_data; + + /* update cache */ + data->device->priv->smart_data_cache_timestamp = time (NULL); + data->device->priv->smart_data_cache_passed = passed; + data->device->priv->smart_data_cache_power_on_hours = power_on_hours; + data->device->priv->smart_data_cache_temperature = temperature; + if (data->device->priv->smart_data_cache_error != NULL) + g_error_free (data->device->priv->smart_data_cache_error); + data->device->priv->smart_data_cache_error = error != NULL ? g_error_copy (error) : NULL; + + if (error != NULL) { + /* g_warning ("op_retrieve_smart_data_cb failed: %s", error->message); */ + data->callback (data->device, FALSE, 0, 0, error, data->user_data); + } else { + data->callback (data->device, passed, power_on_hours, temperature, NULL, data->user_data); + } + g_object_unref (data->device); + g_free (data); +} + +void +gdu_device_retrieve_smart_data (GduDevice *device, + GduDeviceRetrieveSmartDataCompletedFunc callback, + gpointer user_data) +{ + RetrieveSmartDataData *data; + + data = g_new0 (RetrieveSmartDataData, 1); + data->device = g_object_ref (device); + data->callback = callback; + data->user_data = user_data; + + org_freedesktop_DeviceKit_Disks_Device_retrieve_smart_data_async (device->priv->proxy, + op_retrieve_smart_data_cb, + data); +} + +gboolean +gdu_device_smart_data_is_cached (GduDevice *device, int *age_in_seconds) +{ + time_t now; + gboolean ret; + + ret = FALSE; + + if (device->priv->smart_data_cache_timestamp == 0) + goto out; + + now = time (NULL); + if (age_in_seconds != NULL) + *age_in_seconds = now - device->priv->smart_data_cache_timestamp; + + ret = TRUE; + +out: + return ret; +} + +void +gdu_device_smart_data_purge_cache (GduDevice *device) +{ + device->priv->smart_data_cache_timestamp = 0; + if (device->priv->smart_data_cache_error != NULL) + g_error_free (device->priv->smart_data_cache_error); + device->priv->smart_data_cache_error = NULL; +} + +gboolean +gdu_device_retrieve_smart_data_from_cache (GduDevice *device, + GduDeviceRetrieveSmartDataCompletedFunc callback, + gpointer user_data) +{ + gboolean ret; + + ret = FALSE; + + if (device->priv->smart_data_cache_timestamp == 0) + goto out; + + callback (device, + device->priv->smart_data_cache_passed, + device->priv->smart_data_cache_power_on_hours, + device->priv->smart_data_cache_temperature, + device->priv->smart_data_cache_error != NULL ? + g_error_copy (device->priv->smart_data_cache_error) : NULL, + user_data); + + ret = TRUE; + +out: + return ret; +} + +/* -------------------------------------------------------------------------------- */ + +static void +op_run_smart_selftest_cb (DBusGProxy *proxy, GError *error, gpointer user_data) +{ + GduDevice *device = GDU_DEVICE (user_data); + if (error != NULL) { + g_warning ("op_run_smart_selftest_cb failed: %s", error->message); + gdu_device_job_set_failed (device, error); + g_error_free (error); + } + g_object_unref (device); +} + +void +gdu_device_op_run_smart_selftest (GduDevice *device, + const char *test, + gboolean captive) +{ + org_freedesktop_DeviceKit_Disks_Device_run_smart_selftest_async (device->priv->proxy, + test, + captive, + op_run_smart_selftest_cb, + g_object_ref (device)); +} /* -------------------------------------------------------------------------------- */ diff --git a/src/gdu-device.h b/src/gdu-device.h index aa48291..95455b3 100644 --- a/src/gdu-device.h +++ b/src/gdu-device.h @@ -150,6 +150,10 @@ void gdu_device_op_lock_encrypted (GduDevice *device); void gdu_device_op_change_filesystem_label (GduDevice *device, const char *new_label); +void gdu_device_op_run_smart_selftest (GduDevice *device, + const char *test, + gboolean captive); + /* ---------------------------------------------------------------------------------------------------- */ /* ops where feedback is essential */ /* ---------------------------------------------------------------------------------------------------- */ @@ -213,6 +217,27 @@ void gdu_device_op_change_secret_for_encrypted (GduDevice *device, /* ---------------------------------------------------------------------------------------------------- */ +typedef void (*GduDeviceRetrieveSmartDataCompletedFunc) (GduDevice *device, + gboolean passed, + int power_on_hours, + int temperature, + GError *error, + gpointer user_data); + +void gdu_device_retrieve_smart_data (GduDevice *device, + GduDeviceRetrieveSmartDataCompletedFunc callback, + gpointer user_data); + +gboolean gdu_device_smart_data_is_cached (GduDevice *device, int *age_in_seconds); + +void gdu_device_smart_data_purge_cache (GduDevice *device); + +gboolean gdu_device_retrieve_smart_data_from_cache (GduDevice *device, + GduDeviceRetrieveSmartDataCompletedFunc callback, + gpointer user_data); + +/* ---------------------------------------------------------------------------------------------------- */ + /* typically used for non-fire-and-forget ops */ void gdu_device_job_set_failed (GduDevice *device, GError *error); diff --git a/src/gdu-page-drive.c b/src/gdu-page-drive.c index c0f6445..5e63710 100644 --- a/src/gdu-page-drive.c +++ b/src/gdu-page-drive.c @@ -39,6 +39,14 @@ struct _GduPageDrivePrivate GtkWidget *notebook; + GtkWidget *health_status_image; + GtkWidget *health_status_label; + GtkWidget *health_status_explanation_label; + GtkWidget *health_power_on_hours_label; + GtkWidget *health_temperature_label; + GtkWidget *health_refresh_button; + GtkWidget *health_selftest_button; + GtkWidget *create_part_table_vbox; GtkWidget *create_part_table_type_combo_box; @@ -59,6 +67,9 @@ enum { PROP_SHELL, }; +static void health_refresh_button_clicked (GtkWidget *button, gpointer user_data); +static void health_selftest_button_clicked (GtkWidget *button, gpointer user_data); + static void gdu_page_drive_finalize (GduPageDrive *page) { @@ -208,6 +219,7 @@ static void gdu_page_drive_init (GduPageDrive *page) { int row; + GtkWidget *hbox; GtkWidget *vbox2; GtkWidget *vbox3; GtkWidget *label; @@ -216,6 +228,7 @@ gdu_page_drive_init (GduPageDrive *page) GtkWidget *combo_box; GtkWidget *button; GtkWidget *button_box; + GtkWidget *image; page->priv = g_new0 (GduPageDrivePrivate, 1); @@ -241,14 +254,121 @@ gdu_page_drive_init (GduPageDrive *page) gtk_notebook_set_show_tabs (GTK_NOTEBOOK (page->priv->notebook), FALSE); gtk_notebook_set_show_border (GTK_NOTEBOOK (page->priv->notebook), FALSE); - /* ------------ */ - /* Format Drive */ - /* ------------ */ - vbox3 = gtk_vbox_new (FALSE, 5); gtk_notebook_append_page (GTK_NOTEBOOK (page->priv->notebook), vbox3, NULL); page->priv->create_part_table_vbox = vbox3; + /* ------ */ + /* Health */ + /* ------ */ + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), _("<b>Health</b>")); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (vbox3), label, FALSE, FALSE, 0); + 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); + + /* explanatory text */ + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), _("Some hard disks supports S.M.A.R.T., a monitoring system for " + "disks to detect and report on various indicators of " + "reliability, in the hope of anticipating failures.")); + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0); + + table = gtk_table_new (4, 2, FALSE); + gtk_box_pack_start (GTK_BOX (vbox2), table, FALSE, FALSE, 0); + + row = 0; + + /* power on hours */ + label = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), _("<b>Powered On:</b>")); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); + + label = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + page->priv->health_power_on_hours_label = label; + + gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row + 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); + + row++; + + /* temperature */ + label = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), _("<b>Temperature:</b>")); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); + + label = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + page->priv->health_temperature_label = label; + + gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row + 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); + + row++; + + /* assessment */ + label = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), _("<b>Assessment:</b>")); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); + + hbox = gtk_hbox_new (FALSE, 5); + image = gtk_image_new (); + gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0); + label = gtk_label_new (NULL); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0); + gtk_table_attach (GTK_TABLE (table), hbox, 1, 2, row, row + 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); + page->priv->health_status_image = image; + page->priv->health_status_label = label; + + row++; + + label = gtk_label_new (NULL); + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); + gtk_label_set_width_chars (GTK_LABEL (label), 40); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row + 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2); + page->priv->health_status_explanation_label = label; + + /* health buttons */ + button_box = gtk_hbutton_box_new (); + gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_START); + gtk_box_set_spacing (GTK_BOX (button_box), 6); + gtk_box_pack_start (GTK_BOX (vbox2), button_box, TRUE, TRUE, 0); + + button = gtk_button_new_with_mnemonic (_("Refre_sh")); + gtk_button_set_image (GTK_BUTTON (button), + gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_BUTTON)); + gtk_container_add (GTK_CONTAINER (button_box), button); + g_signal_connect (button, "clicked", G_CALLBACK (health_refresh_button_clicked), page); + page->priv->health_refresh_button = button; + + button = gtk_button_new_with_mnemonic (_("Se_lftest...")); + gtk_button_set_image (GTK_BUTTON (button), + gtk_image_new_from_stock (GTK_STOCK_EXECUTE, GTK_ICON_SIZE_BUTTON)); + gtk_container_add (GTK_CONTAINER (button_box), button); + g_signal_connect (button, "clicked", G_CALLBACK (health_selftest_button_clicked), page); + page->priv->health_selftest_button = button; + + /* ------------ */ + /* Format Drive */ + /* ------------ */ + label = gtk_label_new (NULL); gtk_label_set_markup (GTK_LABEL (label), _("<b>Format Media</b>")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); @@ -351,6 +471,219 @@ gdu_page_drive_new (GduShell *shell) return GDU_PAGE_DRIVE (g_object_new (GDU_TYPE_PAGE_DRIVE, "shell", shell, NULL)); } +static void +smart_data_set_pending (GduPageDrive *page) +{ + gtk_image_clear (GTK_IMAGE (page->priv->health_status_image)); + gtk_label_set_markup (GTK_LABEL (page->priv->health_status_label), _("<i>Retrieving...</i>")); + gtk_label_set_text (GTK_LABEL (page->priv->health_power_on_hours_label), _("-")); + gtk_label_set_text (GTK_LABEL (page->priv->health_temperature_label), _("-")); + + gtk_widget_set_sensitive (page->priv->health_refresh_button, FALSE); + gtk_widget_set_sensitive (page->priv->health_selftest_button, FALSE); + gtk_widget_hide (page->priv->health_status_image); + gtk_widget_hide (page->priv->health_status_explanation_label); +} + +static void +smart_data_set_not_supported (GduPageDrive *page) +{ + gtk_image_clear (GTK_IMAGE (page->priv->health_status_image)); + gtk_label_set_markup (GTK_LABEL (page->priv->health_status_label), _("<i>Not Supported</i>")); + gtk_label_set_text (GTK_LABEL (page->priv->health_power_on_hours_label), _("-")); + gtk_label_set_text (GTK_LABEL (page->priv->health_temperature_label), _("-")); + + gtk_widget_set_sensitive (page->priv->health_refresh_button, FALSE); + gtk_widget_set_sensitive (page->priv->health_selftest_button, FALSE); + gtk_widget_hide (page->priv->health_status_image); + gtk_widget_hide (page->priv->health_status_explanation_label); +} + +static void +smart_data_set (GduPageDrive *page, gboolean passed, int power_on_hours, int temperature) +{ + char *s; + + gtk_widget_set_sensitive (page->priv->health_refresh_button, TRUE); + gtk_widget_set_sensitive (page->priv->health_selftest_button, TRUE); + gtk_widget_show (page->priv->health_status_image); + + if (passed) { + gtk_image_set_from_stock (GTK_IMAGE (page->priv->health_status_image), + GTK_STOCK_YES, GTK_ICON_SIZE_MENU); + gtk_label_set_text (GTK_LABEL (page->priv->health_status_label), _("Passed")); + gtk_widget_hide (page->priv->health_status_explanation_label); + } else { + gtk_image_set_from_stock (GTK_IMAGE (page->priv->health_status_image), + GTK_STOCK_NO, GTK_ICON_SIZE_MENU); + gtk_label_set_markup (GTK_LABEL (page->priv->health_status_label), _("<span foreground='red'><b>FAILING</b></span>")); + gtk_label_set_markup (GTK_LABEL (page->priv->health_status_explanation_label), + _("<small><i><b>" + "Drive failure expected in less than 24 hours. " + "Save all data immediately." + "</b></i></small>")); + } + + if (power_on_hours < 24) + s = g_strdup_printf (_("%d hours"), power_on_hours); + else { + int d; + int h; + + d = power_on_hours / 24; + h = power_on_hours - d * 24; + + if (d == 0) + s = g_strdup_printf (_("%d days"), d); + else if (d == 1) + s = g_strdup_printf (_("%d days, 1 hour"), d); + else + s = g_strdup_printf (_("%d days, %d hours"), d, h); + } + gtk_label_set_text (GTK_LABEL (page->priv->health_power_on_hours_label), s); + g_free (s); + + s = g_strdup_printf (_("%d° Celcius"), temperature); + gtk_label_set_text (GTK_LABEL (page->priv->health_temperature_label), s); + g_free (s); +} + +static void +retrieve_smart_data_cb (GduDevice *device, + gboolean passed, + int power_on_hours, + int temperature, + GError *error, + gpointer user_data) +{ + GduPageDrive *page = GDU_PAGE_DRIVE (user_data); + + if (error != NULL) { + smart_data_set_not_supported (page); + g_error_free (error); + goto out; + } + + smart_data_set (page, passed, power_on_hours, temperature); + +out: + ; +} + +static void +health_refresh_button_clicked (GtkWidget *button, gpointer user_data) +{ + GduPageDrive *page = GDU_PAGE_DRIVE (user_data); + GduDevice *device; + + device = gdu_presentable_get_device (gdu_shell_get_selected_presentable (page->priv->shell)); + if (device == NULL) { + g_warning ("%s: device is not supposed to be NULL", __FUNCTION__); + goto out; + } + + smart_data_set_pending (page); + gdu_device_retrieve_smart_data (device, retrieve_smart_data_cb, page); + +out: + if (device != NULL) + g_object_unref (device); +} + +static void +health_selftest_button_clicked (GtkWidget *button, gpointer user_data) +{ + int response; + GtkWidget *dialog; + GduPageDrive *page = GDU_PAGE_DRIVE (user_data); + GduDevice *device; + GtkWidget *hbox; + GtkWidget *image; + GtkWidget *main_vbox; + GtkWidget *label; + GtkWidget *radio0; + GtkWidget *radio1; + const char *test; + + test = NULL; + + device = gdu_presentable_get_device (gdu_shell_get_selected_presentable (page->priv->shell)); + if (device == NULL) { + g_warning ("%s: device is not supposed to be NULL", __FUNCTION__); + goto out; + } + + + dialog = gtk_dialog_new_with_buttons (_("S.M.A.R.T. Selftest"), + GTK_WINDOW (gdu_shell_get_toplevel (page->priv->shell)), + GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT|GTK_DIALOG_NO_SEPARATOR, + NULL); + + gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); + gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2); + gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 5); + gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6); + gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); + + hbox = gtk_hbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, TRUE, TRUE, 0); + + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); + gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0); + gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); + + main_vbox = gtk_vbox_new (FALSE, 10); + gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0); + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), _("<big><b>Select what S.M.A.R.T. test to run on the drive.</b></big>")); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); + gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (label), FALSE, FALSE, 0); + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), _("The tests may take a very long time to complete depending " + "on the speed and size of the disk. You can continue using " + "your system while the test is running.")); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); + gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (label), FALSE, FALSE, 0); + + radio0 = gtk_radio_button_new_with_mnemonic_from_widget (NULL, + _("_Short (usually less than ten minutes)")); + radio1 = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (radio0), + _("_Long (usually tens of minutes)")); + + gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (radio0), FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (radio1), FALSE, FALSE, 0); + + gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); + gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Initiate Selftest"), 0); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), 0); + + gtk_widget_show_all (dialog); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio0))) { + test = "short"; + } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio1))) { + test = "long"; + } + + gtk_widget_destroy (dialog); + if (response != 0) + goto out; + + gdu_device_smart_data_purge_cache (device); + + /* TODO: option for captive */ + gdu_device_op_run_smart_selftest (device, test, FALSE); +out: + if (device != NULL) + g_object_unref (device); +} + static gboolean gdu_page_drive_update (GduPage *_page, GduPresentable *presentable, gboolean reset_page) { @@ -372,6 +705,16 @@ gdu_page_drive_update (GduPage *_page, GduPresentable *presentable, gboolean res gtk_widget_set_sensitive (page->priv->create_part_table_vbox, !gdu_device_is_read_only (device)); if (reset_page) { + if (page_to_show == 0) { + int age; + if (gdu_device_smart_data_is_cached (device, &age) && age < 5 * 60) { + gdu_device_retrieve_smart_data_from_cache (device, retrieve_smart_data_cb, page); + } else { + smart_data_set_pending (page); + gdu_device_retrieve_smart_data (device, retrieve_smart_data_cb, page); + } + } + gtk_combo_box_set_active (GTK_COMBO_BOX (page->priv->create_part_table_type_combo_box), 0); } diff --git a/src/gdu-shell.c b/src/gdu-shell.c index 6f70a4d..caeda3b 100644 --- a/src/gdu-shell.c +++ b/src/gdu-shell.c @@ -406,7 +406,14 @@ gdu_shell_update (GduShell *shell) device = gdu_presentable_get_device (shell->priv->presentable_now_showing); if (device != NULL) { if (gdu_device_job_in_progress (device)) { - job_in_progress = TRUE; + const char *job_id; + + job_id = gdu_device_job_get_id (device); + + /* Ignore this jobs as we trigger it when switching pages */ + if (strcmp (job_id, "RetrieveSmartData") != 0) { + job_in_progress = TRUE; + } } if (gdu_device_job_get_last_error_message (device) != NULL) { |
