[gnome-disk-utility/udisks2-port] Support creating MBR partitions



commit 9da2d20dd7a79c36304e36f944a2970014562b1d
Author: David Zeuthen <davidz redhat com>
Date:   Thu Nov 10 14:49:11 2011 -0500

    Support creating MBR partitions
    
    ... this entails properly handling a lot of edge-cases because MBR is
    so crappy and comes with extended/logical partitions
    
     http://people.freedesktop.org/~david/gdu2-dos-partition-crap.png
     http://people.freedesktop.org/~david/gdu2-infobar-three-primary-and-free-space.png
     http://people.freedesktop.org/~david/gdu2-infobar-mbr-four-primary-and-free-space.png
     http://people.freedesktop.org/~david/gdu2-create-extended-partition.png
    
    Signed-off-by: David Zeuthen <davidz redhat com>

 data/ui/create-partition-dialog.ui         |  190 ++++++++++++++++++----------
 data/ui/filesystem-create.ui               |   37 ++----
 src/palimpsest/gducreatefilesystemwidget.c |  184 +++++++++++++++++++++++----
 src/palimpsest/gducreatefilesystemwidget.h |    3 +-
 src/palimpsest/gducreatepartitiondialog.c  |  160 +++++++++++++++++++++---
 src/palimpsest/gduformatvolumedialog.c     |    4 +-
 src/palimpsest/gduvolumegrid.c             |    1 +
 7 files changed, 442 insertions(+), 137 deletions(-)
---
diff --git a/data/ui/create-partition-dialog.ui b/data/ui/create-partition-dialog.ui
index 221f7ca..c0e7228 100644
--- a/data/ui/create-partition-dialog.ui
+++ b/data/ui/create-partition-dialog.ui
@@ -62,6 +62,78 @@
             <property name="orientation">vertical</property>
             <property name="spacing">12</property>
             <child>
+              <object class="GtkBox" id="infobar-vbox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkInfoBar" id="infobar-dos-error">
+                    <property name="message_type">error</property>
+                    <child internal-child="content_area">
+                      <object class="GtkBox" id="infobar1-vbox1">
+                        <property name="can_focus">False</property>
+                        <property name="orientation">horizontal</property>
+                        <property name="spacing">12</property>
+                        <child>
+                          <object class="GtkLabel" id="infobar1-label1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Error:&lt;/b&gt; Cannot create a new partition. There are already four primary partitions.</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkInfoBar" id="infobar-dos-warning">
+                    <property name="message_type">warning</property>
+                    <child internal-child="content_area">
+                      <object class="GtkBox" id="infobar2-vbox1">
+                        <property name="can_focus">False</property>
+                        <property name="orientation">horizontal</property>
+                        <property name="spacing">12</property>
+                        <child>
+                          <object class="GtkLabel" id="infobar2-label1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Warning:&lt;/b&gt; This is the last primary partition that can be created.</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
               <object class="GtkLabel" id="label1">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
@@ -72,32 +144,15 @@
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">True</property>
-                <property name="position">0</property>
+                <property name="position">1</property>
               </packing>
             </child>
             <child>
-              <object class="GtkGrid" id="grid1">
+              <object class="GtkBox" id="box2">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="margin_left">12</property>
-                <property name="row_spacing">6</property>
-                <property name="column_spacing">10</property>
-                <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">Partition _Size:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">size-spinbutton</property>
-                  </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>
+                <property name="orientation">vertical</property>
                 <child>
                   <object class="GtkScale" id="size-scale">
                     <property name="visible">True</property>
@@ -105,35 +160,51 @@
                     <property name="hexpand">True</property>
                     <property name="adjustment">size-adjustment</property>
                     <property name="restrict_to_fill_level">False</property>
-                    <property name="round_digits">1</property>
                     <property name="draw_value">False</property>
                     <property name="value_pos">bottom</property>
                   </object>
                   <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">0</property>
-                    <property name="width">4</property>
-                    <property name="height">1</property>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkHBox" id="hbox1">
+                  <object class="GtkBox" id="box3">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="spacing">6</property>
                     <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">Partition _Size:</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">size-spinbutton</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
                       <object class="GtkSpinButton" id="size-spinbutton">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
+                        <property name="has_tooltip">True</property>
                         <property name="tooltip_markup" translatable="yes">The size of the partition to create, in megabytes</property>
