[gnome-disk-utility/wip/mdraid] Make the "Select Disks" dialog work inside the "Create RAID Array" dialog



commit ea5c414fdd5c17e3fa7a3039dbeee7291294a6ec
Author: David Zeuthen <zeuthen gmail com>
Date:   Tue Sep 25 12:10:41 2012 -0400

    Make the "Select Disks" dialog work inside the "Create RAID Array" dialog
    
    Signed-off-by: David Zeuthen <zeuthen gmail com>

 src/disks/gducreateraidarraydialog.c |  449 ++++++++++++++++++++++++++++++++-
 src/disks/gdudevicetreemodel.c       |   20 +-
 src/disks/gdudevicetreemodel.h       |    1 +
 src/disks/gduselectdiskdialog.c      |   70 ++++--
 src/disks/gduselectdiskdialog.h      |    1 +
 5 files changed, 505 insertions(+), 36 deletions(-)
---
diff --git a/src/disks/gducreateraidarraydialog.c b/src/disks/gducreateraidarraydialog.c
index f389242..35a7c62 100644
--- a/src/disks/gducreateraidarraydialog.c
+++ b/src/disks/gducreateraidarraydialog.c
@@ -17,6 +17,7 @@
 #include "gduwindow.h"
 #include "gducreateraidarraydialog.h"
 #include "gduselectdiskdialog.h"
+#include "gduatasmartdialog.h"
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -45,6 +46,11 @@ typedef struct
   GtkWidget *chunk_combobox;
   GtkWidget *name_entry;
 
+  GtkWidget *model_label;
+  GtkWidget *device_label;
+  GtkWidget *serial_label;
+  GtkWidget *assessment_label;
+
   GtkListStore *store;
 } DialogData;
 
@@ -65,15 +71,40 @@ static const struct {
   {G_STRUCT_OFFSET (DialogData, chunk_combobox), "chunk-combobox"},
   {G_STRUCT_OFFSET (DialogData, name_entry), "name-entry"},
 
+  {G_STRUCT_OFFSET (DialogData, model_label), "model-label"},
+  {G_STRUCT_OFFSET (DialogData, device_label), "device-label"},
+  {G_STRUCT_OFFSET (DialogData, serial_label), "serial-label"},
+  {G_STRUCT_OFFSET (DialogData, assessment_label), "assessment-label"},
+
   {0, NULL}
 };
 
+enum
+{
+  COMBOBOX_MODEL_COLUMN_ID,
+  COMBOBOX_MODEL_COLUMN_MARKUP,
+  COMBOBOX_MODEL_COLUMN_SEPARATOR,
+  COMBOBOX_MODEL_COLUMN_SENSITIVE,
+  COMBOBOX_MODEL_N_COLUMNS,
+};
+
+enum
+{
+  DISKS_MODEL_COLUMN_SLOT,
+  DISKS_MODEL_COLUMN_BLOCK,
+  DISKS_MODEL_N_COLUMNS
+};
+
 static void update_dialog (DialogData *data);
 
 
 static void on_client_changed (UDisksClient  *client,
                                gpointer       user_data);
 
