[gnome-disk-utility/wip/mdraid] Add dialog for RAID disks



commit 61243f359d202f18c23d11f1d25c8899bef53b07
Author: David Zeuthen <zeuthen gmail com>
Date:   Fri Sep 14 13:07:28 2012 -0400

    Add dialog for RAID disks
    
    http://people.freedesktop.org/~david/gnome-disks-mdraid-20120914-1.png
    
    The toolbar buttons don't do anything yet.
    
    Signed-off-by: David Zeuthen <zeuthen gmail com>

 data/ui/Makefile.am              |    1 +
 data/ui/disks.ui                 |   15 +
 data/ui/md-raid-disks-dialog.ui  |  128 +++++++
 src/disks/Makefile.am            |    1 +
 src/disks/gdumdraiddisksdialog.c |  679 ++++++++++++++++++++++++++++++++++++++
 src/disks/gdumdraiddisksdialog.h |   23 ++
 src/disks/gduwindow.c            |   35 ++
 7 files changed, 882 insertions(+), 0 deletions(-)
---
diff --git a/data/ui/Makefile.am b/data/ui/Makefile.am
index 9e7d7c4..bb68fb7 100644
--- a/data/ui/Makefile.am
+++ b/data/ui/Makefile.am
@@ -24,6 +24,7 @@ ui_DATA = 				\
 	app-menu.ui			\
 	benchmark-dialog.ui		\
 	disk-settings-dialog.ui		\
+	md-raid-disks-dialog.ui		\
 	$(NULL)
 
 EXTRA_DIST = 				\
diff --git a/data/ui/disks.ui b/data/ui/disks.ui
index 076c813..e34e9e5 100644
--- a/data/ui/disks.ui
+++ b/data/ui/disks.ui
@@ -1669,6 +1669,21 @@
         <property name="label" translatable="yes">Wake-Up from Standby</property>
       </object>
     </child>
+    <child>
+      <object class="GtkSeparatorMenuItem" id="generic-drive-menu-item-mdraid-sep-1">
+        <property name="use_action_appearance">False</property>
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkMenuItem" id="generic-drive-menu-item-mdraid-disks">
+        <property name="use_action_appearance">False</property>
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">RAID Disks...</property>
+      </object>
+    </child>
   </object>
   <object class="GtkMenu" id="generic-menu">
     <property name="visible">True</property>
diff --git a/data/ui/md-raid-disks-dialog.ui b/data/ui/md-raid-disks-dialog.ui
new file mode 100644
index 0000000..3585a4d
--- /dev/null
+++ b/data/ui/md-raid-disks-dialog.ui
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkDialog" id="dialog">
+    <property name="width_request">600</property>
+    <property name="height_request">500</property>
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">RAID Disks</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="close-button">
+                <property name="label">gtk-close</property>
+                <property name="use_action_appearance">False</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkScrolledWindow" id="scrolledwindow">
+                <property name="width_request">300</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="treeview">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="show_expanders">False</property>
+                    <property name="level_indentation">12</property>
+                    <child internal-child="selection">
+                      <object class="GtkTreeSelection" id="treeview-selection1"/>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolbar" id="toolbar">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="icon_size">1</property>
+                <child>
+                  <object class="GtkToolButton" id="add-toolbutton">
+                    <property name="use_action_appearance">False</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="label" translatable="yes">Add Disk...</property>
+                    <property name="use_underline">True</property>
+                    <property name="icon_name">list-add-symbolic</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="homogeneous">True</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkToolButton" id="remove-toolbutton">
+                    <property name="use_action_appearance">False</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="label" translatable="yes">Remove Disk...</property>
+                    <property name="use_underline">True</property>
+                    <property name="icon_name">list-remove-symbolic</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="homogeneous">True</property>
+                  </packing>
+                </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">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-7">close-button</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/src/disks/Makefile.am b/src/disks/Makefile.am
index c0226d9..aee0ece 100644
--- a/src/disks/Makefile.am
+++ b/src/disks/Makefile.am
@@ -47,6 +47,7 @@ gnome_disks_SOURCES = 							\
 	gduestimator.h			gduestimator.c			\
 	gduchangepassphrasedialog.h	gduchangepassphrasedialog.c	\
 	gdudisksettingsdialog.h		gdudisksettingsdialog.c		\