+                        <property name="tooltip_text" translatable="yes">The size of the partition to create, in megabytes</property>
                         <property name="invisible_char">â</property>
                         <property name="activates_default">True</property>
+                        <property name="invisible_char_set">True</property>
                         <property name="adjustment">size-adjustment</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">True</property>
-                        <property name="position">0</property>
+                        <property name="position">1</property>
                       </packing>
                     </child>
                     <child>
@@ -146,39 +217,25 @@
                       <packing>
                         <property name="expand">True</property>
                         <property name="fill">True</property>
-                        <property name="position">1</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label4">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">24</property>
+                        <property name="xalign">1</property>
+                        <property name="label" translatable="yes">Free Space _Following:</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">free-following-spinbutton</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">3</property>
                       </packing>
                     </child>
-                  </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="GtkLabel" id="label4">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="margin_left">24</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">Free Space _Following:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">free-following-spinbutton</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">2</property>
-                    <property name="top_attach">1</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHBox" id="hbox2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
                     <child>
                       <object class="GtkSpinButton" id="free-following-spinbutton">
                         <property name="visible">True</property>
@@ -194,7 +251,7 @@
                       <packing>
                         <property name="expand">True</property>
                         <property name="fill">True</property>
-                        <property name="position">0</property>
+                        <property name="position">4</property>
                       </packing>
                     </child>
                     <child>
@@ -207,22 +264,21 @@
                       <packing>
                         <property name="expand">True</property>
                         <property name="fill">True</property>
-                        <property name="position">1</property>
+                        <property name="position">5</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
-                    <property name="left_attach">3</property>
-                    <property name="top_attach">1</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
                   </packing>
                 </child>
               </object>
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">True</property>
-                <property name="position">1</property>
+                <property name="position">2</property>
               </packing>
             </child>
             <child>
@@ -236,7 +292,7 @@
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">True</property>
-                <property name="position">2</property>
+                <property name="position">3</property>
               </packing>
             </child>
             <child>
@@ -252,7 +308,7 @@
               <packing>
                 <property name="expand">True</property>
                 <property name="fill">True</property>
-                <property name="position">3</property>
+                <property name="position">4</property>
               </packing>
             </child>
           </object>
diff --git a/data/ui/filesystem-create.ui b/data/ui/filesystem-create.ui
index 7ecf98e..3bd8249 100644
--- a/data/ui/filesystem-create.ui
+++ b/data/ui/filesystem-create.ui
@@ -26,29 +26,7 @@
           </packing>
         </child>
         <child>
-          <object class="GtkComboBoxText" id="type-combobox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="has_tooltip">True</property>
-            <property name="tooltip_markup" translatable="yes">The kind of filesystem to create. Choose &lt;b&gt;Custom&lt;/b&gt; to specify a custom filesystem type such as &lt;i&gt;btrfs&lt;/i&gt;, &lt;i&gt;xfs&lt;/i&gt; or &lt;i&gt;swap&lt;/i&gt;</property>
-            <property name="tooltip_text" translatable="yes">The kind of filesystem to create. Choose Custom to specify a custom filesystem type such as btrfs, xfs or swap</property>
-            <items>
-              <item translatable="yes">Compatible with all systems and devices (FAT)</item>
-              <item translatable="yes">Compatible with most systems (NTFS)</item>
-              <item translatable="yes">Compatible with Linux systems (ext4)</item>
-              <item translatable="yes">Encrypted, compatible with Linux systems (LUKS, ext4)</item>
-              <item translatable="yes">Custom</item>
-            </items>
-          </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">
+          <object class="GtkLabel" id="name-label">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="xalign">1</property>
@@ -214,6 +192,19 @@
           </packing>
         </child>
         <child>
+          <object class="GtkComboBox" id="type-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>
           <placeholder/>
         </child>
         <child>