+
+static void on_tree_selection_changed (GtkTreeSelection *selection,
+                                       gpointer          user_data);
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 G_GNUC_UNUSED static DialogData *
@@ -88,6 +119,10 @@ dialog_data_unref (DialogData *data)
 {
   if (g_atomic_int_dec_and_test (&data->ref_count))
     {
+      g_signal_handlers_disconnect_by_func (data->treeview,
+                                            G_CALLBACK (on_tree_selection_changed),
+                                            data);
+
       if (data->dialog != NULL)
         {
           gtk_widget_hide (data->dialog);
@@ -115,6 +150,95 @@ dialog_data_close (DialogData *data)
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
+update_dialog_labels (DialogData *data)
+{
+  GtkTreeIter titer;
+  UDisksObject *object = NULL;
+  UDisksBlock *block = NULL;
+  UDisksDrive *drive = NULL;
+  gchar *model_markup = NULL;
+  gchar *device_markup = NULL;
+  gchar *serial_markup = NULL;
+  gchar *assessment_markup = NULL;
+  const gchar *drive_revision = NULL;
+  UDisksObjectInfo *info = NULL;
+  UDisksObject *drive_object = NULL;
+  UDisksDriveAta *ata = NULL;
+
+  if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview)),
+                                       NULL, /* out_model */
+                                       &titer))
+    {
+      gtk_tree_model_get (GTK_TREE_MODEL (data->store),
+                          &titer,
+                          DISKS_MODEL_COLUMN_BLOCK, &block,
+                          -1);
+    }
+  if (block == NULL)
+    goto out;
+
+  object = (UDisksObject *) g_dbus_interface_dup_object (G_DBUS_INTERFACE (block));
+  if (object == NULL)
+    goto out;
+
+  if (udisks_block_get_read_only (block))
+    {
+      /* Translators: Shown for a read-only device. The %s is the device file, e.g. /dev/sdb1 */
+      device_markup = g_strdup_printf (_("%s <span size=\"smaller\">(Read-Only)</span>"),
+                                       udisks_block_get_preferred_device (block));
+    }
+  else
+    {
+      device_markup = g_strdup (udisks_block_get_preferred_device (block));
+    }
+
+  info = udisks_client_get_object_info (data->client, object);
+  drive = udisks_client_get_drive_for_block (data->client, block);
+  if (drive != NULL)
+    {
+      drive_revision = udisks_drive_get_revision (drive);
+      drive_object = (UDisksObject *) g_dbus_interface_get_object (G_DBUS_INTERFACE (drive));
+      ata = udisks_object_peek_drive_ata (drive_object);
+      serial_markup = udisks_drive_dup_serial (drive);
+      if (ata != NULL && !udisks_drive_get_media_removable (drive))
+        {
+          assessment_markup = gdu_ata_smart_get_one_liner_assessment (ata,
+                                                                      NULL,  /* out_smart_is_supported */
+                                                                      NULL); /* out_warning */
+        }
+    }
+
+  if (drive_revision != NULL && strlen (drive_revision) > 0)
+    {
+      /* Translators: Shown for "Model" field.
+       *              The first %s is the name of the object (e.g. "INTEL SSDSA2MH080G1GC").
+       *              The second %s is the fw revision (e.g "45ABX21").
+       */
+      model_markup = g_strdup_printf (C_("mdraid-disks", "%s (%s)"), info->name, drive_revision);
+    }
+  else
+    {
+      model_markup = g_strdup (info->name);
+    }
+
+ out:
+  gtk_label_set_markup (GTK_LABEL (data->model_label),      model_markup != NULL ?      model_markup : "â");
+  gtk_label_set_markup (GTK_LABEL (data->device_label),     device_markup != NULL ?     device_markup : "â");
+  gtk_label_set_markup (GTK_LABEL (data->serial_label),     serial_markup != NULL ?     serial_markup : "â");
+  gtk_label_set_markup (GTK_LABEL (data->assessment_label), assessment_markup != NULL ? assessment_markup : "â");
+
+  g_free (model_markup);
+  g_free (device_markup);
+  g_free (serial_markup);
+  g_free (assessment_markup);
+  if (info != NULL)
+    udisks_object_info_unref (info);
+  g_clear_object (&drive);
+  g_clear_object (&object);
+  g_clear_object (&block);
+}
+
+static void
 update_dialog (DialogData *data)
 {
   /* don't recurse */
@@ -122,7 +246,7 @@ update_dialog (DialogData *data)
     goto out;
 
   data->in_update = TRUE;
-  /* TODO */
+  update_dialog_labels (data);
   data->in_update = FALSE;
 
  out:
@@ -142,30 +266,242 @@ on_property_changed (GObject     *object,
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+static gboolean
+has_block (DialogData  *data,
+           UDisksBlock *block)
+{
+  GtkTreeIter iter;
+  gboolean ret = FALSE;
+
+  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (data->store), &iter))
+    {
+      do
+        {
+          UDisksBlock *iter_block = NULL;
+          gtk_tree_model_get (GTK_TREE_MODEL (data->store), &iter,
+                              DISKS_MODEL_COLUMN_BLOCK, &iter_block,
+                              -1);
+          if (iter_block != NULL)
+            {
+              if (iter_block == block)
+                {
+                  ret = TRUE;
+                  g_object_unref (iter_block);
+                  goto out;
+                }
+              else
+                {
+                  g_object_unref (iter_block);
+                }
+            }
+        }
+      while (gtk_tree_model_iter_next (GTK_TREE_MODEL (data->store), &iter));
+    }
+
+ out:
+  return ret;
+}
+
+static gint
+get_num_blocks (DialogData *data)
+{
+  GtkTreeIter iter;
+  gint ret = 0;
+
+  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (data->store), &iter))
+    {
+      do
+        {
+          ret += 1;
+        }
+      while (gtk_tree_model_iter_next (GTK_TREE_MODEL (data->store), &iter));
+    }
+
+  return ret;
+}
+
 static void
 on_add_toolbutton_clicked (GtkToolButton   *tool_button,
                            gpointer         user_data)
 {
   DialogData *data = user_data;
-  GList *disks;
+  GList *blocks, *l;
+
+  blocks = gdu_select_disk_dialog_show (gdu_window_get_application (data->window),
+                                        GTK_WINDOW (data->dialog),
+                                        0, /* TODO: size */
+                                        GDU_SELECT_DISK_FLAGS_ALLOW_MULTIPLE);
+  for (l = blocks; l != NULL; l = l->next)
+    {
+      UDisksBlock *block = UDISKS_BLOCK (l->data);
+      gint next_slot;
+
+      if (has_block (data, block))
+        continue;
+
+      next_slot = get_num_blocks (data);
 
-  disks = gdu_select_disk_dialog_show (gdu_window_get_application (data->window),
-                                       GTK_WINDOW (data->dialog),
-                                       GDU_SELECT_DISK_FLAGS_ALLOW_MULTIPLE);
-  /* TODO: look at @disks */
-  g_list_free_full (disks, g_object_unref);
+      gtk_list_store_insert_with_values (data->store, NULL /* out_iter */, G_MAXINT, /* position */
+                                         DISKS_MODEL_COLUMN_SLOT, next_slot,
+                                         DISKS_MODEL_COLUMN_BLOCK, block,
+                                         -1);
+
+    }
+  g_list_free_full (blocks, g_object_unref);
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
 
-enum
+static gint
+disks_row_sort_func (GtkTreeModel *model,
+                     GtkTreeIter  *a,
+                     GtkTreeIter  *b,
+                     gpointer      user_data)
 {
-  COMBOBOX_MODEL_COLUMN_ID,
-  COMBOBOX_MODEL_COLUMN_MARKUP,
-  COMBOBOX_MODEL_COLUMN_SEPARATOR,
-  COMBOBOX_MODEL_COLUMN_SENSITIVE,
-  COMBOBOX_MODEL_N_COLUMNS,
-};
+  gint ret;
+  gint slot_a, slot_b;
+  UDisksBlock *block_a = NULL, *block_b = NULL;
+
+  gtk_tree_model_get (model, a,
+                      DISKS_MODEL_COLUMN_SLOT, &slot_a,
+                      DISKS_MODEL_COLUMN_BLOCK, &block_a,
+                      -1);
+  gtk_tree_model_get (model, a,
+                      DISKS_MODEL_COLUMN_SLOT, &slot_b,
+                      DISKS_MODEL_COLUMN_BLOCK, &block_b,
+                      -1);
+
+  ret = slot_a - slot_b;
+  if (ret != 0)
+    goto out;
+
+  ret = g_strcmp0 (udisks_block_get_preferred_device (block_a),
+                   udisks_block_get_preferred_device (block_b));
+
+ out:
+  g_clear_object (&block_a);
+  g_clear_object (&block_b);
+  return ret;
+}
+
+static void
+disks_slot_cell_func (GtkTreeViewColumn *column,
+                      GtkCellRenderer   *renderer,
+                      GtkTreeModel      *model,
+                      GtkTreeIter       *iter,
+                      gpointer           user_data)
+{
+  /* DialogData *data = user_data; */
+  gint slot = -1;
+  gchar *markup = NULL;
+
+  gtk_tree_model_get (model,
+                      iter,
+                      DISKS_MODEL_COLUMN_SLOT, &slot,
+                      -1);
+
+  if (slot == -1)
+    {
+      markup = g_strdup_printf ("â");
+    }
+  else
+    {
+      markup = g_strdup_printf ("%d", slot);
+    }
+
+  g_object_set (renderer,
+                "markup", markup,
+                NULL);
+
+  g_free (markup);
+}
+
+static void
+disks_pixbuf_cell_func (GtkTreeViewColumn *column,
+                        GtkCellRenderer   *renderer,
+                        GtkTreeModel      *model,
+                        GtkTreeIter       *iter,
+                        gpointer           user_data)
+{
+  DialogData *data = user_data;
+  UDisksBlock *block = NULL;
+  UDisksObject *object = NULL;
+  UDisksObjectInfo *info = NULL;
+  GIcon *icon = NULL;
+
+  gtk_tree_model_get (model,
+                      iter,
+                      DISKS_MODEL_COLUMN_BLOCK, &block,
+                      -1);
+
+  if (block == NULL)
+    goto out;
+
+  object = (UDisksObject *) g_dbus_interface_dup_object (G_DBUS_INTERFACE (block));
+  if (object == NULL)
+    goto out;
+
+  info = udisks_client_get_object_info (data->client, object);
+  if (info->icon != NULL)
+    icon = g_object_ref (info->icon);
+
+  if (icon == NULL)
+    icon = g_themed_icon_new ("drive-removable-media"); /* fallback - for now */
+
+ out:
+  g_object_set (renderer,
+                "gicon", icon,
+                NULL);
+
+  g_clear_object (&icon);
+  g_clear_object (&object);
+  g_clear_object (&block);
+  if (info != NULL)
+    udisks_object_info_unref (info);
+}
+
+static void
+disks_name_cell_func (GtkTreeViewColumn *column,
+                      GtkCellRenderer   *renderer,
+                      GtkTreeModel      *model,
+                      GtkTreeIter       *iter,
+                      gpointer           user_data)
+{
+  DialogData *data = user_data;
+  UDisksBlock *block = NULL;
+  UDisksObject *object = NULL;
+  UDisksObjectInfo *info = NULL;
+  gchar *markup = NULL;
+
+  gtk_tree_model_get (model,
+                      iter,
+                      DISKS_MODEL_COLUMN_BLOCK, &block,
+                      -1);
+
+  if (block == NULL)
+    goto out;
+
+  object = (UDisksObject *) g_dbus_interface_dup_object (G_DBUS_INTERFACE (block));
+  if (object == NULL)
+    goto out;
+
+  info = udisks_client_get_object_info (data->client, object);
+  markup = g_strdup (info->description);
+
+ out:
+
+  g_object_set (renderer,
+                "markup", markup,
+                NULL);
+
+  g_free (markup);
+  g_clear_object (&object);
+  g_clear_object (&block);
+  if (info != NULL)
+    udisks_object_info_unref (info);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
 
 static gboolean
 combobox_separator_func (GtkTreeModel *model,
@@ -186,6 +522,7 @@ combobox_init (DialogData  *data,
   GtkListStore *model;
   GtkCellRenderer *renderer;
 
+  {G_STATIC_ASSERT (COMBOBOX_MODEL_N_COLUMNS == 4);}
   model = gtk_list_store_new (COMBOBOX_MODEL_N_COLUMNS,
                               G_TYPE_STRING,
                               G_TYPE_STRING,
@@ -230,9 +567,13 @@ combobox_add_separator (GtkListStore *model)
                                      -1);
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
+
 static void
 init_dialog (DialogData *data)
 {
+  GtkTreeViewColumn *column;
+  GtkCellRenderer *renderer;
   GtkStyleContext *context;
   GtkListStore *model;
   gchar *s;
@@ -243,6 +584,7 @@ init_dialog (DialogData *data)
   gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
   gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
 
+  /* ---------- */
   /* '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);
@@ -252,6 +594,8 @@ init_dialog (DialogData *data)
   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);
 
+  /* ---------- */
+  /* '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);
@@ -265,6 +609,70 @@ init_dialog (DialogData *data)
   s = udisks_client_get_size_for_display (data->client,2048*1024, TRUE, FALSE); combobox_add_item (model, s, "chunk_2048"); g_free (s);
 
 
+  /* ---------- */
+  /* Disks list */
+
+  {G_STATIC_ASSERT (DISKS_MODEL_N_COLUMNS == 2);}
+  data->store = gtk_list_store_new (2,
+                                    G_TYPE_INT,
+                                    UDISKS_TYPE_BLOCK);
+
+  gtk_tree_view_set_model (GTK_TREE_VIEW (data->treeview), GTK_TREE_MODEL (data->store));
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (data->store),
+                                        DISKS_MODEL_COLUMN_SLOT,
+                                        GTK_SORT_ASCENDING);
+  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (data->store),
+                                   DISKS_MODEL_COLUMN_SLOT,
+                                   disks_row_sort_func,
+                                   data, /* user_data */
+                                   NULL); /* GDestroyNotify */
+
+  column = gtk_tree_view_column_new ();
+  gtk_tree_view_append_column (GTK_TREE_VIEW (data->treeview), column);
+  /* Translators: column name for the position of the disk in the RAID array */
+  gtk_tree_view_column_set_title (column, C_("mdraid-disks", "Position"));
+  /* -- */
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  g_object_set (G_OBJECT (renderer),
+                "yalign", 0.5,
+                NULL);
+  gtk_tree_view_column_set_cell_data_func (column,
+                                           renderer,
+                                           disks_slot_cell_func,
+                                           data,  /* user_data */
+                                           NULL); /* user_data GDestroyNotify */
+
+  column = gtk_tree_view_column_new ();
+  gtk_tree_view_append_column (GTK_TREE_VIEW (data->treeview), column);
+  /* Translators: column name for the disk in the RAID array */
+  gtk_tree_view_column_set_title (column, C_("mdraid-disks", "Disk"));
+  gtk_tree_view_column_set_expand (column, TRUE);
+  /* -- */
+  renderer = gtk_cell_renderer_pixbuf_new ();
+  g_object_set (G_OBJECT (renderer),
+                "stock-size", GTK_ICON_SIZE_SMALL_TOOLBAR,
+                NULL);
+  gtk_tree_view_column_pack_start (column, renderer, FALSE);
+  gtk_tree_view_column_set_cell_data_func (column,
+                                           renderer,
+                                           disks_pixbuf_cell_func,
+                                           data,  /* user_data */
+                                           NULL); /* user_data GDestroyNotify */
+  /* -- */
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  g_object_set (G_OBJECT (renderer),
+                "yalign", 0.5,
+                "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
+                NULL);
+  gtk_tree_view_column_set_cell_data_func (column,
+                                           renderer,
+                                           disks_name_cell_func,
+                                           data,  /* user_data */
+                                           NULL); /* user_data GDestroyNotify */
+
+  /* ---------- */
   /* defaults: RAID6, 512 KiB Chunk */
   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");
@@ -276,6 +684,11 @@ init_dialog (DialogData *data)
                     G_CALLBACK (on_add_toolbutton_clicked),
                     data);
 
+  g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview)),
+                    "changed",
+                    G_CALLBACK (on_tree_selection_changed),
+                    data);
+
   /* ---------- */
 
   update_dialog (data);
