[gnome-disk-utility] Don't offer "Create RAID Array" dialog unless disks are all the same size



commit 8cfc8df9873761d314bb86bff701609b5865bcf4
Author: David Zeuthen <zeuthen gmail com>
Date:   Thu Oct 11 15:39:29 2012 -0400

    Don't offer "Create RAID Array" dialog unless disks are all the same size
    
    That way we don't have to show an error cluebar at all.
    
    Signed-off-by: David Zeuthen <zeuthen gmail com>

 data/ui/create-raid-array-dialog.ui  |  322 ++++++++++++++++------------------
 src/disks/gducreateraidarraydialog.c |   74 +++-----
 src/disks/gduwindow.c                |   27 ++-
 src/libgdu/gduutils.c                |   35 ++++
 src/libgdu/gduutils.h                |    3 +
 5 files changed, 233 insertions(+), 228 deletions(-)
---
diff --git a/data/ui/create-raid-array-dialog.ui b/data/ui/create-raid-array-dialog.ui
index 4c76eba..2b59fa6 100644
--- a/data/ui/create-raid-array-dialog.ui
+++ b/data/ui/create-raid-array-dialog.ui
@@ -54,195 +54,167 @@
           </packing>
         </child>
         <child>
-          <object class="GtkBox" id="box1">
+          <object class="GtkGrid" id="grid">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="orientation">vertical</property>
-            <property name="spacing">12</property>
+            <property name="row_spacing">10</property>
+            <property name="column_spacing">10</property>
             <child>
-              <object class="GtkBox" id="infobar-vbox">
+              <object class="GtkLabel" id="label1">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="orientation">vertical</property>
-                <child>
-                  <placeholder/>
-                </child>
+                <property name="xalign">1</property>
+                <property name="label" translatable="yes">RAID _Level</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">level-combobox</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
               </packing>
             </child>
             <child>
-              <object class="GtkGrid" id="grid">
+              <object class="GtkComboBox" id="level-combobox">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="row_spacing">10</property>
-                <property name="column_spacing">10</property>
-                <child>
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">RAID _Level</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">level-combobox</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">0</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkComboBox" id="level-combobox">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="id_column">0</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">0</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">Chunk _Size</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">chunk-combobox</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">1</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label3">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">_Name</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">name-entry</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">2</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkComboBox" id="chunk-combobox">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="id_column">0</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">1</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="name-entry">
-                    <property name="visible">True</property>
-                    <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>
-                    <property name="top_attach">2</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label5">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">Array Size</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">4</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label4">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">Number of Disks</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">3</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="num-disks-label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">3</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="size-label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">4</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
+                <property name="id_column">0</property>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
+                <property name="left_attach">1</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">1</property>
+                <property name="label" translatable="yes">Chunk _Size</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">chunk-combobox</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">1</property>
+                <property name="label" translatable="yes">_Name</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">name-entry</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkComboBox" id="chunk-combobox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="id_column">0</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="name-entry">
+                <property name="visible">True</property>
+                <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>
+                <property name="top_attach">2</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label5">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">1</property>
+                <property name="label" translatable="yes">Array Size</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">4</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label4">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">1</property>
+                <property name="label" translatable="yes">Number of Disks</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">3</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="num-disks-label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">0</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">3</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="size-label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">0</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">4</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
               </packing>
             </child>
           </object>
diff --git a/src/disks/gducreateraidarraydialog.c b/src/disks/gducreateraidarraydialog.c
index ba2f8b4..08ff4f9 100644
--- a/src/disks/gducreateraidarraydialog.c
+++ b/src/disks/gducreateraidarraydialog.c
@@ -37,8 +37,6 @@ typedef struct
 
   GtkWidget *dialog;
 
-  GtkWidget *infobar_vbox;
-
   GtkWidget *grid;
   GtkWidget *level_combobox;
   GtkWidget *chunk_combobox;