diff --git a/src/palimpsest/gducreatefilesystemwidget.c b/src/palimpsest/gducreatefilesystemwidget.c
index e368a93..f34c2ae 100644
--- a/src/palimpsest/gducreatefilesystemwidget.c
+++ b/src/palimpsest/gducreatefilesystemwidget.c
@@ -37,12 +37,14 @@ struct _GduCreateFilesystemWidget
 {
   GtkVBox parent;
 
-  GduApplication *application;
-  UDisksDrive *drive;
+  GduApplication  *application;
+  UDisksDrive     *drive;
+  gchar          **additional_fstypes;
 
   GtkBuilder *builder;
   GtkWidget *grid;
   GtkWidget *type_combobox;
+  GtkWidget *name_label;
   GtkWidget *name_entry;
   GtkWidget *filesystem_label;
   GtkWidget *filesystem_entry;
@@ -68,12 +70,21 @@ enum
   PROP_0,
   PROP_APPLICATION,
   PROP_DRIVE,
+  PROP_ADDITIONAL_FSTYPES,
   PROP_FSTYPE,
   PROP_NAME,
   PROP_PASSPHRASE,
   PROP_HAS_INFO
 };
 
+enum
+{
+  MODEL_COLUMN_ID,
+  MODEL_COLUMN_MARKUP,
+  MODEL_COLUMN_SEPARATOR,
+  MODEL_N_COLUMNS,
+};
+
 G_DEFINE_TYPE (GduCreateFilesystemWidget, gdu_create_filesystem_widget, GTK_TYPE_VBOX)
 
 static void
@@ -83,6 +94,7 @@ gdu_create_filesystem_widget_finalize (GObject *object)
 
   g_object_unref (widget->application);
   g_clear_object (&widget->drive);
+  g_strfreev (widget->additional_fstypes);
   g_free (widget->fstype);
   g_free (widget->name);
   g_free (widget->passphrase);
@@ -108,6 +120,10 @@ gdu_create_filesystem_widget_get_property (GObject    *object,
       g_value_set_object (value, widget->drive);
       break;
 
+    case PROP_ADDITIONAL_FSTYPES:
+      g_value_set_boxed (value, widget->additional_fstypes);
+      break;
+
     case PROP_FSTYPE:
       g_value_set_string (value, widget->fstype);
       break;
@@ -148,6 +164,10 @@ gdu_create_filesystem_widget_set_property (GObject      *object,
       widget->drive = g_value_dup_object (value);
       break;
 
+    case PROP_ADDITIONAL_FSTYPES:
+      widget->additional_fstypes = g_value_dup_boxed (value);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -159,34 +179,36 @@ gdu_create_filesystem_widget_set_property (GObject      *object,
 static void
 update (GduCreateFilesystemWidget *widget)
 {
+  gboolean show_name_widgets = TRUE;
   gboolean show_filesystem_widgets = FALSE;
   gboolean show_passphrase_widgets = FALSE;
   gboolean has_info = FALSE;
   const gchar *fstype = NULL;
   const gchar *name = NULL;
   const gchar *passphrase = NULL;
+  const gchar *id;
 
   name = gtk_entry_get_text (GTK_ENTRY (widget->name_entry));
   passphrase = gtk_entry_get_text (GTK_ENTRY (widget->passphrase_entry));
 
-  switch (gtk_combo_box_get_active (GTK_COMBO_BOX (widget->type_combobox)))
+  id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (widget->type_combobox));
+  if (g_strcmp0 (id, "vfat") == 0)
     {
-    case 0:
       fstype = "vfat";
       has_info = TRUE;
-      break;
-
-    case 1:
+    }
+  else if (g_strcmp0 (id, "ntfs") == 0)
+    {
       fstype = "ntfs";
       has_info = TRUE;
-      break;
-
-    case 2:
+    }
+  else if (g_strcmp0 (id, "ext4") == 0)
+    {
       fstype = "ext4";
       has_info = TRUE;
-      break;
-
-    case 3:
+    }
+  else if (g_strcmp0 (id, "luks+ext4") == 0)
+    {
       fstype = "ext4";
       /* Encrypted, compatible with Linux (LUKS + ext4) */
       show_passphrase_widgets = TRUE;
@@ -198,9 +220,9 @@ update (GduCreateFilesystemWidget *widget)
               has_info = TRUE;
             }
         }
-      break;
-
-    case 4:
+    }
+  else if (g_strcmp0 (id, "custom") == 0)
+    {
       /* Custom */
       show_filesystem_widgets = TRUE;
       if (strlen (gtk_entry_get_text (GTK_ENTRY (widget->filesystem_entry))) > 0)
@@ -211,11 +233,24 @@ update (GduCreateFilesystemWidget *widget)
            */
           has_info = TRUE;
         }
-      break;
+    }
+  else
+    {
+      /* Additional FS */
+      show_name_widgets = FALSE;
+      fstype = id;
+      has_info = TRUE;
+    }
 