@@ -289,6 +702,14 @@ on_client_changed (UDisksClient   *client,
   update_dialog (data);
 }
 
+static void
+on_tree_selection_changed (GtkTreeSelection *selection,
+                           gpointer          user_data)
+{
+  DialogData *data = user_data;
+  update_dialog (data);
+}
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 
diff --git a/src/disks/gdudevicetreemodel.c b/src/disks/gdudevicetreemodel.c
index 93da647..60e0af2 100644
--- a/src/disks/gdudevicetreemodel.c
+++ b/src/disks/gdudevicetreemodel.c
@@ -435,7 +435,7 @@ gdu_device_tree_model_constructed (GObject *object)
   GduDeviceTreeModel *model = GDU_DEVICE_TREE_MODEL (object);
   GType types[GDU_DEVICE_TREE_MODEL_N_COLUMNS];
 
-  G_STATIC_ASSERT (11 == GDU_DEVICE_TREE_MODEL_N_COLUMNS);
+  G_STATIC_ASSERT (12 == GDU_DEVICE_TREE_MODEL_N_COLUMNS);
 
   types[0] = G_TYPE_STRING;
   types[1] = G_TYPE_BOOLEAN;
@@ -443,11 +443,12 @@ gdu_device_tree_model_constructed (GObject *object)
   types[3] = G_TYPE_ICON;
   types[4] = G_TYPE_STRING;
   types[5] = G_TYPE_DBUS_OBJECT;
