[gnome-disk-utility/wip/mdraid] Add 'Select Disk' dialog



commit 04a6514af96b711c03c9e8c69548e7808d9d0bc2
Author: David Zeuthen <zeuthen gmail com>
Date:   Mon Sep 24 10:24:59 2012 -0400

    Add 'Select Disk' dialog
    
    Signed-off-by: David Zeuthen <zeuthen gmail com>

 data/ui/Makefile.am                  |    1 +
 data/ui/create-raid-array-dialog.ui  |    4 +
 data/ui/select-disk-dialog.ui        |   88 +++++++++
 src/disks/Makefile.am                |    1 +
 src/disks/gducreateraidarraydialog.c |   26 +++
 src/disks/gduenums.h                 |    6 +
 src/disks/gduselectdiskdialog.c      |  338 ++++++++++++++++++++++++++++++++++
 src/disks/gduselectdiskdialog.h      |   24 +++
 8 files changed, 488 insertions(+), 0 deletions(-)
---
diff --git a/data/ui/Makefile.am b/data/ui/Makefile.am
index 35d6596..7aa2db8 100644
--- a/data/ui/Makefile.am
+++ b/data/ui/Makefile.am
@@ -26,6 +26,7 @@ ui_DATA = 				\
 	disk-settings-dialog.ui		\
 	md-raid-disks-dialog.ui		\
 	create-raid-array-dialog.ui	\
+	select-disk-dialog.ui		\
 	$(NULL)
 
 EXTRA_DIST = 				\
diff --git a/data/ui/create-raid-array-dialog.ui b/data/ui/create-raid-array-dialog.ui
index 1380cb6..a9208dd 100644
--- a/data/ui/create-raid-array-dialog.ui
+++ b/data/ui/create-raid-array-dialog.ui
@@ -178,6 +178,7 @@
                 <property name="label" translatable="yes">&lt;b&gt;_Disks&lt;/b&gt;</property>
                 <property name="use_markup">True</property>
                 <property name="use_underline">True</property>
+                <property name="mnemonic_widget">treeview</property>
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -209,6 +210,9 @@
                             <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>
diff --git a/data/ui/select-disk-dialog.ui b/data/ui/select-disk-dialog.ui
new file mode 100644
index 0000000..a2de908
--- /dev/null
+++ b/data/ui/select-disk-dialog.ui
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkDialog" id="select-disk-dialog">
+    <property name="width_request">400</property>
+    <property name="height_request">500</property>
+    <property name="can_focus">False</property>
+    <property name="border_width">5</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="button1">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</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>
+            <child>
+              <object class="GtkButton" id="button2">
+                <property name="label" translatable="yes">_Select</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </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="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <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="headers_visible">False</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">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-6">button1</action-widget>
+      <action-widget response="-5">button2</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/src/disks/Makefile.am b/src/disks/Makefile.am
index e75d229..fbffb2d 100644
--- a/src/disks/Makefile.am
+++ b/src/disks/Makefile.am
@@ -49,6 +49,7 @@ gnome_disks_SOURCES = 							\
 	gdudisksettingsdialog.h		gdudisksettingsdialog.c		\
 	gdumdraiddisksdialog.h		gdumdraiddisksdialog.c		\
 	gducreateraidarraydialog.h	gducreateraidarraydialog.c	\
+	gduselectdiskdialog.h		gduselectdiskdialog.c		\
 	$(enum_built_sources)						\
 	$(NULL)
 
diff --git a/src/disks/gducreateraidarraydialog.c b/src/disks/gducreateraidarraydialog.c
index 9a45c24..f389242 100644
--- a/src/disks/gducreateraidarraydialog.c
+++ b/src/disks/gducreateraidarraydialog.c
@@ -16,6 +16,7 @@
 #include "gduapplication.h"
 #include "gduwindow.h"
 #include "gducreateraidarraydialog.h"
+#include "gduselectdiskdialog.h"
 
 /* ---------------------------------------------------------------------------------------------------- */
 
@@ -141,6 +142,22 @@ on_property_changed (GObject     *object,
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+static void
+on_add_toolbutton_clicked (GtkToolButton   *tool_button,
+                           gpointer         user_data)
+{
+  DialogData *data = user_data;
+  GList *disks;
+
+  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);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
 enum
 {
   COMBOBOX_MODEL_COLUMN_ID,
@@ -252,6 +269,15 @@ init_dialog (DialogData *data)
   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");
 
+  /* ---------- */
+
+  g_signal_connect (data->add_toolbutton,
+                    "clicked",
+                    G_CALLBACK (on_add_toolbutton_clicked),
+                    data);
+
+  /* ---------- */
+
   update_dialog (data);
 }
 
diff --git a/src/disks/gduenums.h b/src/disks/gduenums.h
index c87ca37..ea82ebd 100644
--- a/src/disks/gduenums.h
+++ b/src/disks/gduenums.h
@@ -30,6 +30,12 @@ typedef enum
   GDU_POWER_STATE_FLAGS_FAILED            = (1<<2)
 } GduPowerStateFlags;
 