@@ -52,8 +50,6 @@ static const struct {
   const gchar *name;
 } widget_mapping[] = {
 
-  {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"},
@@ -295,46 +291,28 @@ init_dialog (DialogData *data)
         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);
-    }
+  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 */
@@ -441,7 +419,14 @@ gdu_create_raid_array_dialog_show (GduWindow *window,
   data->window = g_object_ref (window);
   data->client = gdu_window_get_client (data->window);
   data->blocks = g_list_copy_deep (blocks, (GCopyFunc) g_object_ref, NULL);
-  g_assert_cmpint (g_list_length (data->blocks), >, 0);
+  data->num_disks = g_list_length (data->blocks);
+  g_assert_cmpint (data->num_disks, >, 0);
+
+  if (!gdu_util_is_same_size (blocks, &data->disk_size))
+    {
+      g_warning ("Disks are not the same size");
+      goto out;
+    }
 
   data->dialog = GTK_WIDGET (gdu_application_new_widget (gdu_window_get_application (window),
                                                          "create-raid-array-dialog.ui",
@@ -477,4 +462,3 @@ gdu_create_raid_array_dialog_show (GduWindow *window,
   dialog_data_close (data);
   dialog_data_unref (data);
 }
-
diff --git a/src/disks/gduwindow.c b/src/disks/gduwindow.c
index 8a619dd..632b1b8 100644
--- a/src/disks/gduwindow.c
+++ b/src/disks/gduwindow.c
@@ -4373,6 +4373,7 @@ static void
 update_for_multi_selection (GduWindow *window, ShowFlags *show_flags)
 {
   GList *selected;
+  GList *selected_blocks;
   GList *l;
   guint num_disks = 0;
   guint num_blocks = 0;
@@ -4380,14 +4381,13 @@ update_for_multi_selection (GduWindow *window, ShowFlags *show_flags)
   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)
+  selected_blocks = gdu_device_tree_model_get_selected_blocks (window->model);
+  for (l = selected_blocks; 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)
@@ -4421,7 +4421,6 @@ update_for_multi_selection (GduWindow *window, ShowFlags *show_flags)
           g_warning ("unhandled object of with path %s", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
         }
     }
-  g_list_free_full (selected, g_object_unref);
 
   if (num_disks == 0)
     {
@@ -4449,17 +4448,29 @@ update_for_multi_selection (GduWindow *window, ShowFlags *show_flags)
   /* visibility - TODO: use ShowFlags instead */
   if (window->in_selection_mode && num_disks > 0)
     {
+      guint64 disk_size;
       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_blocks > 1);
+      /* RAID requires at all disks are the same size */
+      if (gdu_util_is_same_size (selected_blocks, &disk_size))
+        {
+          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_blocks > 1);
+        }
+      else
+        {
+          gtk_widget_hide (window->overlay_toolbar_raid_button);
+        }
     }
   else
     {
       gtk_widget_hide (window->overlay_toolbar);
     }
+
+  g_list_free_full (selected, g_object_unref);
+  g_list_free_full (selected_blocks, g_object_unref);
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/libgdu/gduutils.c b/src/libgdu/gduutils.c
index 35f969d..ccd2405 100644
--- a/src/libgdu/gduutils.c
+++ b/src/libgdu/gduutils.c
@@ -738,3 +738,38 @@ gdu_utils_format_mdraid_level (const gchar *level,
     }
   return ret;
 }
+
+gboolean
+gdu_util_is_same_size (GList   *blocks,
+                       guint64 *out_min_size)
+{
+  gboolean ret = FALSE;
+  guint64 min_size = G_MAXUINT64;
+  guint64 max_size = 0;
+  GList *l;
+
+  if (blocks == NULL)
+    goto out;
+
+  for (l = 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;
+    }
+
+  /* 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)
+    goto out;
+
+  ret = TRUE;
+
+ out:
+  if (out_min_size != NULL)
+    *out_min_size = min_size;
+  return ret;
+}
diff --git a/src/libgdu/gduutils.h b/src/libgdu/gduutils.h
index 1db94ea..03fe8ac 100644
--- a/src/libgdu/gduutils.h
+++ b/src/libgdu/gduutils.h
@@ -62,6 +62,9 @@ gboolean gdu_utils_is_ntfs_available (void);
 gchar *gdu_utils_format_mdraid_level (const gchar *level,
                                       gboolean     long_desc);
 
+gboolean gdu_util_is_same_size (GList   *blocks,
+                                guint64 *out_min_size);
+
 G_END_DECLS
 
 #endif /* __GDU_UTILS_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]