-  types[6] = G_TYPE_BOOLEAN;
-  types[7] = G_TYPE_UINT;
-  types[8] = G_TYPE_BOOLEAN;
-  types[9] = GDU_TYPE_POWER_STATE_FLAGS;
-  types[10] = G_TYPE_UINT64;
+  types[6] = UDISKS_TYPE_BLOCK;
+  types[7] = G_TYPE_BOOLEAN;
+  types[8] = G_TYPE_UINT;
+  types[9] = G_TYPE_BOOLEAN;
+  types[10] = GDU_TYPE_POWER_STATE_FLAGS;
+  types[11] = G_TYPE_UINT64;
   gtk_tree_store_set_column_types (GTK_TREE_STORE (model),
                                    GDU_DEVICE_TREE_MODEL_N_COLUMNS,
                                    types);
@@ -882,6 +883,7 @@ update_drive (GduDeviceTreeModel *model,
   UDisksDrive *drive = NULL;
   UDisksDriveAta *ata = NULL;
   UDisksObjectInfo *info = NULL;
+  UDisksBlock *block = NULL;
   gchar *s = NULL;
   gchar *sort_key = NULL;
   gboolean warning = FALSE;
@@ -902,6 +904,8 @@ update_drive (GduDeviceTreeModel *model,
   drive = udisks_object_peek_drive (object);
   ata = udisks_object_peek_drive_ata (object);
 
+  block = udisks_client_get_block_for_drive (model->client, drive, FALSE); /* get_physical */
+
   sort_key = g_strdup_printf ("00_drives_1_%s", udisks_drive_get_sort_key (drive));
 
   if (ata != NULL)
@@ -952,6 +956,7 @@ update_drive (GduDeviceTreeModel *model,
                       GDU_DEVICE_TREE_MODEL_COLUMN_JOBS_RUNNING, jobs_running,
                       GDU_DEVICE_TREE_MODEL_COLUMN_PULSE, pulse,
                       GDU_DEVICE_TREE_MODEL_COLUMN_SIZE, size,
+                      GDU_DEVICE_TREE_MODEL_COLUMN_BLOCK, block,
                       -1);
 
   /* update spinner, if jobs are running */
@@ -964,6 +969,7 @@ update_drive (GduDeviceTreeModel *model,
     }
 
  out:
+  g_clear_object (&block);
   if (info != NULL)
     udisks_object_info_unref (info);
   g_free (sort_key);
@@ -1161,6 +1167,7 @@ update_mdraid (GduDeviceTreeModel *model,
                       GDU_DEVICE_TREE_MODEL_COLUMN_JOBS_RUNNING, jobs_running,
                       GDU_DEVICE_TREE_MODEL_COLUMN_PULSE, pulse,
                       GDU_DEVICE_TREE_MODEL_COLUMN_SIZE, size,
+                      GDU_DEVICE_TREE_MODEL_COLUMN_BLOCK, block,
                       -1);
 
   /* update spinner, if jobs are running */
@@ -1425,6 +1432,7 @@ update_block (GduDeviceTreeModel  *model,
                       GDU_DEVICE_TREE_MODEL_COLUMN_JOBS_RUNNING, jobs_running,
                       GDU_DEVICE_TREE_MODEL_COLUMN_PULSE, pulse,
                       GDU_DEVICE_TREE_MODEL_COLUMN_SIZE, size,
+                      GDU_DEVICE_TREE_MODEL_COLUMN_BLOCK, block,
                       -1);
 
   /* update spinner, if jobs are running */
diff --git a/src/disks/gdudevicetreemodel.h b/src/disks/gdudevicetreemodel.h
index 0b9efab..2184067 100644
--- a/src/disks/gdudevicetreemodel.h
+++ b/src/disks/gdudevicetreemodel.h
@@ -27,6 +27,7 @@ enum
   GDU_DEVICE_TREE_MODEL_COLUMN_ICON,
   GDU_DEVICE_TREE_MODEL_COLUMN_NAME,
   GDU_DEVICE_TREE_MODEL_COLUMN_OBJECT,
+  GDU_DEVICE_TREE_MODEL_COLUMN_BLOCK,
   GDU_DEVICE_TREE_MODEL_COLUMN_WARNING,
   GDU_DEVICE_TREE_MODEL_COLUMN_PULSE,
   GDU_DEVICE_TREE_MODEL_COLUMN_JOBS_RUNNING,
diff --git a/src/disks/gduselectdiskdialog.c b/src/disks/gduselectdiskdialog.c
index 06abd51..3d33f58 100644
--- a/src/disks/gduselectdiskdialog.c
+++ b/src/disks/gduselectdiskdialog.c
@@ -28,6 +28,7 @@ typedef struct
   GduApplication *application;
   GtkBuilder *builder;
 
+  guint64 size;
   GduSelectDiskFlags flags;
 
   GtkWidget *dialog;
@@ -37,6 +38,7 @@ typedef struct
 
   GduDeviceTreeModel *model;
 
+  GList *ret;
 } DialogData;
 
 static const struct {
@@ -45,7 +47,6 @@ static const struct {
 } widget_mapping[] = {
   {G_STRUCT_OFFSET (DialogData, scrolledwindow), "scrolledwindow"},
   {G_STRUCT_OFFSET (DialogData, treeview), "treeview"},
-
   {0, NULL}
 };
 
@@ -160,25 +161,31 @@ on_tree_selection_changed (GtkTreeSelection *tree_selection,
 }
 
 static gboolean
-dont_select_headings (GtkTreeSelection *selection,
+treeview_select_func (GtkTreeSelection *selection,
                       GtkTreeModel     *model,
                       GtkTreePath      *path,
                       gboolean          selected,
                       gpointer          user_data)
 {
+  /* DialogData *data = user_data; */
+  gboolean selectable = FALSE;
+  gboolean is_heading = FALSE;
   GtkTreeIter iter;
-  gboolean is_heading;
 
-  gtk_tree_model_get_iter (model,
-                           &iter,
-                           path);
+  gtk_tree_model_get_iter (model, &iter, path);
   gtk_tree_model_get (model,
                       &iter,
-                      GDU_DEVICE_TREE_MODEL_COLUMN_IS_HEADING,
-                      &is_heading,
+                      GDU_DEVICE_TREE_MODEL_COLUMN_IS_HEADING, &is_heading,
                       -1);
 
-  return !is_heading;
+  /* headers are never selectable */
+  if (is_heading)
+    goto out;
+
+  selectable = TRUE;
+
+ out:
+  return selectable;
 }
 
 static void
@@ -248,7 +255,7 @@ init_dialog (DialogData *data)
   gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview)));
 
   gtk_tree_selection_set_select_function (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview)),