+typedef enum
+{
+  GDU_SELECT_DISK_FLAGS_NONE              = 0,
+  GDU_SELECT_DISK_FLAGS_ALLOW_MULTIPLE    = (1<<0),
+} GduSelectDiskFlags;
+
 G_END_DECLS
 
 #endif /* __GDU_ENUMS_H__ */
diff --git a/src/disks/gduselectdiskdialog.c b/src/disks/gduselectdiskdialog.c
new file mode 100644
index 0000000..06abd51
--- /dev/null
+++ b/src/disks/gduselectdiskdialog.c
@@ -0,0 +1,338 @@
+/* -*- 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 "gduselectdiskdialog.h"
+#include "gdudevicetreemodel.h"
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+  volatile gint ref_count;
+
+  UDisksClient *client;
+  GduApplication *application;
+  GtkBuilder *builder;
+
+  GduSelectDiskFlags flags;
+
+  GtkWidget *dialog;
+
+  GtkWidget *scrolledwindow;
+  GtkWidget *treeview;
+
+  GduDeviceTreeModel *model;
+
+} DialogData;
+
+static const struct {
+  goffset offset;
+  const gchar *name;
+} widget_mapping[] = {
+  {G_STRUCT_OFFSET (DialogData, scrolledwindow), "scrolledwindow"},
+  {G_STRUCT_OFFSET (DialogData, treeview), "treeview"},
+
+  {0, NULL}
+};
+
+static void update_dialog (DialogData *data);
+
+
+static void on_client_changed (UDisksClient  *client,
+                               gpointer       user_data);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+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->application);
+      g_clear_object (&data->builder);
+
+      g_clear_object (&data->model);
+
+      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)
+{
+  gboolean select_sensitive = FALSE;
+
+  if (gtk_tree_selection_count_selected_rows (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview))) > 0)
+    select_sensitive = TRUE;
+
+  gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog),
+                                     GTK_RESPONSE_OK,
+                                     select_sensitive);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+G_GNUC_UNUSED static void
+on_property_changed (GObject     *object,
+                     GParamSpec  *pspec,
+                     gpointer     user_data)
+{
+  DialogData *data = user_data;
+  update_dialog (data);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gint
+device_sort_function (GtkTreeModel *model,
+                      GtkTreeIter *a,
+                      GtkTreeIter *b,
+                      gpointer user_data)
+{
+  gchar *sa, *sb;
+
+  gtk_tree_model_get (model, a,
+                      GDU_DEVICE_TREE_MODEL_COLUMN_SORT_KEY, &sa,
+                      -1);
+  gtk_tree_model_get (model, b,
+                      GDU_DEVICE_TREE_MODEL_COLUMN_SORT_KEY, &sb,
+                      -1);
+
+  return g_strcmp0 (sa, sb);
+}
+
+static void
+on_row_inserted (GtkTreeModel *tree_model,
+                 GtkTreePath  *path,
+                 GtkTreeIter  *iter,
+                 gpointer      user_data)
+{
+  DialogData *data = user_data;
+  gtk_tree_view_expand_all (GTK_TREE_VIEW (data->treeview));
+}
+
+static void
+on_tree_selection_changed (GtkTreeSelection *tree_selection,
+                           gpointer          user_data)
+{
+  DialogData *data = user_data;
+  update_dialog (data);
+}
+
+static gboolean
+dont_select_headings (GtkTreeSelection *selection,
+                      GtkTreeModel     *model,
+                      GtkTreePath      *path,
+                      gboolean          selected,
+                      gpointer          user_data)
+{
+  GtkTreeIter iter;
+  gboolean is_heading;
+
+  gtk_tree_model_get_iter (model,
+                           &iter,
+                           path);
+  gtk_tree_model_get (model,
+                      &iter,
+                      GDU_DEVICE_TREE_MODEL_COLUMN_IS_HEADING,
+                      &is_heading,
+                      -1);
+
+  return !is_heading;
+}
+
+static void
+init_dialog (DialogData *data)
+{
+  GtkTreeViewColumn *column;
+  GtkCellRenderer *renderer;
+
+  data->model = gdu_device_tree_model_new (data->client);
+
+  gtk_tree_view_set_model (GTK_TREE_VIEW (data->treeview), GTK_TREE_MODEL (data->model));
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (data->model),
+                                        GDU_DEVICE_TREE_MODEL_COLUMN_SORT_KEY,
+                                        GTK_SORT_ASCENDING);
+  /* Force g_strcmp0() as the sort function otherwise ___aa won't come before ____b ... */
+  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (data->model),
+                                   GDU_DEVICE_TREE_MODEL_COLUMN_SORT_KEY,
+                                   device_sort_function,
+                                   NULL, /* user_data */
+                                   NULL); /* GDestroyNotify */
+
+  column = gtk_tree_view_column_new ();
+  gtk_tree_view_append_column (GTK_TREE_VIEW (data->treeview), column);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_column_pack_start (column, renderer, FALSE);
+  gtk_tree_view_column_set_attributes (column,
+                                       renderer,
+                                       "markup", GDU_DEVICE_TREE_MODEL_COLUMN_HEADING_TEXT,
+                                       "visible", GDU_DEVICE_TREE_MODEL_COLUMN_IS_HEADING,
+                                       NULL);
+
+  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_attributes (column,
+                                       renderer,
+                                       "gicon", GDU_DEVICE_TREE_MODEL_COLUMN_ICON,
+                                       NULL);
+  renderer = gtk_cell_renderer_text_new ();
+  g_object_set (G_OBJECT (renderer),
+                "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
+                NULL);
+  gtk_tree_view_column_pack_start (column, renderer, FALSE);
+  gtk_tree_view_column_set_attributes (column,
+                                       renderer,
+                                       "markup", GDU_DEVICE_TREE_MODEL_COLUMN_NAME,
+                                       NULL);
+  renderer = gtk_cell_renderer_spinner_new ();
+  g_object_set (G_OBJECT (renderer),
+                "xalign", 1.0,
+                NULL);
+  gtk_tree_view_column_pack_end (column, renderer, FALSE);
+  gtk_tree_view_column_set_attributes (column,
+                                       renderer,
+                                       "visible", GDU_DEVICE_TREE_MODEL_COLUMN_JOBS_RUNNING,
+                                       "active", GDU_DEVICE_TREE_MODEL_COLUMN_JOBS_RUNNING,
+                                       "pulse", GDU_DEVICE_TREE_MODEL_COLUMN_PULSE,
+                                       NULL);
+
+  gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview)),
+                               data->flags & GDU_SELECT_DISK_FLAGS_ALLOW_MULTIPLE ?
+                                 GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE);
+
+  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,
+                                          data,
+                                          NULL); /* GDestroyNotify */
+  g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview)),
+                    "changed",
+                    G_CALLBACK (on_tree_selection_changed),
+                    data);
+
+  /* expand on insertion - hmm, I wonder if there's an easier way to do this */
+  g_signal_connect (data->model,
+                    "row-inserted",
+                    G_CALLBACK (on_row_inserted),
+                    data);
+  gtk_tree_view_expand_all (GTK_TREE_VIEW (data->treeview));
+
+  update_dialog (data);
+}
+
+static void
+on_client_changed (UDisksClient   *client,
+                   gpointer        user_data)
+{
+  DialogData *data = user_data;
+  update_dialog (data);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+
+GList *
+gdu_select_disk_dialog_show (GduApplication     *application,
+                             GtkWindow          *parent_window,
+                             GduSelectDiskFlags  flags)
+{
+  GList *ret = NULL;
+  DialogData *data;
+  guint n;
+
+  data = g_new0 (DialogData, 1);
+  data->ref_count = 1;
+  data->application = g_object_ref (application);
+  data->client = gdu_application_get_client (data->application);
+  data->flags = flags;
+
+  data->dialog = GTK_WIDGET (gdu_application_new_widget (data->application,
+                                                         "select-disk-dialog.ui",
+                                                         "select-disk-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);
+    }
+
+  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);
+
+  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 */
+          break;
+
+        case GTK_RESPONSE_OK:
+          g_print ("TODO: set ret\n");
+          goto out;
+
+        default:
+          goto out;
+        }
+    }
+ out:
+  dialog_data_close (data);
+  dialog_data_unref (data);
+
+  return ret;
+}
+
diff --git a/src/disks/gduselectdiskdialog.h b/src/disks/gduselectdiskdialog.h
new file mode 100644
index 0000000..13f097e
--- /dev/null
+++ b/src/disks/gduselectdiskdialog.h
@@ -0,0 +1,24 @@
+/* -*- 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_SELECT_DISK_DIALOG_H__
+#define __GDU_SELECT_DISK_DIALOG_H__
+
+#include <gtk/gtk.h>
+#include "gdutypes.h"
+
+G_BEGIN_DECLS
+
+GList *gdu_select_disk_dialog_show (GduApplication     *application,
+                                    GtkWindow          *parent_window,
+                                    GduSelectDiskFlags  flags);
+
+G_END_DECLS
+
+#endif /* __GDU_SELECT_DISK_DIALOG_H__ */



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