[gnome-disk-utility] Start writing a dialog to set up Software RAID



commit 88eff805079564e874b6b9baf3260cc5aae10d66
Author: David Zeuthen <davidz redhat com>
Date:   Sun Jul 19 18:23:20 2009 -0400

    Start writing a dialog to set up Software RAID
    
    As part of this work, refactor GduDeviceTree into model and view
    classes and move this to libgdu-gtk.

 src/gdu-gtk/Makefile.am                     |    6 +
 src/gdu-gtk/gdu-create-linux-md-dialog.c    |  399 +++++++++++++++++++++
 src/gdu-gtk/gdu-create-linux-md-dialog.h    |   62 ++++
 src/gdu-gtk/gdu-gtk-types.h                 |   10 +
 src/gdu-gtk/gdu-gtk.h                       |    3 +
 src/gdu-gtk/gdu-pool-tree-model.c           |  410 ++++++++++++++++++++++
 src/gdu-gtk/gdu-pool-tree-model.h           |   68 ++++
 src/gdu-gtk/gdu-pool-tree-view.c            |  251 +++++++++++++
 src/gdu-gtk/gdu-pool-tree-view.h            |   63 ++++
 src/palimpsest/Makefile.am                  |    1 -
 src/palimpsest/gdu-section-linux-md-drive.c |   13 +-
 src/palimpsest/gdu-shell.c                  |   64 +++-
 src/palimpsest/gdu-tree.c                   |  504 ---------------------------
 src/palimpsest/gdu-tree.h                   |   63 ----
 14 files changed, 1323 insertions(+), 594 deletions(-)
---
diff --git a/src/gdu-gtk/Makefile.am b/src/gdu-gtk/Makefile.am
index 45bbfb3..62608e6 100644
--- a/src/gdu-gtk/Makefile.am
+++ b/src/gdu-gtk/Makefile.am
@@ -9,12 +9,18 @@ libgdu_gtkinclude_HEADERS =              				\
 	gdu-gtk.h							\
 	gdu-gtk-types.h							\
 	gdu-time-label.h						\
+	gdu-pool-tree-view.h						\
+	gdu-pool-tree-model.h						\
+	gdu-create-linux-md-dialog.h					\
 	$(NULL)
 
 libgdu_gtk_la_SOURCES =                 	               		\
 	gdu-gtk.h			gdu-gtk.c			\
 	gdu-gtk-types.h							\
 	gdu-time-label.h		gdu-time-label.c		\
+	gdu-pool-tree-view.h		gdu-pool-tree-view.c		\
+	gdu-pool-tree-model.h		gdu-pool-tree-model.c		\
+	gdu-create-linux-md-dialog.h	gdu-create-linux-md-dialog.c	\
 	$(NULL)
 
 libgdu_gtk_la_CPPFLAGS = 				\