-    default:
-      g_assert_not_reached ();
-      break;
+  if (show_name_widgets)
+    {
+      gtk_widget_show (widget->name_label);
+      gtk_widget_show (widget->name_entry);
+    }
+  else
+    {
+      gtk_widget_hide (widget->name_label);
+      gtk_widget_hide (widget->name_entry);
     }
 
   if (show_filesystem_widgets)
@@ -305,25 +340,109 @@ is_flash (UDisksDrive *drive)
   return ret;
 }
 
+static gboolean
+separator_func (GtkTreeModel *model,
+                GtkTreeIter *iter,
+                gpointer data)
+{
+  gboolean is_separator;
+  gtk_tree_model_get (model, iter,
+                      MODEL_COLUMN_SEPARATOR, &is_separator,
+                      -1);
+  return is_separator;
+}
+
 static void
-set_defaults (GduCreateFilesystemWidget *widget)
+populate (GduCreateFilesystemWidget *widget)
 {
+  GtkListStore *model;
+  GtkCellRenderer *renderer;
+  gchar *s;
+
+  model = gtk_list_store_new (MODEL_N_COLUMNS,
+                              G_TYPE_STRING,
+                              G_TYPE_STRING,
+                              G_TYPE_BOOLEAN);
+  gtk_combo_box_set_model (GTK_COMBO_BOX (widget->type_combobox), GTK_TREE_MODEL (model));
+  g_object_unref (model);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget->type_combobox), renderer, FALSE);
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget->type_combobox), renderer,
+                                  "markup", MODEL_COLUMN_MARKUP,
+                                  NULL);
+
+  gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (widget->type_combobox),
+                                        separator_func,
+                                        widget,
+                                        NULL); /* GDestroyNotify */
+
+  s = g_strdup_printf ("%s <span foreground=\"#555555\" size=\"small\">(%s)</span>",
+                       _("Compatible with all systems and devices"),
+                       _("FAT"));
+  gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
+                                     MODEL_COLUMN_ID, "vfat", MODEL_COLUMN_MARKUP, s, -1);
+  g_free (s);
+  s = g_strdup_printf ("%s <span foreground=\"#555555\" size=\"small\">(%s)</span>",
+                       _("Compatible with most systems"),
+                       _("NTFS"));
+  gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
+                                     MODEL_COLUMN_ID, "ntfs", MODEL_COLUMN_MARKUP, s, -1);
+  g_free (s);
+  s = g_strdup_printf ("%s <span foreground=\"#555555\" size=\"small\">(%s)</span>",
+                       _("Compatible with Linux systems"),
+                       _("Ext4"));
+  gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
+                                     MODEL_COLUMN_ID, "ext4", MODEL_COLUMN_MARKUP, s, -1);
+  g_free (s);
+  s = g_strdup_printf ("%s <span foreground=\"#555555\" size=\"small\">(%s)</span>",
+                       _("Encrypted, compatible with Linux systems"),
+                       _("LUKS + Ext4"));
+  gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
+                                     MODEL_COLUMN_ID,   "luks+ext4", MODEL_COLUMN_MARKUP, s, -1);
+  g_free (s);
+  s = g_strdup_printf ("%s <span foreground=\"#555555\" size=\"small\">(%s)</span>",
+                       _("Custom"),
+                       _("Enter filesystem type"));
+  gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
+                                     MODEL_COLUMN_ID, "custom", MODEL_COLUMN_MARKUP, s, -1);
+  g_free (s);
+
+  /* Add from additional_types */
+  if (widget->additional_fstypes != NULL && widget->additional_fstypes[0] != NULL)
+    {
+      guint n;
+
+      /* separator */
+      gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
+                                         MODEL_COLUMN_SEPARATOR, TRUE, -1);
+
+      for (n = 0; widget->additional_fstypes[n] != NULL; n += 2)
+        {
+          const gchar *fstype = widget->additional_fstypes[n];
+          const gchar *name = widget->additional_fstypes[n+1];
+          gtk_list_store_insert_with_values (model, NULL /* out_iter */, G_MAXINT, /* position */
+                                             MODEL_COLUMN_ID, fstype,
+                                             MODEL_COLUMN_MARKUP, name, -1);
+        }
+    }
+
   /* Default to FAT or NTFS for removable drives... Ext4 otherwise */
   if (widget->drive != NULL && udisks_drive_get_removable (widget->drive))
     {
       /* default FAT for flash and disks/media smaller than 20G (assumed to be flash cards) */
       if (is_flash (widget->drive) || udisks_drive_get_size (widget->drive) < 20L * 1000L*1000L*1000L)
         {
-          gtk_combo_box_set_active (GTK_COMBO_BOX (widget->type_combobox), 0); /* FAT */
+          gtk_combo_box_set_active_id (GTK_COMBO_BOX (widget->type_combobox), "vfat");
         }
       else
         {
-          gtk_combo_box_set_active (GTK_COMBO_BOX (widget->type_combobox), 1); /* NTFS */
+          gtk_combo_box_set_active_id (GTK_COMBO_BOX (widget->type_combobox), "ntfs");
         }
     }
   else
     {
-      gtk_combo_box_set_active (GTK_COMBO_BOX (widget->type_combobox), 2); /* Ext4 */
+      gtk_combo_box_set_active_id (GTK_COMBO_BOX (widget->type_combobox), "ext4");
     }
 
   /* Translators: this is the default name for the filesystem */