+	gdumdraiddisksdialog.h		gdumdraiddisksdialog.c		\
 	$(enum_built_sources)						\
 	$(NULL)
 
diff --git a/src/disks/gdumdraiddisksdialog.c b/src/disks/gdumdraiddisksdialog.c
new file mode 100644
index 0000000..83756b9
--- /dev/null
+++ b/src/disks/gdumdraiddisksdialog.c
@@ -0,0 +1,679 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2008-2012 Red Hat, Inc.
+ *
+ * Licensed under GPL version 2 or later.
+ *
+ * Author: David Zeuthen <zeuthen gmail com>
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <math.h>
+
+#include "gduapplication.h"
+#include "gduwindow.h"
+#include "gdumdraiddisksdialog.h"
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+  volatile gint ref_count;
+
+  UDisksClient *client;
+  UDisksObject *object;
+  UDisksMDRaid *mdraid;
+  guint num_devices;
+
+  GduWindow *window;
+  GtkBuilder *builder;
+
+  GtkWidget *dialog;
+
+  GtkWidget *close_button;
+  GtkWidget *scrolledwindow;
+  GtkWidget *treeview;
+  GtkWidget *toolbar;
+  GtkWidget *add_toolbutton;
+  GtkWidget *remove_toolbutton;
+
+  GtkListStore *store;
+} DialogData;
+
+static const struct {
+  goffset offset;
+  const gchar *name;
+} widget_mapping[] = {
+  {G_STRUCT_OFFSET (DialogData, close_button), "close-button"},
+
+  {G_STRUCT_OFFSET (DialogData, scrolledwindow), "scrolledwindow"},
+  {G_STRUCT_OFFSET (DialogData, treeview), "treeview"},
+  {G_STRUCT_OFFSET (DialogData, toolbar), "toolbar"},
+  {G_STRUCT_OFFSET (DialogData, add_toolbutton), "add-toolbutton"},
+  {G_STRUCT_OFFSET (DialogData, remove_toolbutton), "remove-toolbutton"},
+
+  {0, NULL}
+};
+
+static void update_dialog (DialogData *data);
+
+
+static void on_client_changed (UDisksClient  *client,
+                               gpointer       user_data);
+
+enum
+{
+  COLUMN_SLOT,
+  COLUMN_BLOCK,
+  COLUMN_STATE,
+  COLUMN_NUM_ERRORS,
+  COLUMN_EXPANSION,
+};
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+G_GNUC_UNUSED static DialogData *
+dialog_data_ref (DialogData *data)
+{
+  g_atomic_int_inc (&data->ref_count);
+  return data;
+}
+
+static void
+dialog_data_unref (DialogData *data)
+{
+  if (g_atomic_int_dec_and_test (&data->ref_count))
+    {
+      if (data->dialog != NULL)
+        {
+          gtk_widget_hide (data->dialog);
+          gtk_widget_destroy (data->dialog);
+          data->dialog = NULL;
+        }
+
+      g_signal_handlers_disconnect_by_func (data->client,
+                                            G_CALLBACK (on_client_changed),
+                                            data);
+
+      g_clear_object (&data->object);
+      g_clear_object (&data->window);
+      g_clear_object (&data->builder);
+
+      g_clear_object (&data->store);
+
+      g_free (data);
+    }
+}
+
+static void
+dialog_data_close (DialogData *data)
+{
+  gtk_dialog_response (GTK_DIALOG (data->dialog), GTK_RESPONSE_CANCEL);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+update_dialog (DialogData *data)
+{
+  GVariantIter iter;
+  gint disk_slot;
+  const gchar *disk_block_objpath;
+  const gchar *disk_state;
+  guint64 disk_num_errors;
+  GtkTreeIter titer;
+  UDisksBlock *selected_block = NULL;
+  GtkTreeIter *iter_to_select = NULL;
+
+  /* ---------- */
+
+  /* preserve focus */
+  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,
+                          COLUMN_BLOCK, &selected_block,
+                          -1);
+    }
+  gtk_list_store_clear (data->store);
+  g_variant_iter_init (&iter, udisks_mdraid_get_active_devices (data->mdraid));
+  while (g_variant_iter_next (&iter, "(&oi&sta{sv})",
+                              &disk_block_objpath,
+                              &disk_slot,
+                              &disk_state,
+                              &disk_num_errors,
+                              NULL)) /* expansion */
+    {
+      UDisksObject *object = NULL;
+      UDisksBlock *block = NULL;
+      GtkTreeIter inserted_iter;
+
+      object = udisks_client_peek_object (data->client, disk_block_objpath);
+      if (object != NULL)
+        {
+          block = udisks_object_peek_block (object);
+        }
+
+      gtk_list_store_insert_with_values (data->store,
+                                         &inserted_iter, /* out_iter */
+                                         -1,   /* position */
+                                         COLUMN_SLOT, disk_slot,
+                                         COLUMN_BLOCK, block,
+                                         COLUMN_STATE, disk_state,
+                                         COLUMN_NUM_ERRORS, (guint64) disk_num_errors,
+                                         -1);
+      if (block == selected_block)
+        iter_to_select = gtk_tree_iter_copy (&inserted_iter);
+    }
+  if (iter_to_select == NULL)
+    {
+      GtkTreeIter first_iter;
+      if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (data->store), &first_iter))
+        iter_to_select = gtk_tree_iter_copy (&first_iter);
+    }
+  if (iter_to_select != NULL)
+    {
+      gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview)),
+                                      iter_to_select);
+      gtk_tree_iter_free (iter_to_select);
+    }
+  g_clear_object (&selected_block);
+}
+
+G_GNUC_UNUSED static void
+on_property_changed (GObject     *object,
+                     GParamSpec  *pspec,
+                     gpointer     user_data)
+{
+  DialogData *data = user_data;
+  update_dialog (data);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+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,
+                      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
+pixbuf_cell_func (GtkTreeViewColumn *column,
+                  GtkCellRenderer   *renderer,
+                  GtkTreeModel      *model,
+                  GtkTreeIter       *iter,
+                  gpointer           user_data)
+{
+  DialogData *data = user_data;
+  UDisksBlock *block = NULL;
+  GIcon *icon = NULL;
+
+  gtk_tree_model_get (model,
+                      iter,
+                      COLUMN_BLOCK, &block,
+                      -1);
+
+  if (block == NULL)
+    {
+      icon = NULL;
+    }
+  else
+    {
+      UDisksDrive *drive;
+      drive = udisks_client_get_drive_for_block (data->client, block);
+      if (drive != NULL)
+        {
+          udisks_client_get_drive_info (data->client,
+                                        drive,
+                                        NULL,  /* out_name */
+                                        NULL,  /* out_description */
+                                        &icon, /* out_drive_icon */
+                                        NULL,  /* out_media_description */
+                                        NULL); /* out_media_icon */
+          g_object_unref (drive);
+        }
+      else
+        {
+          icon = g_themed_icon_new ("drive-removable-media"); /* for now */
+        }
+    }
+
+  g_object_set (renderer,
+                "gicon", icon,
+                NULL);
+
+  g_clear_object (&icon);
+  g_clear_object (&block);
+}
+
+static void
+name_cell_func (GtkTreeViewColumn *column,
+                GtkCellRenderer   *renderer,
+                GtkTreeModel      *model,
+                GtkTreeIter       *iter,
+                gpointer           user_data)
+{
+  DialogData *data = user_data;
+  UDisksBlock *block = NULL;
+  gchar *markup = NULL;
+  gchar *s;
+
+  gtk_tree_model_get (model,
+                      iter,
+                      COLUMN_BLOCK, &block,
+                      -1);
+
+  if (block == NULL)
+    {
+      /* Translators: Shown in 'Disk' column when there is no disk for the position in question */
+      markup = g_strdup_printf ("<i>%s</i>",
+                                C_("mdraid-disks", "None"));
+    }
+  else
+    {
+      UDisksDrive *drive = NULL;
+      gchar *name = NULL;
+      gchar *desc = NULL;
+
+      drive = udisks_client_get_drive_for_block (data->client, block);
+      if (drive != NULL)
+        {
+          UDisksPartition *partition = NULL;
+          UDisksObject *object = NULL;
+
+          udisks_client_get_drive_info (data->client,
+                                        drive,
+                                        &name,  /* out_name */
+                                        &desc,  /* out_description */
+                                        NULL,   /* out_drive_icon */
+                                        NULL,   /* out_media_description */
+                                        NULL);  /* out_media_icon */
+
+          object = (UDisksObject *) g_dbus_interface_get_object (G_DBUS_INTERFACE (block));
+          if (object != NULL)
+            partition = udisks_object_peek_partition (object);
+
+          if (partition != NULL)
+            {
+              s = g_strdup_printf (C_("mdraid-disks", "Partition %d of %s"),
+                                   udisks_partition_get_number (partition),
+                                   desc);
+              g_free (desc); desc = s;
+            }
+
+          s = g_strdup_printf ("%s â %s", name, udisks_block_get_preferred_device (block));
+          g_free (name); name = s;
+
+          g_object_unref (drive);
+        }
+      else
+        {
+          s = udisks_client_get_size_for_display (data->client, udisks_block_get_size (block), FALSE, FALSE);
+          /* Translators: Shown in list for a disk/member that is not a drive.
+           *              The %s is the size (e.g. "42.0 GB").
+           */
+          desc = g_strdup_printf (C_("mdraid-disks", "%s Block Device"), s);
+          g_free (s);
+          name = udisks_block_dup_preferred_device (block);
+        }
+
+      /* TODO: once https://bugzilla.gnome.org/show_bug.cgi?id=657194 is resolved, use that instead
+       * of hard-coding the color
+       */
+      markup = g_strdup_printf ("%s\n"
+                                "<small><span foreground=\"#555555\">%s</span></small>",
+                                desc,
+                                name);
+      g_free (desc);
+      g_free (name);
+    }
+
+  g_object_set (renderer,
+                "markup", markup,
+                NULL);
+
+  g_free (markup);
+  g_clear_object (&block);
+}
+
+static void
+num_errors_cell_func (GtkTreeViewColumn *column,
+                      GtkCellRenderer   *renderer,
+                      GtkTreeModel      *model,
+                      GtkTreeIter       *iter,
+                      gpointer           user_data)
+{
+  /* DialogData *data = user_data; */
+  UDisksBlock *block = NULL;
+  guint64 num_errors = 0;
+  gchar *markup = NULL;
+
+  gtk_tree_model_get (model,
+                      iter,
+                      COLUMN_BLOCK, &block,
+                      COLUMN_NUM_ERRORS, &num_errors,
+                      -1);
+
+  if (block == NULL)
+    {
+      markup = g_strdup ("â");
+    }
+  else
+    {
+      markup = g_strdup_printf ("%" G_GUINT64_FORMAT, num_errors);
+    }
+
+  g_object_set (renderer,
+                "markup", markup,
+                NULL);
+
+  g_free (markup);
+  g_clear_object (&block);
+}
+
+static void
+state_cell_func (GtkTreeViewColumn *column,
+                 GtkCellRenderer   *renderer,
+                 GtkTreeModel      *model,
+                 GtkTreeIter       *iter,
+                 gpointer           user_data)
+{
+  /* DialogData *data = user_data; */
+  gchar *state = NULL;
+  gchar *markup = NULL;
+
+  gtk_tree_model_get (model,
+                      iter,
+                      COLUMN_STATE, &state,
+                      -1);
+
+  if (state == NULL || strlen (state) == 0)
+    {
+      markup = g_strdup ("â");
+    }
+  else if (g_strcmp0 (state, "faulty") == 0)
+    {
+      /* Translators: MD-RAID member state for 'faulty' */
+      markup = g_strdup_printf ("<span foreground=\"#ff0000\">%s</span>\n",
+                                C_("mdraid-disks-state", "FAILING"));
+    }
+  else if (g_strcmp0 (state, "in_sync") == 0)
+    {
+      /* Translators: MD-RAID member state for 'in_sync' */
+      markup = g_strdup (C_("mdraid-disks-state", "In Sync"));
+    }
+  else if (g_strcmp0 (state, "writemostly") == 0)
+    {
+      /* Translators: MD-RAID member state for 'writemostly' */
+      markup = g_strdup (C_("mdraid-disks-state", "In Sync (Write-Mostly)"));
+    }
+  else if (g_strcmp0 (state, "blocked") == 0)
+    {
+      /* Translators: MD-RAID member state for 'blocked' */
+      markup = g_strdup (C_("mdraid-disks-state", "Blocked"));
+    }
+  else if (g_strcmp0 (state, "spare") == 0)
+    {
+      /* Translators: MD-RAID member state for 'spare' */
+      markup = g_strdup (C_("mdraid-disks-state", "Spare"));
+    }
+  else
+    {
+      /* Translators: MD-RAID member state unknown. The %s is the raw state from sysfs */
+      markup = g_strdup_printf (C_("mdraid-disks-state", "Unknown (%s)"), state);
+    }
+
+  g_object_set (renderer,
+                "markup", markup,
+                NULL);
+
+  g_free (markup);
+  g_free (state);
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gint
+row_sort_func (GtkTreeModel *model,
+               GtkTreeIter *a,
+               GtkTreeIter *b,
+               gpointer user_data)
+{
+  gint ret;
+  gint slot_a, slot_b;
+  UDisksBlock *block_a = NULL, *block_b = NULL;
+
+  gtk_tree_model_get (model, a,
+                      COLUMN_SLOT, &slot_a,
+                      COLUMN_BLOCK, &block_a,
+                      -1);
+  gtk_tree_model_get (model, a,
+                      COLUMN_SLOT, &slot_b,
+                      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
+init_dialog (DialogData *data)
+{
+  GtkTreeViewColumn *column;
+  GtkCellRenderer *renderer;
+  GtkStyleContext *context;
+
+  context = gtk_widget_get_style_context (data->scrolledwindow);
+  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
+  context = gtk_widget_get_style_context (data->toolbar);
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
+  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
+  gtk_widget_set_name (data->toolbar, "mdraid-disks-toolbar");
+
+  data->store = gtk_list_store_new (5,
+                                    G_TYPE_INT,
+                                    UDISKS_TYPE_BLOCK,
+                                    G_TYPE_STRING,
+                                    G_TYPE_UINT64,
+                                    G_TYPE_VARIANT);
+
+  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),
+                                        COLUMN_SLOT,
+                                        GTK_SORT_ASCENDING);
+  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (data->store),
+                                   COLUMN_SLOT,
+                                   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,
+                                           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_DND,
+                NULL);
+  gtk_tree_view_column_pack_start (column, renderer, FALSE);
+  gtk_tree_view_column_set_cell_data_func (column,
+                                           renderer,
+                                           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,
+                NULL);
+  gtk_tree_view_column_set_cell_data_func (column,
+                                           renderer,
+                                           name_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 state of the disk in the RAID array */
+  gtk_tree_view_column_set_title (column, C_("mdraid-disks", "State"));
+  /* -- */
+  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,
+                                           state_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 number of read errors of the disk in the RAID array */
+  gtk_tree_view_column_set_title (column, C_("mdraid-disks", "Errors"));
+  /* -- */
+  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,
+                                           num_errors_cell_func,
+                                           data,  /* user_data */
+                                           NULL); /* user_data GDestroyNotify */
+
+  g_signal_connect (data->client,
+                    "changed",
+                    G_CALLBACK (on_client_changed),
+                    data);
+
+  update_dialog (data);
+}
+
+static void
+on_client_changed (UDisksClient   *client,
+                   gpointer        user_data)
+{
+  DialogData *data = user_data;
+  update_dialog (data);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+
+void
+gdu_mdraid_disks_dialog_show (GduWindow    *window,
+                              UDisksObject *object)
+{
+  DialogData *data;
+  guint n;
+
+  data = g_new0 (DialogData, 1);
+  data->ref_count = 1;
+  data->object = g_object_ref (object);
+  data->mdraid = udisks_object_peek_mdraid (data->object);
+  data->num_devices = udisks_mdraid_get_num_devices (data->mdraid);
+  data->window = g_object_ref (window);
+  data->client = gdu_window_get_client (data->window);
+
+  data->dialog = GTK_WIDGET (gdu_application_new_widget (gdu_window_get_application (window),
+                                                         "md-raid-disks-dialog.ui",
+                                                         "dialog",
+                                                         &data->builder));
+  for (n = 0; widget_mapping[n].name != NULL; n++)
+    {
+      gpointer *p = (gpointer *) ((char *) data + widget_mapping[n].offset);
+      *p = gtk_builder_get_object (data->builder, widget_mapping[n].name);
+    }
+
+  gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (window));
+
+  init_dialog (data);
+
+  update_dialog (data);
+
+  while (TRUE)
+    {
+      gint response;
+      response = gtk_dialog_run (GTK_DIALOG (data->dialog));
+      /* Keep in sync with .ui file */
+      switch (response)
+        {
+        case GTK_RESPONSE_CLOSE: /* Close */
+          goto out;
+          break;
+
+        default:
+          goto out;
+        }
+    }
+ out:
+  dialog_data_close (data);
+  dialog_data_unref (data);
+}
+
diff --git a/src/disks/gdumdraiddisksdialog.h b/src/disks/gdumdraiddisksdialog.h
new file mode 100644
index 0000000..523ac5f
--- /dev/null
+++ b/src/disks/gdumdraiddisksdialog.h
@@ -0,0 +1,23 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2008-2012 Red Hat, Inc.
+ *
+ * Licensed under GPL version 2 or later.
+ *
+ * Author: David Zeuthen <zeuthen gmail com>
+ */
+
+#ifndef __GDU_MDRAID_DISKS_DIALOG_H__
+#define __GDU_MDRAID_DISKS_DIALOG_H__
+
+#include <gtk/gtk.h>
+#include "gdutypes.h"
+
+G_BEGIN_DECLS
+
+void   gdu_mdraid_disks_dialog_show (GduWindow    *window,
+                                     UDisksObject *object);
+
+G_END_DECLS
+
+#endif /* __GDU_MDRAID_DISKS_DIALOG_H__ */
diff --git a/src/disks/gduwindow.c b/src/disks/gduwindow.c
index a4d5aa6..502b4ec 100644
--- a/src/disks/gduwindow.c
+++ b/src/disks/gduwindow.c
@@ -37,6 +37,7 @@
 #include "gdurestorediskimagedialog.h"
 #include "gduchangepassphrasedialog.h"
 #include "gdudisksettingsdialog.h"
+#include "gdumdraiddisksdialog.h"
 
 /* Keep in sync with tabs in disks.ui file */
 typedef enum
@@ -111,6 +112,9 @@ struct _GduWindow
   GtkWidget *generic_drive_menu_item_drive_sep_2;
   GtkWidget *generic_drive_menu_item_standby_now;
   GtkWidget *generic_drive_menu_item_resume_now;
+  /* MDRaid-specific items */
+  GtkWidget *generic_drive_menu_item_mdraid_sep_1;
+  GtkWidget *generic_drive_menu_item_mdraid_disks;
 
   GtkWidget *generic_menu;
   GtkWidget *generic_menu_item_configure_fstab;
@@ -201,6 +205,9 @@ static const struct {
   {G_STRUCT_OFFSET (GduWindow, generic_drive_menu_item_drive_sep_2), "generic-drive-menu-item-drive-sep-2"},
   {G_STRUCT_OFFSET (GduWindow, generic_drive_menu_item_standby_now), "generic-drive-menu-item-standby-now"},
   {G_STRUCT_OFFSET (GduWindow, generic_drive_menu_item_resume_now), "generic-drive-menu-item-resume-now"},
+  /* MDRaid-specific items */
+  {G_STRUCT_OFFSET (GduWindow, generic_drive_menu_item_mdraid_sep_1), "generic-drive-menu-item-mdraid-sep-1"},
+  {G_STRUCT_OFFSET (GduWindow, generic_drive_menu_item_mdraid_disks), "generic-drive-menu-item-mdraid-disks"},
 
   {G_STRUCT_OFFSET (GduWindow, generic_menu), "generic-menu"},
   {G_STRUCT_OFFSET (GduWindow, generic_menu_item_configure_fstab), "generic-menu-item-configure-fstab"},
@@ -266,6 +273,7 @@ typedef enum
   SHOW_FLAGS_DRIVE_MENU_DISK_SETTINGS         = (1<<5),
   SHOW_FLAGS_DRIVE_MENU_STANDBY_NOW           = (1<<6),
   SHOW_FLAGS_DRIVE_MENU_RESUME_NOW            = (1<<7),
+  SHOW_FLAGS_DRIVE_MENU_MDRAID_DISKS          = (1<<8),
 } ShowFlagsDriveMenu;
 
 typedef enum {
@@ -345,6 +353,8 @@ static void on_generic_drive_menu_item_restore_disk_image (GtkMenuItem *menu_ite
                                                            gpointer   user_data);
 static void on_generic_drive_menu_item_benchmark (GtkMenuItem *menu_item,
                                                   gpointer   user_data);
+static void on_generic_drive_menu_item_mdraid_disks (GtkMenuItem *menu_item,
+                                                     gpointer   user_data);
 
 static void on_generic_menu_item_configure_fstab (GtkMenuItem *menu_item,
                                                   gpointer   user_data);
@@ -500,6 +510,8 @@ update_for_show_flags (GduWindow *window,
                             show_flags->drive_menu & SHOW_FLAGS_DRIVE_MENU_RESTORE_DISK_IMAGE);
   gtk_widget_set_sensitive (GTK_WIDGET (window->generic_drive_menu_item_benchmark),
                             show_flags->drive_menu & SHOW_FLAGS_DRIVE_MENU_BENCHMARK);
+  gtk_widget_set_sensitive (GTK_WIDGET (window->generic_drive_menu_item_mdraid_disks),
+                            show_flags->drive_menu & SHOW_FLAGS_DRIVE_MENU_MDRAID_DISKS);
 
   gtk_widget_set_sensitive (GTK_WIDGET (window->generic_menu_item_configure_fstab),
                             show_flags->volume_menu & SHOW_FLAGS_VOLUME_MENU_CONFIGURE_FSTAB);
@@ -1267,6 +1279,10 @@ gdu_window_constructed (GObject *object)
                     "activate",
                     G_CALLBACK (on_generic_drive_menu_item_benchmark),
                     window);
+  g_signal_connect (window->generic_drive_menu_item_mdraid_disks,
+                    "activate",
+                    G_CALLBACK (on_generic_drive_menu_item_mdraid_disks),
+                    window);
 
   /* volume menu */
   g_signal_connect (window->generic_menu_item_configure_fstab,
@@ -1927,6 +1943,7 @@ update_device_page_for_mdraid (GduWindow      *window,
     {
       device_desc = get_device_file_for_display (block);
       show_flags->drive_buttons |= SHOW_FLAGS_DRIVE_BUTTONS_RAID_STOP;
+      show_flags->drive_menu |= SHOW_FLAGS_DRIVE_MENU_MDRAID_DISKS;
     }
   else
     {
@@ -2164,6 +2181,12 @@ update_device_page_for_mdraid (GduWindow      *window,
 
   /* -------------------------------------------------- */
 
+  /* Show MDRaid-specific items */
+  gtk_widget_show (GTK_WIDGET (window->generic_drive_menu_item_mdraid_sep_1));
+  gtk_widget_show (GTK_WIDGET (window->generic_drive_menu_item_mdraid_disks));
+
+  /* -------------------------------------------------- */
+
   g_list_free_full (members, g_object_unref);
   g_list_free_full (jobs, g_object_unref);
   g_free (level_desc);
@@ -2937,6 +2960,10 @@ update_device_page (GduWindow      *window,
   gtk_widget_hide (GTK_WIDGET (window->generic_drive_menu_item_standby_now));
   gtk_widget_hide (GTK_WIDGET (window->generic_drive_menu_item_resume_now));
 
+  /* Hide all MDRaid-specific items - will be turned on again in update_device_page_for_mdraid() */
+  gtk_widget_hide (GTK_WIDGET (window->generic_drive_menu_item_mdraid_sep_1));
+  gtk_widget_hide (GTK_WIDGET (window->generic_drive_menu_item_mdraid_disks));
+
   /* always show the generic toolbar item */
   gtk_action_set_visible (GTK_ACTION (gtk_builder_get_object (window->builder,
                                                               "devtab-action-generic")), TRUE);
@@ -3171,6 +3198,14 @@ on_generic_drive_menu_item_disk_settings (GtkMenuItem *menu_item,
   gdu_disk_settings_dialog_show (window, window->current_object);
 }
 
+static void
+on_generic_drive_menu_item_mdraid_disks (GtkMenuItem *menu_item,
+                                         gpointer     user_data)
+{
+  GduWindow *window = GDU_WINDOW (user_data);
+  gdu_mdraid_disks_dialog_show (window, window->current_object);
+}
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void



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