diff --git a/src/gdu-gtk/gdu-create-linux-md-dialog.c b/src/gdu-gtk/gdu-create-linux-md-dialog.c
new file mode 100644
index 0000000..82a66ae
--- /dev/null
+++ b/src/gdu-gtk/gdu-create-linux-md-dialog.c
@@ -0,0 +1,399 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include "gdu-create-linux-md-dialog.h"
+
+struct GduCreateLinuxMdDialogPrivate
+{
+        gchar *level;
+        GduPool *pool;
+        GtkWidget *name_entry;
+};
+
+enum
+{
+        PROP_0,
+        PROP_POOL,
+        PROP_LEVEL,
+        PROP_NAME,
+};
+
+static void gdu_create_linux_md_dialog_constructed (GObject *object);
+
+G_DEFINE_TYPE (GduCreateLinuxMdDialog, gdu_create_linux_md_dialog, GTK_TYPE_DIALOG)
+
+static void
+gdu_create_linux_md_dialog_finalize (GObject *object)
+{
+        GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (object);
+
+        g_object_unref (dialog->priv->pool);
+        g_free (dialog->priv->level);
+
+        if (G_OBJECT_CLASS (gdu_create_linux_md_dialog_parent_class)->finalize != NULL)
+                G_OBJECT_CLASS (gdu_create_linux_md_dialog_parent_class)->finalize (object);
+}
+
+static void
+gdu_create_linux_md_dialog_get_property (GObject    *object,
+                                guint       property_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+        GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (object);
+
+        switch (property_id) {
+        case PROP_POOL:
+                g_value_set_object (value, dialog->priv->pool);
+                break;
+
+        case PROP_LEVEL:
+                g_value_set_string (value, dialog->priv->level);
+                break;
+
+        case PROP_NAME:
+                g_value_set_string (value, gdu_create_linux_md_dialog_get_name (dialog));
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+                break;
+        }
+}
+
+static void
+gdu_create_linux_md_dialog_set_property (GObject      *object,
+                                   guint         property_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+        GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (object);
+
+        switch (property_id) {
+        case PROP_POOL:
+                dialog->priv->pool = g_value_dup_object (value);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+                break;
+        }
+}
+
+static void
+gdu_create_linux_md_dialog_class_init (GduCreateLinuxMdDialogClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        g_type_class_add_private (klass, sizeof (GduCreateLinuxMdDialogPrivate));
+
+        object_class->get_property = gdu_create_linux_md_dialog_get_property;
+        object_class->set_property = gdu_create_linux_md_dialog_set_property;
+        object_class->constructed  = gdu_create_linux_md_dialog_constructed;
+        object_class->finalize     = gdu_create_linux_md_dialog_finalize;
+
+        g_object_class_install_property (object_class,
+                                         PROP_POOL,
+                                         g_param_spec_object ("pool",
+                                                              _("Pool"),
+                                                              _("The pool of devices"),
+                                                              GDU_TYPE_POOL,
+                                                              G_PARAM_READABLE |
+                                                              G_PARAM_WRITABLE |
+                                                              G_PARAM_CONSTRUCT_ONLY |
+                                                              G_PARAM_STATIC_NAME |
+                                                              G_PARAM_STATIC_NICK |
+                                                              G_PARAM_STATIC_BLURB));
+
+        g_object_class_install_property (object_class,
+                                         PROP_LEVEL,
+                                         g_param_spec_string ("level",
+                                                              _("RAID Level"),
+                                                              _("The selected RAID level"),
+                                                              NULL,
+                                                              G_PARAM_READABLE |
+                                                              G_PARAM_STATIC_NAME |
+                                                              G_PARAM_STATIC_NICK |
+                                                              G_PARAM_STATIC_BLURB));
+
+        g_object_class_install_property (object_class,
+                                         PROP_NAME,
+                                         g_param_spec_string ("fs-label",
+                                                              _("Filesystem label"),
+                                                              _("The requested filesystem label"),
+                                                              NULL,
+                                                              G_PARAM_READABLE |
+                                                              G_PARAM_STATIC_NAME |
+                                                              G_PARAM_STATIC_NICK |
+                                                              G_PARAM_STATIC_BLURB));
+}
+
+static void
+gdu_create_linux_md_dialog_init (GduCreateLinuxMdDialog *dialog)
+{
+        dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog, GDU_TYPE_CREATE_LINUX_MD_DIALOG, GduCreateLinuxMdDialogPrivate);
+}
+
+GtkWidget *
+gdu_create_linux_md_dialog_new (GtkWindow *parent,
+                                GduPool   *pool)
+{
+        return GTK_WIDGET (g_object_new (GDU_TYPE_CREATE_LINUX_MD_DIALOG,
+                                         "transient-for", parent,
+                                         "pool", pool,
+                                         NULL));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+gchar *
+gdu_create_linux_md_dialog_get_level  (GduCreateLinuxMdDialog *dialog)
+{
+        g_return_val_if_fail (GDU_IS_CREATE_LINUX_MD_DIALOG (dialog), NULL);
+        return g_strdup (dialog->priv->level);
+}
+
+gchar *
+gdu_create_linux_md_dialog_get_name (GduCreateLinuxMdDialog *dialog)
+{
+        g_return_val_if_fail (GDU_IS_CREATE_LINUX_MD_DIALOG (dialog), NULL);
+        return g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->priv->name_entry)));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_combo_box_changed (GtkWidget *combo_box,
+                      gpointer   user_data)
+{
+        GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (user_data);
+        GduKnownFilesystem *kfs;
+        gint max_label_len;
+
+        /* keep in sync with where combo box is constructed in constructed() */
+        g_free (dialog->priv->level);
+        switch (gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box))) {
+        case 0:
+                dialog->priv->level = g_strdup ("linear");
+                break;
+        case 1:
+                dialog->priv->level = g_strdup ("raid0");
+                break;
+        case 2:
+                dialog->priv->level = g_strdup ("raid1");
+                break;
+        case 3:
+                dialog->priv->level = g_strdup ("raid4");
+                break;
+        case 4:
+                dialog->priv->level = g_strdup ("raid5");
+                break;
+        case 5:
+                dialog->priv->level = g_strdup ("raid6");
+                break;
+        case 6:
+                dialog->priv->level = g_strdup ("raid10");
+                break;
+        default:
+                g_assert_not_reached ();
+                break;
+        }
+
+        max_label_len = 0;
+        kfs = gdu_pool_get_known_filesystem_by_id (dialog->priv->pool, dialog->priv->level);
+        if (kfs != NULL) {
+                max_label_len = gdu_known_filesystem_get_max_label_len (kfs);
+                g_object_unref (kfs);
+        }
+}
+
+static void
+on_name_entry_activated (GtkWidget *combo_box,
+                             gpointer   user_data)
+{
+        GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (user_data);
+
+        gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+gdu_create_linux_md_dialog_constructed (GObject *object)
+{
+        GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (object);
+        GtkWidget *content_area;
+        GtkWidget *button;
+        GtkWidget *label;
+        GtkWidget *hbox;
+        GtkWidget *image;
+        GtkWidget *table;
+        GtkWidget *entry;
+        GtkWidget *combo_box;
+        GtkWidget *vbox2;
+        GdkPixbuf *pixbuf;
+        gint row;
+        gboolean ret;
+        GtkWidget *align;
+        gchar *s;
+
+        ret = FALSE;
+
+        pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+                                           "gdu-raid-array",
+                                           48,
+                                           0,
+                                           NULL);
+
+        gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+        gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
+        gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 0);
+        gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 5);
+        gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6);
+
+        gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+        gtk_window_set_title (GTK_WINDOW (dialog), "");
+        gtk_window_set_icon_name (GTK_WINDOW (dialog), "nautilus-gdu");
+
+        gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+        button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+                                        _("C_reate"),
+                                        GTK_RESPONSE_OK);
+        gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+        content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+        gtk_container_set_border_width (GTK_CONTAINER (content_area), 10);
+
+        /*  icon and text labels  */
+        hbox = gtk_hbox_new (FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (content_area), hbox, FALSE, TRUE, 0);
+
+        image = gtk_image_new_from_pixbuf (pixbuf);
+        gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+        gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 12);
+
+        align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+        gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 12, 0, 0);
+        gtk_box_pack_start (GTK_BOX (hbox), align, TRUE, TRUE, 0);
+
+        vbox2 = gtk_vbox_new (FALSE, 12);
+        gtk_container_add (GTK_CONTAINER (align), vbox2);
+
+        row = 0;
+
+        table = gtk_table_new (2, 2, FALSE);
+        gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+        gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+        gtk_box_pack_start (GTK_BOX (vbox2), table, FALSE, FALSE, 0);
+
+        /*  filesystem type  */
+        label = gtk_label_new (NULL);
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), _("_Level:"));
+        gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+                          GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+        combo_box = gtk_combo_box_new_text ();
+        /* keep in sync with on_combo_box_changed() */
+        gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box),
+                                   _("Concatenated"));
+        gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box),
+                                   _("Striped (RAID 0)"));
+        gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box),
+                                   _("Mirrored (RAID 1)"));
+        gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box),
+                                   _("RAID 4"));
+        gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box),
+                                   _("RAID 5"));
+        gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box),
+                                   _("RAID 6"));
+        gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box),
+                                   _("RAID 10"));
+        gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 2);
+        dialog->priv->level = g_strdup ("raid1");
+        gtk_table_attach (GTK_TABLE (table), combo_box, 1, 2, row, row +1,
+                          GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo_box);
+        row++;
+
+        /*  filesystem label  */
+        label = gtk_label_new (NULL);
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), _("_Name:"));
+        gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+                          GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+        entry = gtk_entry_new ();
+        /* Translators: Keep length of translation of "New RAID Device" to less than 32 characters */
+        gtk_entry_set_text (GTK_ENTRY (entry), _("New RAID Device"));
+        gtk_entry_set_max_length (GTK_ENTRY (entry), 32); /* on-disk-format restriction */
+        gtk_table_attach (GTK_TABLE (table), entry, 1, 2, row, row + 1,
+                          GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+        dialog->priv->name_entry = entry;
+        row++;
+
+        /* -------------------------------------------------------------------------------- */
+
+        /* component tree-views */
+
+
+
+        /* -------------------------------------------------------------------------------- */
+
+        hbox = gtk_hbox_new (FALSE, 6);
+        gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
+
+        image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
+        gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+
+	label = gtk_label_new (NULL);
+        s = g_strconcat ("<i>",
+                         _("Warning: All data on the volume will be irrevocably lost."),
+                         "</i>",
+                         NULL);
+        gtk_label_set_markup (GTK_LABEL (label), s);
+        g_free (s);
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+
+        g_signal_connect (combo_box,
+                          "changed",
+                          G_CALLBACK (on_combo_box_changed),
+                          dialog);
+
+        g_signal_connect (dialog->priv->name_entry,
+                          "activate",
+                          G_CALLBACK (on_name_entry_activated),
+                          dialog);
+
+        gtk_widget_grab_focus (dialog->priv->name_entry);
+        gtk_editable_select_region (GTK_EDITABLE (dialog->priv->name_entry), 0, 1000);
+
+        if (G_OBJECT_CLASS (gdu_create_linux_md_dialog_parent_class)->constructed != NULL)
+                G_OBJECT_CLASS (gdu_create_linux_md_dialog_parent_class)->constructed (object);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/gdu-gtk/gdu-create-linux-md-dialog.h b/src/gdu-gtk/gdu-create-linux-md-dialog.h
new file mode 100644
index 0000000..7fad710
--- /dev/null
+++ b/src/gdu-gtk/gdu-create-linux-md-dialog.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#ifndef __GDU_CREATE_LINUX_MD_DIALOG_H
+#define __GDU_CREATE_LINUX_MD_DIALOG_H
+
+#include <gdu-gtk/gdu-gtk.h>
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_CREATE_LINUX_MD_DIALOG            gdu_create_linux_md_dialog_get_type()
+#define GDU_CREATE_LINUX_MD_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDU_TYPE_CREATE_LINUX_MD_DIALOG, GduCreateLinuxMdDialog))
+#define GDU_CREATE_LINUX_MD_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GDU_TYPE_CREATE_LINUX_MD_DIALOG, GduCreateLinuxMdDialogClass))
+#define GDU_IS_CREATE_LINUX_MD_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDU_TYPE_CREATE_LINUX_MD_DIALOG))
+#define GDU_IS_CREATE_LINUX_MD_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDU_TYPE_CREATE_LINUX_MD_DIALOG))
+#define GDU_CREATE_LINUX_MD_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GDU_TYPE_CREATE_LINUX_MD_DIALOG, GduCreateLinuxMdDialogClass))
+
+typedef struct GduCreateLinuxMdDialogClass   GduCreateLinuxMdDialogClass;
+typedef struct GduCreateLinuxMdDialogPrivate GduCreateLinuxMdDialogPrivate;
+
+struct GduCreateLinuxMdDialog
+{
+        GtkDialog parent;
+
+        /*< private >*/
+        GduCreateLinuxMdDialogPrivate *priv;
+};
+
+struct GduCreateLinuxMdDialogClass
+{
+        GtkDialogClass parent_class;
+};
+
+GType       gdu_create_linux_md_dialog_get_type  (void) G_GNUC_CONST;
+GtkWidget*  gdu_create_linux_md_dialog_new       (GtkWindow              *parent,
+                                                  GduPool                *pool);
+gchar      *gdu_create_linux_md_dialog_get_level (GduCreateLinuxMdDialog *dialog);
+gchar      *gdu_create_linux_md_dialog_get_name  (GduCreateLinuxMdDialog *dialog);
+
+G_END_DECLS
+
+#endif  /* __GDU_CREATE_LINUX_MD_DIALOG_H */
+
diff --git a/src/gdu-gtk/gdu-gtk-types.h b/src/gdu-gtk/gdu-gtk-types.h
index 50dd6a1..e419d75 100644
--- a/src/gdu-gtk/gdu-gtk-types.h
+++ b/src/gdu-gtk/gdu-gtk-types.h
@@ -32,8 +32,18 @@
 
 G_BEGIN_DECLS
 
+struct GduTimeLabel;
 typedef struct GduTimeLabel             GduTimeLabel;
 
+struct GduPoolTreeModel;
+typedef struct GduPoolTreeModel         GduPoolTreeModel;
+
+struct GduPoolTreeView;
+typedef struct GduPoolTreeView          GduPoolTreeView;
+
+struct GduCreateLinuxMdDialog;
+typedef struct GduCreateLinuxMdDialog   GduCreateLinuxMdDialog;
+
 G_END_DECLS
 
 #endif /* __GDU_GTK_TYPES_H */
diff --git a/src/gdu-gtk/gdu-gtk.h b/src/gdu-gtk/gdu-gtk.h
index 7bc191b..85965e2 100644
--- a/src/gdu-gtk/gdu-gtk.h
+++ b/src/gdu-gtk/gdu-gtk.h
@@ -29,6 +29,9 @@
 #define __GDU_GTK_INSIDE_GDU_GTK_H
 #include <gdu-gtk/gdu-gtk-types.h>
 #include <gdu-gtk/gdu-time-label.h>
+#include <gdu-gtk/gdu-pool-tree-view.h>
+#include <gdu-gtk/gdu-pool-tree-model.h>
+#include <gdu-gtk/gdu-create-linux-md-dialog.h>
 #undef __GDU_GTK_INSIDE_GDU_GTK_H
 
 G_BEGIN_DECLS
diff --git a/src/gdu-gtk/gdu-pool-tree-model.c b/src/gdu-gtk/gdu-pool-tree-model.c
new file mode 100644
index 0000000..d29c8a2
--- /dev/null
+++ b/src/gdu-gtk/gdu-pool-tree-model.c
@@ -0,0 +1,410 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include "gdu-gtk.h"
+#include "gdu-pool-tree-model.h"
+
+struct GduPoolTreeModelPrivate
+{
+        GduPool *pool;
+};
+
+G_DEFINE_TYPE (GduPoolTreeModel, gdu_pool_tree_model, GTK_TYPE_TREE_STORE)
+
+enum
+{
+        PROP_0,
+        PROP_POOL,
+};
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void on_presentable_added   (GduPool          *pool,
+                                    GduPresentable   *presentable,
+                                    gpointer          user_data);
+static void on_presentable_removed (GduPool          *pool,
+                                    GduPresentable   *presentable,
+                                    gpointer          user_data);
+static void on_presentable_changed (GduPool          *pool,
+                                    GduPresentable   *presentable,
+                                    gpointer          user_data);
+static void add_presentable        (GduPoolTreeModel *model,
+                                    GduPresentable   *presentable,
+                                    GtkTreeIter      *iter_out);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+gdu_pool_tree_model_set_property (GObject      *object,
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+        GduPoolTreeModel *model = GDU_POOL_TREE_MODEL (object);
+
+        switch (prop_id) {
+        case PROP_POOL:
+                model->priv->pool = g_value_dup_object (value);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gdu_pool_tree_model_get_property (GObject     *object,
+                             guint        prop_id,
+                             GValue      *value,
+                             GParamSpec  *pspec)
+{
+        GduPoolTreeModel *model = GDU_POOL_TREE_MODEL (object);
+
+        switch (prop_id) {
+        case PROP_POOL:
+                g_value_set_object (value, model->priv->pool);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+    }
+}
+
+static void
+gdu_pool_tree_model_finalize (GObject *object)
+{
+        GduPoolTreeModel *model = GDU_POOL_TREE_MODEL (object);
+
+        g_signal_handlers_disconnect_by_func (model->priv->pool, on_presentable_added, model);
+        g_signal_handlers_disconnect_by_func (model->priv->pool, on_presentable_removed, model);
+        g_signal_handlers_disconnect_by_func (model->priv->pool, on_presentable_changed, model);
+
+        g_object_unref (model->priv->pool);
+
+        if (G_OBJECT_CLASS (gdu_pool_tree_model_parent_class)->finalize != NULL)
+                G_OBJECT_CLASS (gdu_pool_tree_model_parent_class)->finalize (object);
+}
+
+static gint
+presentable_sort_func (GtkTreeModel *model,
+                       GtkTreeIter  *a,
+                       GtkTreeIter  *b,
+                       gpointer      userdata)
+{
+        GduPresentable *p1;
+        GduPresentable *p2;
+        gint result;
+
+        result = 0;
+
+        gtk_tree_model_get (model, a, GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE, &p1, -1);
+        gtk_tree_model_get (model, b, GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE, &p2, -1);
+        if (p1 == NULL || p2 == NULL)
+                goto out;
+
+        result = gdu_presentable_compare (p1, p2);
+
+ out:
+        if (p1 != NULL)
+                g_object_unref (p1);
+        if (p2 != NULL)
+                g_object_unref (p2);
+
+        return result;
+}
+
+static void
+gdu_pool_tree_model_constructed (GObject *object)
+{
+        GduPoolTreeModel *model = GDU_POOL_TREE_MODEL (object);
+        GType column_types[4];
+        GList *presentables;
+        GList *l;
+
+        column_types[0] = GDK_TYPE_PIXBUF;
+        column_types[1] = G_TYPE_STRING;
+        column_types[2] = GDU_TYPE_PRESENTABLE;
+        column_types[3] = G_TYPE_STRING;
+
+        gtk_tree_store_set_column_types (GTK_TREE_STORE (object),
+                                         G_N_ELEMENTS (column_types),
+                                         column_types);
+
+        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (object),
+                                         GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE,
+                                         presentable_sort_func,
+                                         NULL,
+                                         NULL);
+
+        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (object),
+                                              GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE,
+                                              GTK_SORT_ASCENDING);
+
+        /* coldplug */
+        presentables = gdu_pool_get_presentables (model->priv->pool);
+        for (l = presentables; l != NULL; l = l->next) {
+                GduPresentable *presentable = GDU_PRESENTABLE (l->data);
+
+                add_presentable (model, presentable, NULL);
+                g_object_unref (presentable);
+        }
+        g_list_free (presentables);
+
+        /* add/remove/change when the pool reports presentable add/remove/change */
+        g_signal_connect (model->priv->pool,
+                          "presentable-added",
+                          G_CALLBACK (on_presentable_added),
+                          model);
+        g_signal_connect (model->priv->pool,
+                          "presentable-removed",
+                          G_CALLBACK (on_presentable_removed),
+                          model);
+        g_signal_connect (model->priv->pool,
+                          "presentable-changed",
+                          G_CALLBACK (on_presentable_changed),
+                          model);
+
+        if (G_OBJECT_CLASS (gdu_pool_tree_model_parent_class)->constructed != NULL)
+                G_OBJECT_CLASS (gdu_pool_tree_model_parent_class)->constructed (object);
+}
+
+static void
+gdu_pool_tree_model_class_init (GduPoolTreeModelClass *klass)
+{
+        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+        gobject_class->finalize     = gdu_pool_tree_model_finalize;
+        gobject_class->constructed  = gdu_pool_tree_model_constructed;
+        gobject_class->set_property = gdu_pool_tree_model_set_property;
+        gobject_class->get_property = gdu_pool_tree_model_get_property;
+
+        g_type_class_add_private (klass, sizeof (GduPoolTreeModelPrivate));
+
+        /**
+         * GduPoolTreeModel:pool:
+         *
+         * The pool used.
+         */
+        g_object_class_install_property (gobject_class,
+                                         PROP_POOL,
+                                         g_param_spec_object ("pool",
+                                                              NULL,
+                                                              NULL,
+                                                              GDU_TYPE_POOL,
+                                                              G_PARAM_WRITABLE |
+                                                              G_PARAM_READABLE |
+                                                              G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gdu_pool_tree_model_init (GduPoolTreeModel *model)
+{
+        model->priv = G_TYPE_INSTANCE_GET_PRIVATE (model, GDU_TYPE_POOL_TREE_MODEL, GduPoolTreeModelPrivate);
+}
+
+GduPoolTreeModel *
+gdu_pool_tree_model_new (GduPool *pool)
+{
+        return GDU_POOL_TREE_MODEL (g_object_new (GDU_TYPE_POOL_TREE_MODEL,
+                                                  "pool", pool,
+                                                  NULL));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct {
+        GduPresentable *presentable;
+        gboolean found;
+        GtkTreeIter iter;
+} FIBDData;
+
+static gboolean
+find_iter_by_presentable_foreach (GtkTreeModel *model,
+                                  GtkTreePath  *path,
+                                  GtkTreeIter  *iter,
+                                  gpointer      data)
+{
+        gboolean ret;
+        GduPresentable *presentable = NULL;
+        FIBDData *fibd_data = (FIBDData *) data;
+
+        ret = FALSE;
+        gtk_tree_model_get (model,
+                            iter,
+                            GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE, &presentable,
+                            -1);
+        if (presentable == fibd_data->presentable) {
+                fibd_data->found = TRUE;
+                fibd_data->iter = *iter;
+                ret = TRUE;
+        }
+        if (presentable != NULL)
+                g_object_unref (presentable);
+
+        return ret;
+}
+
+
+gboolean
+gdu_pool_tree_model_get_iter_for_presentable (GduPoolTreeModel *model,
+                                              GduPresentable   *presentable,
+                                              GtkTreeIter      *out_iter)
+{
+        FIBDData fibd_data;
+        gboolean ret;
+
+        fibd_data.presentable = presentable;
+        fibd_data.found = FALSE;
+        gtk_tree_model_foreach (GTK_TREE_MODEL (model),
+                                find_iter_by_presentable_foreach,
+                                &fibd_data);
+        if (fibd_data.found) {
+                if (out_iter != NULL)
+                        *out_iter = fibd_data.iter;
+                ret = TRUE;
+        } else {
+                ret = FALSE;
+        }
+
+        return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+add_presentable (GduPoolTreeModel *model,
+                 GduPresentable   *presentable,
+                 GtkTreeIter      *iter_out)
+{
+        GtkTreeIter  iter;
+        GtkTreeIter  iter2;
+        GtkTreeIter *parent_iter;
+        GdkPixbuf   *pixbuf;
+        char        *name;
+        GduPresentable *enclosing_presentable;
+
+        /* check to see if presentable is already added */
+        if (gdu_pool_tree_model_get_iter_for_presentable (model, presentable, NULL))
+                goto out;
+
+        /* set up parent relationship */
+        parent_iter = NULL;
+        enclosing_presentable = gdu_presentable_get_enclosing_presentable (presentable);
+        if (enclosing_presentable != NULL) {
+                if (gdu_pool_tree_model_get_iter_for_presentable (model, enclosing_presentable, &iter2)) {
+                        parent_iter = &iter2;
+                } else {
+                        /* add parent if it's not already added */
+                        g_warning ("No parent for %s", gdu_presentable_get_id (enclosing_presentable));
+                        add_presentable (model, enclosing_presentable, &iter2);
+                        parent_iter = &iter2;
+                }
+                g_object_unref (enclosing_presentable);
+        }
+
+        name = gdu_presentable_get_name (presentable);
+        pixbuf = gdu_util_get_pixbuf_for_presentable (presentable, GTK_ICON_SIZE_MENU);
+
+        /*g_debug ("adding %s (%p)", gdu_presentable_get_id (presentable), presentable);*/
+
+        gtk_tree_store_append (GTK_TREE_STORE (model),
+                               &iter,
+                               parent_iter);
+        gtk_tree_store_set (GTK_TREE_STORE (model),
+                            &iter,
+                            GDU_POOL_TREE_MODEL_COLUMN_ICON, pixbuf,
+                            GDU_POOL_TREE_MODEL_COLUMN_NAME, name,
+                            GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE, presentable,
+                            -1);
+
+        if (iter_out != NULL)
+                *iter_out = iter;
+
+        g_free (name);
+        if (pixbuf != NULL)
+                g_object_unref (pixbuf);
+
+out:
+        ;
+}
+
+static void
+on_presentable_added (GduPool          *pool,
+                      GduPresentable   *presentable,
+                      gpointer          user_data)
+{
+        GduPoolTreeModel *model = GDU_POOL_TREE_MODEL (user_data);
+
+        add_presentable (model, presentable, NULL);
+}
+
+static void
+on_presentable_removed (GduPool          *pool,
+                        GduPresentable   *presentable,
+                        gpointer          user_data)
+{
+        GduPoolTreeModel *model = GDU_POOL_TREE_MODEL (user_data);
+        GtkTreeIter iter;
+
+        if (gdu_pool_tree_model_get_iter_for_presentable (model, presentable, &iter)) {
+                gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
+        }
+}
+
+static void
+on_presentable_changed (GduPool          *pool,
+                        GduPresentable   *presentable,
+                        gpointer          user_data)
+{
+        GduPoolTreeModel *model = GDU_POOL_TREE_MODEL (user_data);
+        char *name;
+        GtkTreeIter iter;
+        GdkPixbuf *pixbuf;
+        GduDevice *device;
+
+        /* update name and icon */
+        if (gdu_pool_tree_model_get_iter_for_presentable (model, presentable, &iter)) {
+
+                name = gdu_presentable_get_name (presentable);
+                device = gdu_presentable_get_device (presentable);
+
+                pixbuf = gdu_util_get_pixbuf_for_presentable (presentable, GTK_ICON_SIZE_MENU);
+
+                gtk_tree_store_set (GTK_TREE_STORE (model),
+                                    &iter,
+                                    GDU_POOL_TREE_MODEL_COLUMN_ICON, pixbuf,
+                                    GDU_POOL_TREE_MODEL_COLUMN_NAME, name,
+                                    -1);
+
+                g_free (name);
+                if (pixbuf != NULL)
+                        g_object_unref (pixbuf);
+                if (device != NULL)
+                        g_object_unref (device);
+        }
+}
diff --git a/src/gdu-gtk/gdu-pool-tree-model.h b/src/gdu-gtk/gdu-pool-tree-model.h
new file mode 100644
index 0000000..1a492fb
--- /dev/null
+++ b/src/gdu-gtk/gdu-pool-tree-model.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#if !defined (__GDU_GTK_INSIDE_GDU_GTK_H) && !defined (GDU_GTK_COMPILATION)
+#error "Only <gdu-gtk/gdu-gtk.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef GDU_POOL_TREE_MODEL_H
+#define GDU_POOL_TREE_MODEL_H
+
+#include <gdu-gtk/gdu-gtk-types.h>
+
+#define GDU_TYPE_POOL_TREE_MODEL             (gdu_pool_tree_model_get_type ())
+#define GDU_POOL_TREE_MODEL(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDU_TYPE_POOL_TREE_MODEL, GduPoolTreeModel))
+#define GDU_POOL_TREE_MODEL_CLASS(obj)       (G_TYPE_CHECK_CLASS_CAST ((obj), GDU_POOL_TREE_MODEL,  GduPoolTreeModelClass))
+#define GDU_IS_POOL_TREE_MODEL(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDU_TYPE_POOL_TREE_MODEL))
+#define GDU_IS_POOL_TREE_MODEL_CLASS(obj)    (G_TYPE_CHECK_CLASS_TYPE ((obj), GDU_TYPE_POOL_TREE_MODEL))
+#define GDU_POOL_TREE_MODEL_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GDU_TYPE_POOL_TREE_MODEL, GduPoolTreeModelClass))
+
+typedef struct GduPoolTreeModelClass       GduPoolTreeModelClass;
+typedef struct GduPoolTreeModelPrivate     GduPoolTreeModelPrivate;
+
+typedef enum {
+        GDU_POOL_TREE_MODEL_COLUMN_ICON,
+        GDU_POOL_TREE_MODEL_COLUMN_NAME,
+        GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE,
+} GduPoolTreeModelColumn;
+
+struct GduPoolTreeModel
+{
+        GtkTreeStore parent;
+
+        /* private */
+        GduPoolTreeModelPrivate *priv;
+};
+
+struct GduPoolTreeModelClass
+{
+        GtkTreeStoreClass parent_class;
+};
+
+
+GType             gdu_pool_tree_model_get_type                 (void);
+GduPoolTreeModel *gdu_pool_tree_model_new                      (GduPool *pool);
+gboolean          gdu_pool_tree_model_get_iter_for_presentable (GduPoolTreeModel *model,
+                                                                GduPresentable   *presentable,
+                                                                GtkTreeIter      *out_iter);
+
+#endif /* GDU_POOL_TREE_MODEL_H */
diff --git a/src/gdu-gtk/gdu-pool-tree-view.c b/src/gdu-gtk/gdu-pool-tree-view.c
new file mode 100644
index 0000000..b1084e7
--- /dev/null
+++ b/src/gdu-gtk/gdu-pool-tree-view.c
@@ -0,0 +1,251 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include "gdu-pool-tree-view.h"
+#include "gdu-pool-tree-model.h"
+
+
+struct GduPoolTreeViewPrivate
+{
+        GduPoolTreeModel *model;
+};
+
+G_DEFINE_TYPE (GduPoolTreeView, gdu_pool_tree_view, GTK_TYPE_TREE_VIEW)
+
+enum {
+        PROP_0,
+        PROP_POOL_TREE_MODEL,
+};
+
+static void
+gdu_pool_tree_view_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+        GduPoolTreeView *view = GDU_POOL_TREE_VIEW (object);
+
+        switch (prop_id) {
+        case PROP_POOL_TREE_MODEL:
+                view->priv->model = g_value_dup_object (value);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gdu_pool_tree_view_get_property (GObject     *object,
+                                 guint        prop_id,
+                                 GValue      *value,
+                                 GParamSpec  *pspec)
+{
+        GduPoolTreeView *view = GDU_POOL_TREE_VIEW (object);
+
+        switch (prop_id) {
+        case PROP_POOL_TREE_MODEL:
+                g_value_set_object (value, view->priv->model);
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+    }
+}
+
+static void
+gdu_pool_tree_view_finalize (GObject *object)
+{
+        GduPoolTreeView *view = GDU_POOL_TREE_VIEW (object);
+
+        if (view->priv->model != NULL)
+                g_object_unref (view->priv->model);
+
+        if (G_OBJECT_CLASS (gdu_pool_tree_view_parent_class)->finalize != NULL)
+                G_OBJECT_CLASS (gdu_pool_tree_view_parent_class)->finalize (object);
+}
+
+static void
+on_row_inserted (GtkTreeModel *tree_model,
+                 GtkTreePath  *path,
+                 GtkTreeIter  *iter,
+                 gpointer      user_data)
+{
+        GduPoolTreeView *view = GDU_POOL_TREE_VIEW (user_data);
+        gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
+}
+
+static void
+gdu_pool_tree_view_constructed (GObject *object)
+{
+        GduPoolTreeView *view = GDU_POOL_TREE_VIEW (object);
+        GtkCellRenderer *renderer;
+        GtkTreeViewColumn *column;
+
+        gtk_tree_view_set_model (GTK_TREE_VIEW (view),
+                                 GTK_TREE_MODEL (view->priv->model));
+
+        column = gtk_tree_view_column_new ();
+        gtk_tree_view_column_set_title (column, "Title");
+        renderer = gtk_cell_renderer_pixbuf_new ();
+        gtk_tree_view_column_pack_start (column, renderer, FALSE);
+        gtk_tree_view_column_set_attributes (column, renderer,
+                                             "pixbuf", GDU_POOL_TREE_MODEL_COLUMN_ICON,
+                                             NULL);
+        renderer = gtk_cell_renderer_text_new ();
+        gtk_tree_view_column_pack_start (column, renderer, TRUE);
+        gtk_tree_view_column_set_attributes (column, renderer,
+                                             "text", GDU_POOL_TREE_MODEL_COLUMN_NAME,
+                                             NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
+
+        gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (view), FALSE);
+        gtk_tree_view_set_level_indentation (GTK_TREE_VIEW (view), 16);
+        gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
+
+        /* expand on insertion - hmm, I wonder if there's an easier way to do this */
+        g_signal_connect (view->priv->model,
+                          "row-inserted",
+                          G_CALLBACK (on_row_inserted),
+                          view);
+
+        if (G_OBJECT_CLASS (gdu_pool_tree_view_parent_class)->constructed != NULL)
+                G_OBJECT_CLASS (gdu_pool_tree_view_parent_class)->constructed (object);
+}
+
+static void
+gdu_pool_tree_view_class_init (GduPoolTreeViewClass *klass)
+{
+        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+        gobject_class->finalize     = gdu_pool_tree_view_finalize;
+        gobject_class->constructed  = gdu_pool_tree_view_constructed;
+        gobject_class->set_property = gdu_pool_tree_view_set_property;
+        gobject_class->get_property = gdu_pool_tree_view_get_property;
+
+        g_type_class_add_private (klass, sizeof (GduPoolTreeViewPrivate));
+
+        /**
+         * GduPoolTreeView:pool-tree-model:
+         *
+         * The #GduPoolTreeModel instance we are getting information from
+         */
+        g_object_class_install_property (gobject_class,
+                                         PROP_POOL_TREE_MODEL,
+                                         g_param_spec_object ("pool-tree-model",
+                                                              NULL,
+                                                              NULL,
+                                                              GDU_TYPE_POOL_TREE_MODEL,
+                                                              G_PARAM_WRITABLE |
+                                                              G_PARAM_READABLE |
+                                                              G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gdu_pool_tree_view_init (GduPoolTreeView *view)
+{
+        view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view, GDU_TYPE_POOL_TREE_VIEW, GduPoolTreeViewPrivate);
+}
+
+GtkWidget *
+gdu_pool_tree_view_new (GduPoolTreeModel *model)
+{
+        return GTK_WIDGET (g_object_new (GDU_TYPE_POOL_TREE_VIEW,
+                                         "pool-tree-model", model,
+                                         NULL));
+}
+
+GduPresentable *
+gdu_pool_tree_view_get_selected_presentable (GduPoolTreeView *view)
+{
+        GtkTreePath *path;
+        GduPresentable *presentable;
+
+        presentable = NULL;
+
+        gtk_tree_view_get_cursor (GTK_TREE_VIEW (view), &path, NULL);
+        if (path != NULL) {
+                GtkTreeIter iter;
+
+                if (gtk_tree_model_get_iter (GTK_TREE_MODEL (view->priv->model), &iter, path)) {
+
+                        gtk_tree_model_get (GTK_TREE_MODEL (view->priv->model),
+                                            &iter,
+                                            GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE,
+                                            &presentable,
+                                            -1);
+                }
+
+                gtk_tree_path_free (path);
+        }
+
+        return presentable;
+}
+
+void
+gdu_pool_tree_view_select_presentable (GduPoolTreeView *view,
+                                       GduPresentable  *presentable)
+{
+        GtkTreePath *path;
+        GtkTreeIter iter;
+
+        if (presentable == NULL)
+                goto out;
+
+        if (!gdu_pool_tree_model_get_iter_for_presentable (view->priv->model, presentable, &iter))
+                goto out;
+
+        path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->priv->model), &iter);
+        if (path == NULL)
+                goto out;
+
+        gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path, NULL, FALSE);
+        gtk_tree_path_free (path);
+out:
+        ;
+}
+
+void
+gdu_pool_tree_view_select_first_presentable (GduPoolTreeView *view)
+{
+        GtkTreePath *path;
+        GtkTreeIter iter;
+
+        if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (view->priv->model), &iter)) {
+                path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->priv->model), &iter);
+                if (path == NULL)
+                        goto out;
+
+                gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path, NULL, FALSE);
+                gtk_tree_path_free (path);
+        }
+out:
+        ;
+}
diff --git a/src/gdu-gtk/gdu-pool-tree-view.h b/src/gdu-gtk/gdu-pool-tree-view.h
new file mode 100644
index 0000000..71c3828
--- /dev/null
+++ b/src/gdu-gtk/gdu-pool-tree-view.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#if !defined (__GDU_GTK_INSIDE_GDU_GTK_H) && !defined (GDU_GTK_COMPILATION)
+#error "Only <gdu-gtk/gdu-gtk.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef GDU_POOL_TREE_VIEW_H
+#define GDU_POOL_TREE_VIEW_H
+
+#include <gdu-gtk/gdu-gtk-types.h>
+
+#define GDU_TYPE_POOL_TREE_VIEW             (gdu_pool_tree_view_get_type ())
+#define GDU_POOL_TREE_VIEW(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDU_TYPE_POOL_TREE_VIEW, GduPoolTreeView))
+#define GDU_POOL_TREE_VIEW_CLASS(obj)       (G_TYPE_CHECK_CLASS_CAST ((obj), GDU_POOL_TREE_VIEW,  GduPoolTreeViewClass))
+#define GDU_IS_POOL_TREE_VIEW(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDU_TYPE_POOL_TREE_VIEW))
+#define GDU_IS_POOL_TREE_VIEW_CLASS(obj)    (G_TYPE_CHECK_CLASS_TYPE ((obj), GDU_TYPE_POOL_TREE_VIEW))
+#define GDU_POOL_TREE_VIEW_GET_CLASS        (G_TYPE_INSTANCE_GET_CLASS ((obj), GDU_TYPE_POOL_TREE_VIEW, GduPoolTreeViewClass))
+
+typedef struct GduPoolTreeViewClass       GduPoolTreeViewClass;
+typedef struct GduPoolTreeViewPrivate     GduPoolTreeViewPrivate;
+
+struct GduPoolTreeView
+{
+        GtkTreeView parent;
+
+        /*< private >*/
+        GduPoolTreeViewPrivate *priv;
+};
+
+struct GduPoolTreeViewClass
+{
+        GtkTreeViewClass parent_class;
+};
+
+
+GType            gdu_pool_tree_view_get_type                 (void) G_GNUC_CONST;
+GtkWidget       *gdu_pool_tree_view_new                      (GduPoolTreeModel *model);
+GduPresentable  *gdu_pool_tree_view_get_selected_presentable (GduPoolTreeView  *view);
+void             gdu_pool_tree_view_select_presentable       (GduPoolTreeView  *view,
+                                                              GduPresentable   *presentable);
+void             gdu_pool_tree_view_select_first_presentable (GduPoolTreeView  *view);
+
+#endif /* GDU_POOL_TREE_VIEW_H */
diff --git a/src/palimpsest/Makefile.am b/src/palimpsest/Makefile.am
index a2b6446..a59f258 100644
--- a/src/palimpsest/Makefile.am
+++ b/src/palimpsest/Makefile.am
@@ -19,7 +19,6 @@ palimpsest_SOURCES = 									\
 	gdu-section-encrypted.h			gdu-section-encrypted.c			\
 	gdu-section-linux-md-drive.h		gdu-section-linux-md-drive.c		\
 	gdu-section-no-media.h			gdu-section-no-media.c			\
-	gdu-tree.h				gdu-tree.c				\
 	$(NULL)
 
 palimpsest_CPPFLAGS = 					\
diff --git a/src/palimpsest/gdu-section-linux-md-drive.c b/src/palimpsest/gdu-section-linux-md-drive.c
index b85d71b..976512b 100644
--- a/src/palimpsest/gdu-section-linux-md-drive.c
+++ b/src/palimpsest/gdu-section-linux-md-drive.c
@@ -29,7 +29,6 @@
 #include <gdu/gdu.h>
 #include <gdu-gtk/gdu-gtk.h>
 
-#include "gdu-tree.h"
 #include "gdu-section-linux-md-drive.h"
 
 struct _GduSectionLinuxMdDrivePrivate
@@ -96,6 +95,8 @@ on_add_clicked (GtkButton *button,
         char *array_name;
         char *s;
         char *s2;
+        GtkWidget *scrolled_window;
+        GduPoolTreeModel *model;
 
         device = NULL;
         selected_device = NULL;
@@ -164,14 +165,14 @@ on_add_clicked (GtkButton *button,
         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
         gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
 
-
-        GtkWidget *scrolled_window;
         scrolled_window = gtk_scrolled_window_new (NULL, NULL);
         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                                         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
                                              GTK_SHADOW_IN);
-        tree_view = gdu_device_tree_new (pool);
+        model = gdu_pool_tree_model_new (pool);
+        tree_view = gdu_pool_tree_view_new (model);
+        g_object_unref (model);
         gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
 
 	gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
@@ -184,9 +185,7 @@ on_add_clicked (GtkButton *button,
         gtk_widget_show_all (dialog);
         response = gtk_dialog_run (GTK_DIALOG (dialog));
 
-        selected_presentable = gdu_device_tree_get_selected_presentable (GTK_TREE_VIEW (tree_view));
-        if (selected_presentable != NULL)
-                g_object_ref (selected_presentable);
+        selected_presentable = gdu_pool_tree_view_get_selected_presentable (GDU_POOL_TREE_VIEW (tree_view));
         gtk_widget_destroy (dialog);
 
         if (response < 0)
diff --git a/src/palimpsest/gdu-shell.c b/src/palimpsest/gdu-shell.c
index 9e8b231..df32b7e 100644
--- a/src/palimpsest/gdu-shell.c
+++ b/src/palimpsest/gdu-shell.c
@@ -33,7 +33,6 @@
 #include <gdu-gtk/gdu-gtk.h>
 
 #include "gdu-shell.h"
-#include "gdu-tree.h"
 
 #include "gdu-section-health.h"
 #include "gdu-section-partition.h"
@@ -52,7 +51,7 @@ struct _GduShellPrivate
         GtkWidget *app_window;
         GduPool *pool;
 
-        GtkWidget *treeview;
+        GtkWidget *tree_view;
 
         GtkWidget *icon_image;
         GtkWidget *name_label;
@@ -138,8 +137,8 @@ gdu_shell_get_selected_presentable (GduShell *shell)
 void
 gdu_shell_select_presentable (GduShell *shell, GduPresentable *presentable)
 {
-        gdu_device_tree_select_presentable (GTK_TREE_VIEW (shell->priv->treeview), presentable);
-        gtk_widget_grab_focus (shell->priv->treeview);
+        gdu_pool_tree_view_select_presentable (GDU_POOL_TREE_VIEW (shell->priv->tree_view), presentable);
+        gtk_widget_grab_focus (shell->priv->tree_view);
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -811,10 +810,8 @@ device_tree_changed (GtkTreeSelection *selection, gpointer user_data)
 {
         GduShell *shell = GDU_SHELL (user_data);
         GduPresentable *presentable;
-        GtkTreeView *device_tree_view;
 
-        device_tree_view = gtk_tree_selection_get_tree_view (selection);
-        presentable = gdu_device_tree_get_selected_presentable (device_tree_view);
+        presentable = gdu_pool_tree_view_get_selected_presentable (GDU_POOL_TREE_VIEW (shell->priv->tree_view));
 
         if (presentable != NULL) {
 
@@ -835,6 +832,8 @@ device_tree_changed (GtkTreeSelection *selection, gpointer user_data)
                                   (GCallback) presentable_job_changed, shell);
 
                 gdu_shell_update (shell);
+
+                g_object_unref (presentable);
         }
 }
 
@@ -862,8 +861,8 @@ presentable_removed (GduPool *pool, GduPresentable *presentable, gpointer user_d
                         gdu_shell_select_presentable (shell, enclosing_presentable);
                         g_object_unref (enclosing_presentable);
                 } else {
-                        gdu_device_tree_select_first_presentable (GTK_TREE_VIEW (shell->priv->treeview));
-                        gtk_widget_grab_focus (shell->priv->treeview);
+                        gdu_pool_tree_view_select_first_presentable (GDU_POOL_TREE_VIEW (shell->priv->tree_view));
+                        gtk_widget_grab_focus (shell->priv->tree_view);
                 }
         }
         gdu_shell_update (shell);
@@ -1559,6 +1558,25 @@ help_contents_action_callback (GtkAction *action, gpointer user_data)
 }
 
 static void
+new_linud_md_array_callback (GtkAction *action, gpointer user_data)
+{
+        GduShell *shell = GDU_SHELL (user_data);
+        GtkWidget *dialog;
+        gint response;
+
+        g_debug ("New Linux MD Array!");
+
+        dialog = gdu_create_linux_md_dialog_new (GTK_WINDOW (shell->priv->app_window),
+                                                 shell->priv->pool);
+
+        gtk_widget_show_all (dialog);
+        response = gtk_dialog_run (GTK_DIALOG (dialog));
+        gtk_widget_destroy (dialog);
+
+        g_debug ("response = %d", response);
+}
+
+static void
 quit_action_callback (GtkAction *action, gpointer user_data)
 {
         gtk_main_quit ();
@@ -1601,6 +1619,9 @@ static const gchar *ui =
         "<ui>"
         "  <menubar>"
         "    <menu action='file'>"
+        "      <menu action='file-new'>"
+        "        <menuitem action='file-new-linux-md-array'/>"
+        "      </menu>"
         "      <menuitem action='quit'/>"
         "    </menu>"
         "    <menu action='edit'>"
@@ -1644,6 +1665,8 @@ static const gchar *ui =
 
 static GtkActionEntry entries[] = {
         {"file", NULL, N_("_File"), NULL, NULL, NULL },
+        {"file-new", NULL, N_("_New"), NULL, NULL, NULL },
+        {"file-new-linux-md-array", "gdu-raid-array", N_("Software _RAID Array"), NULL, N_("Create a new Software RAID array"), G_CALLBACK (new_linud_md_array_callback)},
         {"edit", NULL, N_("_Edit"), NULL, NULL, NULL },
         {"help", NULL, N_("_Help"), NULL, NULL, NULL },
 
@@ -1861,7 +1884,7 @@ create_window (GduShell *shell)
         GtkWidget *toolbar;
         GtkAccelGroup *accel_group;
         GtkWidget *hpane;
-        GtkWidget *treeview_scrolled_window;
+        GtkWidget *tree_view_scrolled_window;
         GtkTreeSelection *select;
         GtkWidget *content_area;
         GtkWidget *button;
@@ -1870,6 +1893,7 @@ create_window (GduShell *shell)
         GtkWidget *vbox3;
         GtkWidget *hbox;
         GtkWidget *image;
+        GduPoolTreeModel *model;
 
         shell->priv->pool = gdu_pool_new ();
 
@@ -1891,14 +1915,16 @@ create_window (GduShell *shell)
         gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
 
         /* tree view */
-        treeview_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
-        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (treeview_scrolled_window),
+        tree_view_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (tree_view_scrolled_window),
                                         GTK_POLICY_NEVER,
                                         GTK_POLICY_AUTOMATIC);
-        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (treeview_scrolled_window),
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (tree_view_scrolled_window),
                                              GTK_SHADOW_IN);
-        shell->priv->treeview = gdu_device_tree_new (shell->priv->pool);
-        gtk_container_add (GTK_CONTAINER (treeview_scrolled_window), shell->priv->treeview);
+        model = gdu_pool_tree_model_new (shell->priv->pool);
+        shell->priv->tree_view = gdu_pool_tree_view_new (model);
+        g_object_unref (model);
+        gtk_container_add (GTK_CONTAINER (tree_view_scrolled_window), shell->priv->tree_view);
 
         /* --- */
 
@@ -1988,18 +2014,18 @@ create_window (GduShell *shell)
 
         /* setup and add horizontal pane */
         hpane = gtk_hpaned_new ();
-        gtk_paned_add1 (GTK_PANED (hpane), treeview_scrolled_window);
+        gtk_paned_add1 (GTK_PANED (hpane), tree_view_scrolled_window);
         gtk_paned_add2 (GTK_PANED (hpane), vbox1);
         //gtk_paned_set_position (GTK_PANED (hpane), 260);
 
         gtk_box_pack_start (GTK_BOX (vbox), hpane, TRUE, TRUE, 0);
 
-        select = gtk_tree_view_get_selection (GTK_TREE_VIEW (shell->priv->treeview));
+        select = gtk_tree_view_get_selection (GTK_TREE_VIEW (shell->priv->tree_view));
         gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
         g_signal_connect (select, "changed", (GCallback) device_tree_changed, shell);
 
         /* when starting up, set focus on tree view */
-        gtk_widget_grab_focus (shell->priv->treeview);
+        gtk_widget_grab_focus (shell->priv->tree_view);
 
         g_signal_connect (shell->priv->pool, "presentable-added", (GCallback) presentable_added, shell);
         g_signal_connect (shell->priv->pool, "presentable-removed", (GCallback) presentable_removed, shell);
@@ -2007,6 +2033,6 @@ create_window (GduShell *shell)
 
         gtk_widget_show_all (vbox);
 
-        gdu_device_tree_select_first_presentable (GTK_TREE_VIEW (shell->priv->treeview));
+        gdu_pool_tree_view_select_first_presentable (GDU_POOL_TREE_VIEW (shell->priv->tree_view));
 }
 



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