-                                          dont_select_headings,
+                                          treeview_select_func,
                                           data,
                                           NULL); /* GDestroyNotify */
   g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview)),
@@ -263,6 +270,17 @@ init_dialog (DialogData *data)
                     data);
   gtk_tree_view_expand_all (GTK_TREE_VIEW (data->treeview));
 
+
+  /* Dialog title */
+  if (data->flags & GDU_SELECT_DISK_FLAGS_ALLOW_MULTIPLE)
+    {
+      gtk_window_set_title (GTK_WINDOW (data->dialog), C_("select-disk-dialog", "Select Disks"));
+    }
+  else
+    {
+      gtk_window_set_title (GTK_WINDOW (data->dialog), C_("select-disk-dialog", "Select Disk"));
+    }
+
   update_dialog (data);
 }
 
@@ -276,10 +294,28 @@ on_client_changed (UDisksClient   *client,
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+static void
+add_block_func (GtkTreeModel *model,
+                GtkTreePath  *path,
+                GtkTreeIter  *iter,
+                gpointer      user_data)
+{
+  DialogData *data = user_data;
+  UDisksBlock *block = NULL;
+
+  gtk_tree_model_get (model, iter,
+                      GDU_DEVICE_TREE_MODEL_COLUMN_BLOCK, &block,
+                      -1);
+  if (block != NULL)
+    {
+      data->ret = g_list_prepend (data->ret, block); /* adopts block */
+    }
+}
 
 GList *
 gdu_select_disk_dialog_show (GduApplication     *application,
                              GtkWindow          *parent_window,
+                             guint64             size,
                              GduSelectDiskFlags  flags)
 {
   GList *ret = NULL;
@@ -290,6 +326,7 @@ gdu_select_disk_dialog_show (GduApplication     *application,
   data->ref_count = 1;
   data->application = g_object_ref (application);
   data->client = gdu_application_get_client (data->application);
+  data->size = size;
   data->flags = flags;
 
   data->dialog = GTK_WIDGET (gdu_application_new_widget (data->application,
@@ -302,11 +339,6 @@ gdu_select_disk_dialog_show (GduApplication     *application,
       *p = gtk_builder_get_object (data->builder, widget_mapping[n].name);
     }
 
-  if (data->flags & GDU_SELECT_DISK_FLAGS_ALLOW_MULTIPLE)
-    gtk_window_set_title (GTK_WINDOW (data->dialog), C_("select-disk-dialog", "Select Disks"));
-  else
-    gtk_window_set_title (GTK_WINDOW (data->dialog), C_("select-disk-dialog", "Select Disk"));
-
   gtk_window_set_transient_for (GTK_WINDOW (data->dialog), parent_window);
 
   init_dialog (data);
@@ -322,7 +354,13 @@ gdu_select_disk_dialog_show (GduApplication     *application,
           break;
 
         case GTK_RESPONSE_OK:
-          g_print ("TODO: set ret\n");
+          gtk_tree_selection_selected_foreach (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview)),
+                                               add_block_func,
+                                               data);
+          ret = g_list_reverse (data->ret);
+          /* TODO: ensure @ret is sorted according to sort function.
+           *       Or does selected_foreach() guarantee that?
+           */
           goto out;
 
         default:
diff --git a/src/disks/gduselectdiskdialog.h b/src/disks/gduselectdiskdialog.h
index 13f097e..2a2c708 100644
--- a/src/disks/gduselectdiskdialog.h
+++ b/src/disks/gduselectdiskdialog.h
@@ -17,6 +17,7 @@ G_BEGIN_DECLS
 
 GList *gdu_select_disk_dialog_show (GduApplication     *application,
                                     GtkWindow          *parent_window,
+                                    guint64             size,
                                     GduSelectDiskFlags  flags);
 
 G_END_DECLS



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