@@ -357,6 +476,7 @@ gdu_create_filesystem_widget_constructed (GObject *object)
   widget->grid = GTK_WIDGET (gtk_builder_get_object (widget->builder, "filesystem-create-grid"));
   widget->type_combobox = GTK_WIDGET (gtk_builder_get_object (widget->builder, "type-combobox"));
   g_signal_connect (widget->type_combobox, "notify::active", G_CALLBACK (on_property_changed), widget);
+  widget->name_label = GTK_WIDGET (gtk_builder_get_object (widget->builder, "name-label"));
   widget->name_entry = GTK_WIDGET (gtk_builder_get_object (widget->builder, "name-entry"));
   g_signal_connect (widget->name_entry, "notify::text", G_CALLBACK (on_property_changed), widget);
   widget->filesystem_label = GTK_WIDGET (gtk_builder_get_object (widget->builder, "filesystem-label"));
@@ -375,7 +495,7 @@ gdu_create_filesystem_widget_constructed (GObject *object)
   gtk_widget_reparent (widget->grid, GTK_WIDGET (widget));
   gtk_widget_destroy (dummy_window);
 
-  set_defaults (widget);
+  populate (widget);
   update (widget);
 
   if (G_OBJECT_CLASS (gdu_create_filesystem_widget_parent_class)->constructed != NULL)
@@ -409,6 +529,14 @@ gdu_create_filesystem_widget_class_init (GduCreateFilesystemWidgetClass *klass)
                                                         G_PARAM_CONSTRUCT_ONLY |
                                                         G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_ADDITIONAL_FSTYPES,
+                                   g_param_spec_boxed ("additional-fstypes", NULL, NULL,
+                                                       G_TYPE_STRV,
+                                                       G_PARAM_READABLE |
+                                                       G_PARAM_WRITABLE |
+                                                       G_PARAM_CONSTRUCT_ONLY |
+                                                       G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_property (gobject_class, PROP_FSTYPE,
                                    g_param_spec_string ("fstype", NULL, NULL,
                                                         NULL,
@@ -440,13 +568,15 @@ gdu_create_filesystem_widget_init (GduCreateFilesystemWidget *widget)
 }
 
 GtkWidget *
-gdu_create_filesystem_widget_new (GduApplication *application,
-                                  UDisksDrive    *drive)
+gdu_create_filesystem_widget_new (GduApplication            *application,
+                                  UDisksDrive               *drive,
+                                  const gchar * const       *additional_fstypes)
 {
   g_return_val_if_fail (GDU_IS_APPLICATION (application), NULL);
   return GTK_WIDGET (g_object_new (GDU_TYPE_CREATE_FILESYSTEM_WIDGET,
                                    "application", application,
                                    "drive", drive,
+                                   "additional-fstypes", additional_fstypes,
                                    NULL));
 }
 
diff --git a/src/palimpsest/gducreatefilesystemwidget.h b/src/palimpsest/gducreatefilesystemwidget.h
index b72a641..e6bbadf 100644
--- a/src/palimpsest/gducreatefilesystemwidget.h
+++ b/src/palimpsest/gducreatefilesystemwidget.h
@@ -34,7 +34,8 @@ G_BEGIN_DECLS
 
 GType        gdu_create_filesystem_widget_get_type       (void) G_GNUC_CONST;
 GtkWidget*   gdu_create_filesystem_widget_new            (GduApplication            *application,
-                                                          UDisksDrive               *drive);
+                                                          UDisksDrive               *drive,
+                                                          const gchar * const       *addtional_fstypes);
 const gchar *gdu_create_filesystem_widget_get_name       (GduCreateFilesystemWidget *widget);
 const gchar *gdu_create_filesystem_widget_get_fstype     (GduCreateFilesystemWidget *widget);
 const gchar *gdu_create_filesystem_widget_get_passphrase (GduCreateFilesystemWidget *widget);
diff --git a/src/palimpsest/gducreatepartitiondialog.c b/src/palimpsest/gducreatepartitiondialog.c
index 41476cc..644b19f 100644
--- a/src/palimpsest/gducreatepartitiondialog.c
+++ b/src/palimpsest/gducreatepartitiondialog.c
@@ -44,13 +44,14 @@ typedef struct
 
   GtkBuilder *builder;
   GtkWidget *dialog;
+  GtkWidget *dos_error_infobar;
+  GtkWidget *dos_warning_infobar;
   GtkWidget *size_spinbutton;
   GtkAdjustment *size_adjustment;
   GtkAdjustment *free_following_adjustment;
 
   GtkWidget *contents_box;
   GtkWidget *create_filesystem_widget;
-
 } CreatePartitionData;
 
 static void
