summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gdu-device.c145
-rw-r--r--src/gdu-device.h25
-rw-r--r--src/gdu-page-drive.c351
-rw-r--r--src/gdu-shell.c9
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) {