[gnome-disk-utility] Update "Create RAID Array" dialog
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-disk-utility] Update "Create RAID Array" dialog
- Date: Thu, 11 Oct 2012 17:15:24 +0000 (UTC)
commit c7534927bc414fafe262c0a6dcb221891ff7b002
Author: David Zeuthen <zeuthen gmail com>
Date: Thu Oct 11 13:14:55 2012 -0400
Update "Create RAID Array" dialog
Signed-off-by: David Zeuthen <zeuthen gmail com>
data/ui/create-raid-array-dialog.ui | 6 +-
src/disks/gducreateraidarraydialog.c | 233 +++++++++++++++++++++++++++++-----
src/disks/gdudevicetreemodel.c | 44 +++++++
src/disks/gdudevicetreemodel.h | 1 +
src/disks/gduwindow.c | 22 +++-
5 files changed, 265 insertions(+), 41 deletions(-)
---
diff --git a/data/ui/create-raid-array-dialog.ui b/data/ui/create-raid-array-dialog.ui
index 305245f..4c76eba 100644
--- a/data/ui/create-raid-array-dialog.ui
+++ b/data/ui/create-raid-array-dialog.ui
@@ -58,6 +58,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
+ <property name="spacing">12</property>
<child>
<object class="GtkBox" id="infobar-vbox">
<property name="visible">True</property>
@@ -74,7 +75,7 @@
</packing>
</child>
<child>
- <object class="GtkGrid" id="grid1">
+ <object class="GtkGrid" id="grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">10</property>
@@ -168,6 +169,7 @@
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="invisible_char">â</property>
+ <property name="activates_default">True</property>
</object>
<packing>
<property name="left_attach">1</property>
@@ -181,7 +183,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
- <property name="label" translatable="yes">RAID Array Size</property>
+ <property name="label" translatable="yes">Array Size</property>
<style>
<class name="dim-label"/>
</style>
diff --git a/src/disks/gducreateraidarraydialog.c b/src/disks/gducreateraidarraydialog.c
index c0e37c5..ba2f8b4 100644
--- a/src/disks/gducreateraidarraydialog.c
+++ b/src/disks/gducreateraidarraydialog.c
@@ -25,9 +25,11 @@ typedef struct
{
volatile gint ref_count;
- gboolean in_update;
+ gboolean disks_not_same_size;
- GList *objects;
+ GList *blocks;
+ guint64 disk_size;
+ guint num_disks;
UDisksClient *client;
GduWindow *window;
@@ -37,6 +39,7 @@ typedef struct
GtkWidget *infobar_vbox;
+ GtkWidget *grid;
GtkWidget *level_combobox;
GtkWidget *chunk_combobox;
GtkWidget *name_entry;
@@ -51,6 +54,7 @@ static const struct {
{G_STRUCT_OFFSET (DialogData, infobar_vbox), "infobar-vbox"},
+ {G_STRUCT_OFFSET (DialogData, grid), "grid"},
{G_STRUCT_OFFSET (DialogData, level_combobox), "level-combobox"},
{G_STRUCT_OFFSET (DialogData, chunk_combobox), "chunk-combobox"},
{G_STRUCT_OFFSET (DialogData, name_entry), "name-entry"},
@@ -95,7 +99,7 @@ dialog_data_unref (DialogData *data)
g_clear_object (&data->window);
g_clear_object (&data->builder);
- g_list_free_full (data->objects, g_object_unref);
+ g_list_free_full (data->blocks, g_object_unref);
g_free (data);
}
}
@@ -112,21 +116,73 @@ dialog_data_close (DialogData *data)
static void
update_dialog (DialogData *data)
{
- /* don't recurse */
- if (data->in_update)
+ gboolean create_sensitive = FALSE;
+ gboolean chunk_level_sensitive = TRUE;
+ const gchar *raid_level;
+ guint64 raid_size;
+ gchar *s;
+
+ if (data->disks_not_same_size)
goto out;
- data->in_update = TRUE;
- /* TODO */
- data->in_update = FALSE;
+ create_sensitive = TRUE;
+
+ raid_level = gtk_combo_box_get_active_id (GTK_COMBO_BOX (data->level_combobox));
+ if (g_strcmp0 (raid_level, "raid0") == 0)
+ {
+ raid_size = data->disk_size * data->num_disks;
+ }
+ else if (g_strcmp0 (raid_level, "raid1") == 0)
+ {
+ chunk_level_sensitive = FALSE; /* does not make sense on RAID-1 */
+ raid_size = data->disk_size;
+ }
+ else if (g_strcmp0 (raid_level, "raid4") == 0)
+ {
+ raid_size = data->disk_size * (data->num_disks - 1);
+ }
+ else if (g_strcmp0 (raid_level, "raid5") == 0)
+ {
+ raid_size = data->disk_size * (data->num_disks - 1);
+ }
+ else if (g_strcmp0 (raid_level, "raid6") == 0)
+ {
+ raid_size = data->disk_size * (data->num_disks - 2);
+ }
+ else if (g_strcmp0 (raid_level, "raid10") == 0)
+ {
+ /* Yes, MD RAID-10 makes sense with two drives - also see drivers/md/raid10.c
+ * function raid10_size() for the formula
+ *
+ * The constants below stems from the fact that the default for
+ * RAID-10 creation is "n2", e.g. two near copies.
+ */
+ gint num_far_copies = 1;
+ gint num_near_copies = 2;
+ raid_size = data->disk_size / num_far_copies;
+ raid_size *= data->num_disks;
+ raid_size /= num_near_copies;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+
+ s = udisks_client_get_size_for_display (data->client, raid_size, FALSE, FALSE);
+ gtk_label_set_text (GTK_LABEL (data->size_label), s);
+ g_free (s);
out:
- ;
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog),
+ GTK_RESPONSE_OK,
+ create_sensitive);
+ gtk_widget_set_sensitive (data->chunk_combobox, chunk_level_sensitive);
}
/* ---------------------------------------------------------------------------------------------------- */
-G_GNUC_UNUSED static void
+static void
on_property_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data)
@@ -193,12 +249,13 @@ combobox_init (DialogData *data,
static void
combobox_add_item (GtkListStore *model,
const gchar *markup,
- const gchar *id)
+ const gchar *id,
+ gboolean sensitive)
{
gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
COMBOBOX_MODEL_COLUMN_ID, id,
COMBOBOX_MODEL_COLUMN_MARKUP, markup,
- COMBOBOX_MODEL_COLUMN_SENSITIVE, TRUE,
+ COMBOBOX_MODEL_COLUMN_SENSITIVE, sensitive,
-1);
}
@@ -216,42 +273,148 @@ combobox_add_separator (GtkListStore *model)
static void
init_dialog (DialogData *data)
{
- gchar *s;
+ gchar *s, *s2, *s3;
GtkListStore *model;
+ guint64 min_size;
+ guint64 max_size;
+ GList *l;
+
+ /* ---------- */
+ /* check disk size and get block objects */
+
+ min_size = G_MAXUINT64;
+ max_size = 0;
+ data->num_disks = 0;
+ for (l = data->blocks; l != NULL; l = l->next)
+ {
+ UDisksBlock *block = UDISKS_BLOCK (l->data);
+ guint64 block_size = udisks_block_get_size (block);
+ if (block_size > max_size)
+ max_size = block_size;
+ if (block_size < min_size)
+ min_size = block_size;
+ data->num_disks += 1;
+ }
+ /* Bail if there is more than a 1% difference and at least 1MiB */
+ if (max_size - min_size > min_size * 101LL / 100LL &&
+ max_size - min_size > 1048576)
+ {
+ GtkWidget *infobar;
+ infobar = gdu_utils_create_info_bar (GTK_MESSAGE_ERROR,
+ /* Shown in error info-bar if trying to create a RAID array on disks of different size */
+ _("All disks in a RAID Array must be the same size"),
+ NULL);
+ gtk_box_pack_start (GTK_BOX (data->infobar_vbox), infobar, TRUE, TRUE, 0);
+ gtk_widget_show_all (infobar);
+ gtk_widget_set_sensitive (data->grid, FALSE);
+ data->disks_not_same_size = TRUE;
+ gtk_label_set_text (GTK_LABEL (data->num_disks_label), "â");
+ gtk_label_set_text (GTK_LABEL (data->size_label), "â");
+ }
+ else
+ {
+ data->disk_size = min_size;
+
+ /* Translators: Shown in "Create RAID Array" dialog.
+ * The %d is number of disks and is always >= 2.
+ */
+ s2 = g_strdup_printf (dngettext (GETTEXT_PACKAGE,
+ "%d disk",
+ "%d disks",
+ (gint) data->num_disks),
+ (gint) data->num_disks);
+ s3 = udisks_client_get_size_for_display (data->client, data->disk_size, FALSE, FALSE);
+ /* Translators: Shown in "Create RAID Array" dialog.
+ * The first %s is the number of disks e.g. '3 disks'.
+ * The second %s is the size of the disk e.g. '42 GB' or '3 TB'.
+ */
+ s = g_strdup_printf (_("%s of %s each"), s2, s3);
+ gtk_label_set_text (GTK_LABEL (data->num_disks_label), s);
+ /* size_label is set in update_dialog() */
+ g_free (s3);
+ g_free (s2);
+ g_free (s);
+ }
/* ---------- */
/* 'RAID Level' combobox */
model = combobox_init (data, data->level_combobox);
- s = gdu_utils_format_mdraid_level ("raid0", TRUE); combobox_add_item (model, s, "raid0"); g_free (s);
- s = gdu_utils_format_mdraid_level ("raid1", TRUE); combobox_add_item (model, s, "raid1"); g_free (s);
- s = gdu_utils_format_mdraid_level ("raid4", TRUE); combobox_add_item (model, s, "raid4"); g_free (s);
- s = gdu_utils_format_mdraid_level ("raid5", TRUE); combobox_add_item (model, s, "raid5"); g_free (s);
- s = gdu_utils_format_mdraid_level ("raid6", TRUE); combobox_add_item (model, s, "raid6"); g_free (s);
- s = gdu_utils_format_mdraid_level ("raid10", TRUE); combobox_add_item (model, s, "raid10"); g_free (s);
+ s = gdu_utils_format_mdraid_level ("raid0", TRUE);
+ combobox_add_item (model, s, "raid0", TRUE); g_free (s);
+ s = gdu_utils_format_mdraid_level ("raid1", TRUE);
+ combobox_add_item (model, s, "raid1", TRUE); g_free (s);
+ s = gdu_utils_format_mdraid_level ("raid4", TRUE);
+ combobox_add_item (model, s, "raid4", TRUE); g_free (s);
+ s = gdu_utils_format_mdraid_level ("raid5", TRUE);
+ combobox_add_item (model, s, "raid5", TRUE); g_free (s);
+ s = gdu_utils_format_mdraid_level ("raid6", TRUE);
+ combobox_add_item (model, s, "raid6", data->num_disks > 2); g_free (s);
+ s = gdu_utils_format_mdraid_level ("raid10", TRUE);
+ combobox_add_item (model, s, "raid10", TRUE); g_free (s);
/* ---------- */
/* 'Chunk Size' combobox */
model = combobox_init (data, data->chunk_combobox);
- s = udisks_client_get_size_for_display (data->client, 4*1024, TRUE, FALSE); combobox_add_item (model, s, "chunk_4"); g_free (s);
- s = udisks_client_get_size_for_display (data->client, 8*1024, TRUE, FALSE); combobox_add_item (model, s, "chunk_8"); g_free (s);
- s = udisks_client_get_size_for_display (data->client, 16*1024, TRUE, FALSE); combobox_add_item (model, s, "chunk_16"); g_free (s);
- s = udisks_client_get_size_for_display (data->client, 32*1024, TRUE, FALSE); combobox_add_item (model, s, "chunk_32"); g_free (s);
- s = udisks_client_get_size_for_display (data->client, 64*1024, TRUE, FALSE); combobox_add_item (model, s, "chunk_64"); g_free (s);
- s = udisks_client_get_size_for_display (data->client, 128*1024, TRUE, FALSE); combobox_add_item (model, s, "chunk_128"); g_free (s);
- s = udisks_client_get_size_for_display (data->client, 256*1024, TRUE, FALSE); combobox_add_item (model, s, "chunk_256"); g_free (s);
- s = udisks_client_get_size_for_display (data->client, 512*1024, TRUE, FALSE); combobox_add_item (model, s, "chunk_512"); g_free (s);
- s = udisks_client_get_size_for_display (data->client,1024*1024, TRUE, FALSE); combobox_add_item (model, s, "chunk_1024"); g_free (s);
- s = udisks_client_get_size_for_display (data->client,2048*1024, TRUE, FALSE); combobox_add_item (model, s, "chunk_2048"); g_free (s);
-
+ s = udisks_client_get_size_for_display (data->client, 4*1024, TRUE, FALSE);
+ combobox_add_item (model, s, "chunk_4", TRUE); g_free (s);
+ s = udisks_client_get_size_for_display (data->client, 8*1024, TRUE, FALSE);
+ combobox_add_item (model, s, "chunk_8", TRUE); g_free (s);
+ s = udisks_client_get_size_for_display (data->client, 16*1024, TRUE, FALSE);
+ combobox_add_item (model, s, "chunk_16", TRUE); g_free (s);
+ s = udisks_client_get_size_for_display (data->client, 32*1024, TRUE, FALSE);
+ combobox_add_item (model, s, "chunk_32", TRUE); g_free (s);
+ s = udisks_client_get_size_for_display (data->client, 64*1024, TRUE, FALSE);
+ combobox_add_item (model, s, "chunk_64", TRUE); g_free (s);
+ s = udisks_client_get_size_for_display (data->client, 128*1024, TRUE, FALSE);
+ combobox_add_item (model, s, "chunk_128", TRUE); g_free (s);
+ s = udisks_client_get_size_for_display (data->client, 256*1024, TRUE, FALSE);
+ combobox_add_item (model, s, "chunk_256", TRUE); g_free (s);
+ s = udisks_client_get_size_for_display (data->client, 512*1024, TRUE, FALSE);
+ combobox_add_item (model, s, "chunk_512", TRUE); g_free (s);
+ s = udisks_client_get_size_for_display (data->client,1024*1024, TRUE, FALSE);
+ combobox_add_item (model, s, "chunk_1024", TRUE); g_free (s);
+ s = udisks_client_get_size_for_display (data->client,2048*1024, TRUE, FALSE);
+ combobox_add_item (model, s, "chunk_2048", TRUE); g_free (s);
/* ---------- */
- /* defaults: RAID6, 512 KiB Chunk */
- gtk_combo_box_set_active_id (GTK_COMBO_BOX (data->level_combobox), "raid6");
+ /* defaults: RAID-1 for two disks, RAID-5 for three disks, RAID-6 otherwise, 512 KiB Chunk */
+ if (data->num_disks == 2)
+ gtk_combo_box_set_active_id (GTK_COMBO_BOX (data->level_combobox), "raid1");
+ else if (data->num_disks == 3)
+ gtk_combo_box_set_active_id (GTK_COMBO_BOX (data->level_combobox), "raid5");
+ else
+ gtk_combo_box_set_active_id (GTK_COMBO_BOX (data->level_combobox), "raid6");
gtk_combo_box_set_active_id (GTK_COMBO_BOX (data->chunk_combobox), "chunk_512");
+ /* Translators: this is the default name for the RAID Array */
+ gtk_entry_set_text (GTK_ENTRY (data->name_entry), _("New RAID Array"));
+
+ /* ---------- */
+
+ g_signal_connect (data->level_combobox,
+ "notify::active",
+ G_CALLBACK (on_property_changed),
+ data);
+
+ g_signal_connect (data->chunk_combobox,
+ "notify::active",
+ G_CALLBACK (on_property_changed),
+ data);
+
+ g_signal_connect (data->name_entry,
+ "notify::text",
+ G_CALLBACK (on_property_changed),
+ data);
+
+ g_signal_connect (data->client,
+ "changed",
+ G_CALLBACK (on_client_changed),
+ data);
/* ---------- */
+ gtk_widget_grab_focus (data->name_entry);
+
update_dialog (data);
}
@@ -268,7 +431,7 @@ on_client_changed (UDisksClient *client,
void
gdu_create_raid_array_dialog_show (GduWindow *window,
- GList *objects)
+ GList *blocks)
{
DialogData *data;
guint n;
@@ -277,7 +440,8 @@ gdu_create_raid_array_dialog_show (GduWindow *window,
data->ref_count = 1;
data->window = g_object_ref (window);
data->client = gdu_window_get_client (data->window);
- data->objects = g_list_copy_deep (objects, (GCopyFunc) g_object_ref, NULL);
+ data->blocks = g_list_copy_deep (blocks, (GCopyFunc) g_object_ref, NULL);
+ g_assert_cmpint (g_list_length (data->blocks), >, 0);
data->dialog = GTK_WIDGET (gdu_application_new_widget (gdu_window_get_application (window),
"create-raid-array-dialog.ui",
@@ -290,6 +454,7 @@ gdu_create_raid_array_dialog_show (GduWindow *window,
}
gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (window));
+ gtk_dialog_set_default_response (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK);
init_dialog (data);
diff --git a/src/disks/gdudevicetreemodel.c b/src/disks/gdudevicetreemodel.c
index 8a829b3..e1ba3f4 100644
--- a/src/disks/gdudevicetreemodel.c
+++ b/src/disks/gdudevicetreemodel.c
@@ -1656,3 +1656,47 @@ gdu_device_tree_model_get_selected (GduDeviceTreeModel *model)
return ret;
}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+get_selected_blocks_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ UDisksBlock *block = NULL;
+ gboolean selected = FALSE;
+ GList **ret = user_data;
+
+ gtk_tree_model_get (model,
+ iter,
+ GDU_DEVICE_TREE_MODEL_COLUMN_BLOCK, &block,
+ GDU_DEVICE_TREE_MODEL_COLUMN_SELECTED, &selected,
+ -1);
+
+ if (selected && block != NULL)
+ {
+ *ret = g_list_prepend (*ret, block); /* adopts ownership of @block */
+ }
+ else
+ {
+ g_clear_object (&block);
+ }
+
+ return FALSE; /* keep iterating */
+}
+
+GList *
+gdu_device_tree_model_get_selected_blocks (GduDeviceTreeModel *model)
+{
+ GList *ret = NULL;
+
+ g_return_val_if_fail (GDU_IS_DEVICE_TREE_MODEL (model), NULL);
+
+ gtk_tree_model_foreach (GTK_TREE_MODEL (model), get_selected_blocks_cb, &ret);
+
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/disks/gdudevicetreemodel.h b/src/disks/gdudevicetreemodel.h
index 7866b9c..99768db 100644
--- a/src/disks/gdudevicetreemodel.h
+++ b/src/disks/gdudevicetreemodel.h
@@ -48,6 +48,7 @@ void gdu_device_tree_model_clear_selected (GduDeviceTreeMode
void gdu_device_tree_model_toggle_selected (GduDeviceTreeModel *model,
GtkTreeIter *iter);
GList *gdu_device_tree_model_get_selected (GduDeviceTreeModel *model);
+GList *gdu_device_tree_model_get_selected_blocks (GduDeviceTreeModel *model);
G_END_DECLS
diff --git a/src/disks/gduwindow.c b/src/disks/gduwindow.c
index 2b26a5c..8a619dd 100644
--- a/src/disks/gduwindow.c
+++ b/src/disks/gduwindow.c
@@ -4375,9 +4375,20 @@ update_for_multi_selection (GduWindow *window, ShowFlags *show_flags)
GList *selected;
GList *l;
guint num_disks = 0;
+ guint num_blocks = 0;
guint64 total_size = 0;
+ guint64 total_size_block = 0;
gchar *s, *s2;
+ selected = gdu_device_tree_model_get_selected_blocks (window->model);
+ for (l = selected; l != NULL; l = l->next)
+ {
+ UDisksBlock *block = UDISKS_BLOCK (l->data);
+ total_size_block += udisks_block_get_size (block);
+ num_blocks++;
+ }
+ g_list_free_full (selected, g_object_unref);
+
selected = gdu_device_tree_model_get_selected (window->model);
for (l = selected; l != NULL; l = l->next)
{
@@ -4441,8 +4452,9 @@ update_for_multi_selection (GduWindow *window, ShowFlags *show_flags)
gtk_widget_show (window->overlay_toolbar);
gtk_widget_show (window->overlay_toolbar_erase_button);
gtk_widget_show (window->overlay_toolbar_raid_button);
+ /* TODO: check that appropriate RAID array exist and size is right before setting this to TRUE */
gtk_widget_set_sensitive (window->ms_raid_menu_item_add_to, TRUE);
- gtk_widget_set_sensitive (window->ms_raid_menu_item_create, num_disks > 1);
+ gtk_widget_set_sensitive (window->ms_raid_menu_item_create, num_blocks > 1);
}
else
{
@@ -4475,11 +4487,11 @@ on_ms_raid_menu_item_create_activated (GtkMenuItem *menu_item,
gpointer user_data)
{
GduWindow *window = GDU_WINDOW (user_data);
- GList *selected;
+ GList *selected_blocks;
- selected = gdu_device_tree_model_get_selected (window->model);
+ selected_blocks = gdu_device_tree_model_get_selected_blocks (window->model);
/* exit multiple selection mode */
device_tree_selection_toolbar_select_done_toggle (window, FALSE);
- gdu_create_raid_array_dialog_show (window, selected);
- g_list_free_full (selected, g_object_unref);
+ gdu_create_raid_array_dialog_show (window, selected_blocks);
+ g_list_free_full (selected_blocks, g_object_unref);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]