@@ -71,15 +72,103 @@ create_partition_data_free (CreatePartitionData *data)
   g_free (data);
 }
 
+static guint
+count_primary_dos_partitions (CreatePartitionData *data)
+{
+  GList *partitions, *l;
+  guint ret = 0;
+  partitions = udisks_client_get_partitions (gdu_window_get_client (data->window), data->table);
+  for (l = partitions; l != NULL; l = l->next)
+    {
+      UDisksPartition *partition = UDISKS_PARTITION (l->data);
+      if (!udisks_partition_get_is_contained (partition))
+        ret += 1;
+    }
+  g_list_foreach (partitions, (GFunc) g_object_unref, NULL);
+  g_list_free (partitions);
+  return ret;
+}
+
+static gboolean
+have_dos_extended (CreatePartitionData *data)
+{
+  GList *partitions, *l;
+  gboolean ret = FALSE;
+  partitions = udisks_client_get_partitions (gdu_window_get_client (data->window), data->table);
+  for (l = partitions; l != NULL; l = l->next)
+    {
+      UDisksPartition *partition = UDISKS_PARTITION (l->data);
+      if (udisks_partition_get_is_container (partition))
+        {
+          ret = TRUE;
+          break;
+        }
+    }
+  g_list_foreach (partitions, (GFunc) g_object_unref, NULL);
+  g_list_free (partitions);
+  return ret;
+}
+
+static gboolean
+is_inside_dos_extended (CreatePartitionData *data, guint64 offset)
+{
+  GList *partitions, *l;
+  gboolean ret = FALSE;
+  partitions = udisks_client_get_partitions (gdu_window_get_client (data->window), data->table);
+  for (l = partitions; l != NULL; l = l->next)
+    {
+      UDisksPartition *partition = UDISKS_PARTITION (l->data);
+      if (udisks_partition_get_is_container (partition))
+        {
+          if (offset >= udisks_partition_get_offset (partition) &&
+              offset < udisks_partition_get_offset (partition) + udisks_partition_get_size (partition))
+            {
+              ret = TRUE;
+              break;
+            }
+        }
+    }
+  g_list_foreach (partitions, (GFunc) g_object_unref, NULL);
+  g_list_free (partitions);
+  return ret;
+}
+
 static void
 create_partition_update (CreatePartitionData *data)
 {
   gboolean can_proceed = FALSE;
+  gboolean show_dos_error = FALSE;
+  gboolean show_dos_warning = FALSE;
+
+  /* MBR Partitioning sucks. So if we're trying to create a primary partition, then
+   *
+   *  - Show WARNING if trying to create 4th primary partition
+   *  - Show ERROR if there are already 4 primary partitions
+   */
+  if (g_strcmp0 (udisks_partition_table_get_type_ (data->table), "dos") == 0)
+    {
+      if (!is_inside_dos_extended (data, data->offset))
+        {
+          guint num_primary;
+          num_primary = count_primary_dos_partitions (data);
+          if (num_primary == 4)
+            show_dos_error = TRUE;
+          else if (num_primary == 3)
+            show_dos_warning = TRUE;
+        }
+    }
 
   if (gtk_adjustment_get_value (data->size_adjustment) > 0 &&
       gdu_create_filesystem_widget_get_has_info (GDU_CREATE_FILESYSTEM_WIDGET (data->create_filesystem_widget)))
     can_proceed = TRUE;
 
+  if (show_dos_error)
+    can_proceed = FALSE;
+
+  if (!show_dos_warning)
+    gtk_widget_set_no_show_all (data->dos_warning_infobar, TRUE);
+  if (!show_dos_error)
+    gtk_widget_set_no_show_all (data->dos_error_infobar, TRUE);
   gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK, can_proceed);
 }
 
@@ -172,23 +261,31 @@ create_partition_cb (GObject      *source_object,
   name = gdu_create_filesystem_widget_get_name (GDU_CREATE_FILESYSTEM_WIDGET (data->create_filesystem_widget));
   passphrase = gdu_create_filesystem_widget_get_passphrase (GDU_CREATE_FILESYSTEM_WIDGET (data->create_filesystem_widget));
 
-  g_variant_builder_init (&options_builder, G_VARIANT_TYPE_VARDICT);
-  if (name != NULL && strlen (name) > 0)
-    g_variant_builder_add (&options_builder, "{sv}", "label", g_variant_new_string (name));
-  if (!(g_strcmp0 (fstype, "vfat") == 0 || g_strcmp0 (fstype, "ntfs") == 0))
+  /* Not meaningful to create a filesystem if requested to create an extended partition */
+  if (g_strcmp0 (fstype, "dos_extended") == 0)
+    {
+      create_partition_data_free (data);
+    }
+  else
     {
-      /* TODO: need a better way to determine if this should be TRUE */
-      g_variant_builder_add (&options_builder, "{sv}", "take-ownership", g_variant_new_boolean (TRUE));
+      g_variant_builder_init (&options_builder, G_VARIANT_TYPE_VARDICT);
+      if (name != NULL && strlen (name) > 0)
+        g_variant_builder_add (&options_builder, "{sv}", "label", g_variant_new_string (name));
+      if (!(g_strcmp0 (fstype, "vfat") == 0 || g_strcmp0 (fstype, "ntfs") == 0))
+        {
+          /* TODO: need a better way to determine if this should be TRUE */
+          g_variant_builder_add (&options_builder, "{sv}", "take-ownership", g_variant_new_boolean (TRUE));
+        }
+      if (passphrase != NULL && strlen (passphrase) > 0)
+        g_variant_builder_add (&options_builder, "{sv}", "encrypt.passphrase", g_variant_new_string (passphrase));
+
+      udisks_block_call_format (partition_block,
+                                fstype,
+                                g_variant_builder_end (&options_builder),
+                                NULL, /* GCancellable */
+                                format_cb,
+                                data);
     }
-  if (passphrase != NULL && strlen (passphrase) > 0)
-    g_variant_builder_add (&options_builder, "{sv}", "encrypt.passphrase", g_variant_new_string (passphrase));
-
-  udisks_block_call_format (partition_block,
-                            fstype,
-                            g_variant_builder_end (&options_builder),
-                            NULL, /* GCancellable */
-                            format_cb,
-                            data);
 
  out:
   g_free (created_partition_object_path);
@@ -204,6 +301,8 @@ gdu_create_partition_dialog_show (GduWindow    *window,
   CreatePartitionData *data;
   guint64 max_size_mb;
   gint response;
+  const gchar *additional_fstypes[3] = {NULL, NULL, NULL};
+  gchar dos_extended_partition_name[256];
 
   data = g_new0 (CreatePartitionData, 1);
   data->window = g_object_ref (window);
@@ -216,16 +315,33 @@ gdu_create_partition_dialog_show (GduWindow    *window,
   data->offset = offset;
   data->max_size = max_size;
 
+  if (g_strcmp0 (udisks_partition_table_get_type_ (data->table), "dos") == 0)
+    {
+      if (!have_dos_extended (data))
+        {
+          snprintf (dos_extended_partition_name, sizeof dos_extended_partition_name,
+                    "%s <span foreground=\"#555555\" size=\"small\">(%s)</span>",
+                    _("Extended partition"),
+                    _("For logical partitions"));
+          additional_fstypes[0] = "dos_extended";
+          additional_fstypes[1] = dos_extended_partition_name;
+        }
+    }
+
   data->dialog = gdu_application_new_widget (gdu_window_get_application (window),
                                              "create-partition-dialog.ui",
                                              "create-partition-dialog",
                                              &data->builder);
+  data->dos_error_infobar = GTK_WIDGET (gtk_builder_get_object (data->builder, "infobar-dos-error"));;
+  data->dos_warning_infobar = GTK_WIDGET (gtk_builder_get_object (data->builder, "infobar-dos-warning"));;
   data->size_spinbutton = GTK_WIDGET (gtk_builder_get_object (data->builder, "size-spinbutton"));
   data->size_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (data->builder, "size-adjustment"));
   g_signal_connect (data->size_adjustment, "notify::value", G_CALLBACK (create_partition_property_changed), data);
   data->free_following_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (data->builder, "free-following-adjustment"));
   data->contents_box = GTK_WIDGET (gtk_builder_get_object (data->builder, "contents-box"));
-  data->create_filesystem_widget = gdu_create_filesystem_widget_new (gdu_window_get_application (window), data->drive);
+  data->create_filesystem_widget = gdu_create_filesystem_widget_new (gdu_window_get_application (window),
+                                                                     data->drive,
+                                                                     additional_fstypes);
   gtk_box_pack_start (GTK_BOX (data->contents_box),
                       data->create_filesystem_widget,
                       TRUE, TRUE, 0);
@@ -272,14 +388,22 @@ gdu_create_partition_dialog_show (GduWindow    *window,
   if (response == GTK_RESPONSE_OK)
     {
       guint64 size;
+      const gchar *fstype;
+      const gchar *partition_type = "";
 
       gtk_widget_hide (data->dialog);
 
+      fstype = gdu_create_filesystem_widget_get_fstype (GDU_CREATE_FILESYSTEM_WIDGET (data->create_filesystem_widget));
+      if (g_strcmp0 (fstype, "dos_extended") == 0)
+        {
+          partition_type = "0x05";
+        }
+
       size = gtk_adjustment_get_value (data->size_adjustment) * 1000L * 1000L;
       udisks_partition_table_call_create_partition (data->table,
                                                     data->offset,
                                                     size,
-                                                    "", /* use default type */
+                                                    partition_type, /* use default type */
                                                     "", /* use blank partition name */
                                                     g_variant_new ("a{sv}", NULL), /* options */
                                                     NULL, /* GCancellable */
diff --git a/src/palimpsest/gduformatvolumedialog.c b/src/palimpsest/gduformatvolumedialog.c
index 8a3bead..1697082 100644
--- a/src/palimpsest/gduformatvolumedialog.c
+++ b/src/palimpsest/gduformatvolumedialog.c
@@ -123,7 +123,9 @@ gdu_format_volume_dialog_show (GduWindow    *window,
                                              &data->builder);
 
   data->contents_box = GTK_WIDGET (gtk_builder_get_object (data->builder, "contents-box"));
-  data->create_filesystem_widget = gdu_create_filesystem_widget_new (gdu_window_get_application (window), data->drive);
+  data->create_filesystem_widget = gdu_create_filesystem_widget_new (gdu_window_get_application (window),
+                                                                     data->drive,
+                                                                     NULL); /* additional_fstypes */
   gtk_box_pack_start (GTK_BOX (data->contents_box),
                       data->create_filesystem_widget,
                       TRUE, TRUE, 0);
diff --git a/src/palimpsest/gduvolumegrid.c b/src/palimpsest/gduvolumegrid.c
index 96a9517..1b2ed54 100644
--- a/src/palimpsest/gduvolumegrid.c
+++ b/src/palimpsest/gduvolumegrid.c
@@ -1947,6 +1947,7 @@ grid_element_set_details (GduVolumeGrid  *grid,
         if (partition != NULL && udisks_partition_get_is_container (partition))
           {
             g_ptr_array_add (lines, g_strdup (C_("volume-grid", "Extended Partition")));
+            maybe_add_partition (grid, lines, partition);
             g_ptr_array_add (lines, g_strdup (size_str));
           }
         else if (filesystem != NULL)



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