[gnome-disk-utility] More detail in the TreeView and incremental work on the Create RAID dialog
- From: David Zeuthen <davidz src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-disk-utility] More detail in the TreeView and incremental work on the Create RAID dialog
- Date: Tue, 4 Aug 2009 17:39:52 +0000 (UTC)
commit 38fd7da105fbf80db78be64641c898aa59f8a08f
Author: David Zeuthen <davidz redhat com>
Date: Tue Aug 4 13:10:47 2009 -0400
More detail in the TreeView and incremental work on the Create RAID dialog
src/gdu-gtk/Makefile.am | 40 ++-
src/gdu-gtk/gdu-create-linux-md-dialog.c | 673 +++++++++++++++++++++++++--
src/gdu-gtk/gdu-create-linux-md-dialog.h | 20 +-
src/gdu-gtk/gdu-gtk-enums.h | 61 +++
src/gdu-gtk/gdu-gtk-enumtypes.c.template | 39 ++
src/gdu-gtk/gdu-gtk-enumtypes.h.template | 24 +
src/gdu-gtk/gdu-gtk-types.h | 4 +
src/gdu-gtk/gdu-gtk.h | 2 +
src/gdu-gtk/gdu-pool-tree-model.c | 91 +++--
src/gdu-gtk/gdu-pool-tree-model.h | 6 -
src/gdu-gtk/gdu-pool-tree-view.c | 189 +++++++-
src/gdu-gtk/gdu-pool-tree-view.h | 12 +-
src/gdu-gtk/gdu-size-widget.c | 408 ++++++++++++++++
src/gdu-gtk/gdu-size-widget.h | 72 +++
src/gdu/gdu-drive.c | 219 ++++++++-
src/gdu/gdu-linux-md-drive.c | 114 ++++-
src/gdu/gdu-presentable.c | 23 +-
src/gdu/gdu-presentable.h | 6 +-
src/gdu/gdu-volume-hole.c | 9 +-
src/gdu/gdu-volume.c | 78 +++-
src/palimpsest/gdu-section-linux-md-drive.c | 2 +-
src/palimpsest/gdu-shell.c | 3 +-
22 files changed, 1907 insertions(+), 188 deletions(-)
---
diff --git a/src/gdu-gtk/Makefile.am b/src/gdu-gtk/Makefile.am
index 62608e6..21fa964 100644
--- a/src/gdu-gtk/Makefile.am
+++ b/src/gdu-gtk/Makefile.am
@@ -1,6 +1,26 @@
NULL =
+gdu-gtk-enumtypes.h: gdu-gtk-enums.h gdu-gtk-enumtypes.h.template
+ ( top_builddir=`cd $(top_builddir) && pwd`; \
+ cd $(srcdir) && glib-mkenums --template gdu-gtk-enumtypes.h.template gdu-gtk-enums.h ) > \
+ gdu-gtk-enumtypes.h.tmp && mv gdu-gtk-enumtypes.h.tmp gdu-gtk-enumtypes.h
+
+gdu-gtk-enumtypes.c: gdu-gtk-enums.h gdu-gtk-enumtypes.c.template
+ ( top_builddir=`cd $(top_builddir) && pwd`; \
+ cd $(srcdir) && glib-mkenums --template gdu-gtk-enumtypes.c.template gdu-gtk-enums.h ) > \
+ gdu-gtk-enumtypes.c.tmp && mv gdu-gtk-enumtypes.c.tmp gdu-gtk-enumtypes.c
+
+BUILT_SOURCES = \
+ gdu-gtk-enumtypes.c \
+ gdu-gtk-enumtypes.h \
+ $(NULL)
+
+EXTRADIST = \
+ gdu-gtk-enumtypes.h.template \
+ gdu-gtk-enumtypes.c.template \
+ $(NULL)
+
lib_LTLIBRARIES=libgdu-gtk.la
libgdu_gtkincludedir=$(includedir)/gnome-disk-utility/gdu-gtk
@@ -8,19 +28,25 @@ libgdu_gtkincludedir=$(includedir)/gnome-disk-utility/gdu-gtk
libgdu_gtkinclude_HEADERS = \
gdu-gtk.h \
gdu-gtk-types.h \
+ gdu-gtk-enums.h \
+ gdu-gtk-enumtypes.h \
gdu-time-label.h \
gdu-pool-tree-view.h \
gdu-pool-tree-model.h \
+ gdu-size-widget.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 \
+libgdu_gtk_la_SOURCES = \
+ gdu-gtk.h gdu-gtk.c \
+ gdu-gtk-enums.h \
+ gdu-gtk-enumtypes.h gdu-gtk-enumtypes.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-size-widget.h gdu-size-widget.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
index 82a66ae..45dbc25 100644
--- a/src/gdu-gtk/gdu-create-linux-md-dialog.c
+++ b/src/gdu-gtk/gdu-create-linux-md-dialog.c
@@ -20,16 +20,44 @@
* Author: David Zeuthen <davidz redhat com>
*/
+#define _GNU_SOURCE
+
#include "config.h"
#include <glib/gi18n-lib.h>
+#include <math.h>
+
#include "gdu-create-linux-md-dialog.h"
+#include "gdu-size-widget.h"
struct GduCreateLinuxMdDialogPrivate
{
- gchar *level;
GduPool *pool;
+ GduPoolTreeModel *model;
+
+ /* represents user selected options */
+ gchar *level;
+ guint num_disks;
+ guint64 component_size;
+ guint64 total_size;
+
+ /* Number of disks with room for components */
+ guint available_num_disks;
+
+ /* The maximum possible size of the array - this is a function of available_num_disks
+ * and num_disks and how each disk is laid out. Is 0 if an array for the given
+ * configuration cannot be created.
+ */
+ guint64 available_total_size;
+
GtkWidget *name_entry;
+ GtkWidget *num_disks_spin_button;
+ GtkWidget *size_widget;
+ GtkWidget *tree_view;
+
+ GtkWidget *tip_container;
+ GtkWidget *tip_image;
+ GtkWidget *tip_label;
};
enum
@@ -42,6 +70,32 @@ enum
static void gdu_create_linux_md_dialog_constructed (GObject *object);
+static void update (GduCreateLinuxMdDialog *dialog);
+
+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 on_row_changed (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data);
+
+static void on_row_deleted (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ gpointer user_data);
+
+static void on_row_inserted (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data);
+
G_DEFINE_TYPE (GduCreateLinuxMdDialog, gdu_create_linux_md_dialog, GTK_TYPE_DIALOG)
static void
@@ -49,7 +103,15 @@ gdu_create_linux_md_dialog_finalize (GObject *object)
{
GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (object);
+ g_signal_handlers_disconnect_by_func (dialog->priv->pool, on_presentable_added, dialog);
+ g_signal_handlers_disconnect_by_func (dialog->priv->pool, on_presentable_removed, dialog);
+ g_signal_handlers_disconnect_by_func (dialog->priv->pool, on_presentable_changed, dialog);
+ g_signal_handlers_disconnect_by_func (dialog->priv->model, on_row_changed, dialog);
+ g_signal_handlers_disconnect_by_func (dialog->priv->model, on_row_deleted, dialog);
+ g_signal_handlers_disconnect_by_func (dialog->priv->model, on_row_inserted, dialog);
+
g_object_unref (dialog->priv->pool);
+ g_object_unref (dialog->priv->model);
g_free (dialog->priv->level);
if (G_OBJECT_CLASS (gdu_create_linux_md_dialog_parent_class)->finalize != NULL)
@@ -58,9 +120,9 @@ gdu_create_linux_md_dialog_finalize (GObject *object)
static void
gdu_create_linux_md_dialog_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (object);
@@ -85,9 +147,9 @@ gdu_create_linux_md_dialog_get_property (GObject *object,
static void
gdu_create_linux_md_dialog_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (object);
@@ -231,7 +293,7 @@ on_combo_box_changed (GtkWidget *combo_box,
static void
on_name_entry_activated (GtkWidget *combo_box,
- gpointer user_data)
+ gpointer user_data)
{
GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (user_data);
@@ -241,6 +303,28 @@ on_name_entry_activated (GtkWidget *combo_box,
/* ---------------------------------------------------------------------------------------------------- */
static void
+on_num_disks_spin_button_value_changed (GtkSpinButton *spin_button,
+ gpointer user_data)
+{
+ GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (user_data);
+
+ dialog->priv->num_disks = (gint) gtk_spin_button_get_value (spin_button);
+
+ update (dialog);
+}
+
+static void
+on_size_widget_changed (GduSizeWidget *widget,
+ gpointer user_data)
+{
+ GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (user_data);
+
+ dialog->priv->total_size = (guint64) gdu_size_widget_get_size (widget);
+
+ update (dialog);
+}
+
+static void
gdu_create_linux_md_dialog_constructed (GObject *object)
{
GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (object);
@@ -252,8 +336,10 @@ gdu_create_linux_md_dialog_constructed (GObject *object)
GtkWidget *table;
GtkWidget *entry;
GtkWidget *combo_box;
+ GtkWidget *vbox;
GtkWidget *vbox2;
- GdkPixbuf *pixbuf;
+ GtkWidget *spin_button;
+ GtkWidget *size_widget;
gint row;
gboolean ret;
GtkWidget *align;
@@ -261,44 +347,39 @@ gdu_create_linux_md_dialog_constructed (GObject *object)
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_window_set_title (GTK_WINDOW (dialog), _("Create RAID Array"));
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), "gdu-raid-array");
gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
button = gtk_dialog_add_button (GTK_DIALOG (dialog),
- _("C_reate"),
+ _("Cr_eate"),
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);
+ //vbox = gtk_vbox_new (FALSE, 0);
+ //gtk_container_add (GTK_CONTAINER (content_area), vbox);
+ vbox = content_area;
- 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);
+ label = gtk_label_new (NULL);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ s = g_strconcat ("<b>", _("General"), "</b>", NULL);
+ gtk_label_set_markup (GTK_LABEL (label), s);
+ g_free (s);
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
vbox2 = gtk_vbox_new (FALSE, 12);
+ align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (align), 6, 0, 12, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
gtk_container_add (GTK_CONTAINER (align), vbox2);
row = 0;
@@ -308,7 +389,7 @@ gdu_create_linux_md_dialog_constructed (GObject *object)
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
gtk_box_pack_start (GTK_BOX (vbox2), table, FALSE, FALSE, 0);
- /* filesystem type */
+ /* RAID level */
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:"));
@@ -337,7 +418,7 @@ gdu_create_linux_md_dialog_constructed (GObject *object)
gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo_box);
row++;
- /* filesystem label */
+ /* array name */
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:"));
@@ -353,31 +434,91 @@ gdu_create_linux_md_dialog_constructed (GObject *object)
dialog->priv->name_entry = entry;
row++;
- /* -------------------------------------------------------------------------------- */
+ /* Number of components */
+ 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), _("Number of _Disks:"));
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+
+
+ spin_button = gtk_spin_button_new_with_range (2, 10000, 1);
+ dialog->priv->num_disks_spin_button = spin_button;
+ g_signal_connect (spin_button,
+ "value-changed",
+ G_CALLBACK (on_num_disks_spin_button_value_changed),
+ dialog);
- /* component tree-views */
+ align = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
+ gtk_container_add (GTK_CONTAINER (align), spin_button);
+
+ gtk_table_attach (GTK_TABLE (table),
+ align,
+ 1, 2,
+ row, row + 1,
+ GTK_EXPAND | GTK_FILL,
+ GTK_EXPAND | GTK_FILL, 2, 2);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), spin_button);
+ row++;
+
+ /* Size */
+ 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), _("Array _Size:"));
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+ size_widget = gdu_size_widget_new (1000 * 1000,
+ 1000 * 1000,
+ 10 * 1000 * 1000);
+ dialog->priv->size_widget = size_widget;
+ g_signal_connect (size_widget,
+ "changed",
+ G_CALLBACK (on_size_widget_changed),
+ dialog);
+ gtk_table_attach (GTK_TABLE (table), size_widget, 1, 2, row, row + 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), size_widget);
+ row++;
/* -------------------------------------------------------------------------------- */
- hbox = gtk_hbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
+ /* Tree view for showing selected volumes */
+ GtkWidget *tree_view;
+ GtkWidget *scrolled_window;
+
+ dialog->priv->model = gdu_pool_tree_model_new (dialog->priv->pool);
+
+ tree_view = gdu_pool_tree_view_new (dialog->priv->model,
+ GDU_POOL_TREE_VIEW_FLAGS_SHOW_TOGGLE);
+ dialog->priv->tree_view = tree_view;
- 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);
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_SHADOW_IN);
- label = gtk_label_new (NULL);
- s = g_strconcat ("<i>",
- _("Warning: All data on the volume will be irrevocably lost."),
- "</i>",
- NULL);
+ gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
+
+ label = gtk_label_new (NULL);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ s = g_strconcat ("<b>", _("Components"), "</b>", 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);
+ gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+ vbox2 = gtk_vbox_new (FALSE, 12);
+ align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (align), 6, 0, 12, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (align), vbox2);
+ gtk_box_pack_start (GTK_BOX (vbox2), scrolled_window, TRUE, TRUE, 0);
+
+ /* -------------------------------------------------------------------------------- */
g_signal_connect (combo_box,
"changed",
@@ -392,8 +533,450 @@ gdu_create_linux_md_dialog_constructed (GObject *object)
gtk_widget_grab_focus (dialog->priv->name_entry);
gtk_editable_select_region (GTK_EDITABLE (dialog->priv->name_entry), 0, 1000);
+
+ /* -------------------------------------------------------------------------------- */
+
+ g_signal_connect (dialog->priv->pool,
+ "presentable-added",
+ G_CALLBACK (on_presentable_added),
+ dialog);
+ g_signal_connect (dialog->priv->pool,
+ "presentable-removed",
+ G_CALLBACK (on_presentable_removed),
+ dialog);
+ g_signal_connect (dialog->priv->pool,
+ "presentable-changed",
+ G_CALLBACK (on_presentable_changed),
+ dialog);
+ g_signal_connect (dialog->priv->model,
+ "row-changed",
+ G_CALLBACK (on_row_changed),
+ dialog);
+ g_signal_connect (dialog->priv->model,
+ "row-deleted",
+ G_CALLBACK (on_row_deleted),
+ dialog);
+ g_signal_connect (dialog->priv->model,
+ "row-inserted",
+ G_CALLBACK (on_row_inserted),
+ dialog);
+
+ 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_INFO, GTK_ICON_SIZE_MENU);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0);
+
+ label = gtk_label_new (NULL);
+ 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);
+
+ dialog->priv->tip_container = hbox;
+ dialog->priv->tip_image = image;
+ dialog->priv->tip_label = label;
+ gtk_widget_set_no_show_all (hbox, TRUE);
+
+ /* update the dialog */
+ update (dialog);
+
+ /* and start out with selecting max size */
+ gdu_size_widget_set_size (GDU_SIZE_WIDGET (dialog->priv->size_widget),
+ dialog->priv->available_total_size);
+
+ /* select a sane size for the dialog and allow resizing */
+ gtk_widget_set_size_request (GTK_WIDGET (dialog), 400, 450);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+
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);
}
/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_presentable_added (GduPool *pool,
+ GduPresentable *presentable,
+ gpointer user_data)
+{
+ GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (user_data);
+ update (dialog);
+}
+
+static void
+on_presentable_removed (GduPool *pool,
+ GduPresentable *presentable,
+ gpointer user_data)
+{
+ GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (user_data);
+ update (dialog);
+}
+
+static void
+on_presentable_changed (GduPool *pool,
+ GduPresentable *presentable,
+ gpointer user_data)
+{
+ GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (user_data);
+ update (dialog);
+}
+
+static void
+on_row_changed (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (user_data);
+ update (dialog);
+}
+
+static void
+on_row_deleted (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ gpointer user_data)
+{
+ GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (user_data);
+ update (dialog);
+}
+
+static void
+on_row_inserted (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ GduCreateLinuxMdDialog *dialog = GDU_CREATE_LINUX_MD_DIALOG (user_data);
+ update (dialog);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gint
+guint64_compare (gconstpointer a,
+ gconstpointer b)
+{
+ guint64 va, vb;
+ va = *((guint64 *) a);
+ vb = *((guint64 *) b);
+ if (va > vb)
+ return 1;
+ else if (va < vb)
+ return -1;
+ else
+ return 0;
+}
+
+static gboolean
+get_selected_foreach_func (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ GList **ret = user_data;
+ gboolean toggled;
+ GduPresentable *presentable;
+
+ gtk_tree_model_get (model,
+ iter,
+ GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE, &presentable,
+ GDU_POOL_TREE_MODEL_COLUMN_TOGGLED, &toggled,
+ -1);
+ if (presentable != NULL) {
+ if (toggled)
+ *ret = g_list_prepend (*ret, g_object_ref (presentable));
+ g_object_unref (presentable);
+ }
+
+ return FALSE; /* keep iterating */
+}
+
+
+static GList *
+get_selected_presentables (GduCreateLinuxMdDialog *dialog)
+{
+ GList *ret;
+ ret = NULL;
+ gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->priv->model),
+ get_selected_foreach_func,
+ &ret);
+ return ret;
+}
+
+static void
+update (GduCreateLinuxMdDialog *dialog)
+{
+ GList *l;
+ GList *presentables;
+ GHashTable *map_disks_to_biggest_component_size;
+ GList *selected_presentables;
+ GList *drives_for_selected_presentables;
+ gboolean can_create;
+ guint num_toggled;
+ gchar *tip_text;
+ const gchar *tip_stock_icon;
+
+ tip_text = NULL;
+ tip_stock_icon = NULL;
+
+ can_create = FALSE;
+
+ if (dialog->priv->num_disks < 2)
+ dialog->priv->num_disks = 2;
+
+ presentables = gdu_pool_get_presentables (dialog->priv->pool);
+ selected_presentables = get_selected_presentables (dialog);
+ drives_for_selected_presentables = NULL;
+ for (l = selected_presentables; l != NULL; l = l->next) {
+ GduPresentable *p = GDU_PRESENTABLE (l->data);
+ GduPresentable *drive;
+
+ drive = gdu_presentable_get_toplevel (p);
+ if (drive == NULL)
+ continue;
+
+ g_object_unref (drive); /* don't own the ref */
+ if (!GDU_IS_DRIVE (drive))
+ continue;
+
+ if (g_list_find (drives_for_selected_presentables, drive) == NULL)
+ drives_for_selected_presentables = g_list_prepend (drives_for_selected_presentables, drive);
+ }
+
+ /* hash from drive to largest free component */
+ map_disks_to_biggest_component_size = g_hash_table_new_full ((GHashFunc) gdu_presentable_hash,
+ (GEqualFunc) gdu_presentable_equals,
+ g_object_unref,
+ g_free);
+ for (l = presentables; l != NULL; l = l->next) {
+ GduPresentable *p = GDU_PRESENTABLE (l->data);
+ GduPresentable *drive;
+ guint64 size;
+ guint64 *existing_size;
+
+ if (gdu_presentable_is_allocated (p))
+ continue;
+
+ drive = gdu_presentable_get_toplevel (p);
+ if (drive == NULL)
+ continue;
+
+ g_object_unref (drive); /* don't own the ref */
+ if (!GDU_IS_DRIVE (drive))
+ continue;
+
+ size = gdu_presentable_get_size (p);
+
+ existing_size = g_hash_table_lookup (map_disks_to_biggest_component_size,
+ drive);
+ if ((existing_size == NULL) || (existing_size != NULL && (*existing_size) > size)) {
+ g_hash_table_insert (map_disks_to_biggest_component_size,
+ g_object_ref (drive),
+ g_memdup (&size, sizeof (guint64)));
+ }
+ }
+
+ dialog->priv->available_num_disks = g_hash_table_size (map_disks_to_biggest_component_size);
+
+ if (dialog->priv->num_disks > dialog->priv->available_num_disks) {
+ dialog->priv->available_total_size = 0;
+ } else {
+ GList *sizes;
+
+ sizes = g_hash_table_get_values (map_disks_to_biggest_component_size);
+ sizes = g_list_sort (sizes, guint64_compare);
+ sizes = g_list_reverse (sizes);
+ /* biggest is now first */
+
+ dialog->priv->available_total_size = dialog->priv->num_disks *
+ (*((guint64 *) g_list_nth_data (sizes, dialog->priv->num_disks - 1)));
+
+ g_list_free (sizes);
+ }
+
+ /* clamp total_size and num_disks to what is available */
+ if (dialog->priv->total_size > dialog->priv->available_total_size)
+ dialog->priv->total_size = dialog->priv->available_total_size;
+ if (dialog->priv->num_disks > dialog->priv->available_num_disks)
+ dialog->priv->num_disks = dialog->priv->available_num_disks;
+
+ //if (dialog->priv->total_size == 0)
+ // dialog->priv->total_size = dialog->priv->available_total_size;
+
+ g_debug ("==========");
+ g_debug ("available_num_disks = %d", dialog->priv->available_num_disks);
+ g_debug ("available_total_size = %" G_GUINT64_FORMAT, dialog->priv->available_total_size);
+ g_debug ("num_disks = %d", dialog->priv->num_disks);
+ g_debug ("total_size = %" G_GUINT64_FORMAT, dialog->priv->total_size);
+
+ if (dialog->priv->available_total_size == 0) {
+ gtk_widget_set_sensitive (dialog->priv->size_widget, FALSE);
+ gtk_widget_set_sensitive (dialog->priv->tree_view, FALSE);
+ tip_text = g_strdup (_("Not enough disks with available space. "
+ "Plug in more disks or make space available."));
+ tip_stock_icon = GTK_STOCK_DIALOG_ERROR;
+ } else {
+ gtk_widget_set_sensitive (dialog->priv->size_widget, TRUE);
+ gtk_widget_set_sensitive (dialog->priv->tree_view, TRUE);
+ }
+
+ /* set range for num_disks_spin_button according to what we've found out */
+ gtk_spin_button_set_range (GTK_SPIN_BUTTON (dialog->priv->num_disks_spin_button),
+ 2.0,
+ dialog->priv->available_num_disks);
+ if (gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->priv->num_disks_spin_button)) != dialog->priv->num_disks)
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->num_disks_spin_button),
+ dialog->priv->num_disks);
+
+ /* ditto for the size widget */
+ gdu_size_widget_set_max_size (GDU_SIZE_WIDGET (dialog->priv->size_widget),
+ dialog->priv->available_total_size);
+ if (gdu_size_widget_get_size (GDU_SIZE_WIDGET (dialog->priv->size_widget)) != dialog->priv->total_size)
+ gdu_size_widget_set_size (GDU_SIZE_WIDGET (dialog->priv->size_widget),
+ dialog->priv->total_size);
+
+ /* --- */
+
+ /* now update the tree model toggles to make free space objects selectable */
+ num_toggled = 0;
+ for (l = presentables; l != NULL; l = l->next) {
+ GduPresentable *p = GDU_PRESENTABLE (l->data);
+ GduPresentable *drive;
+ guint64 size;
+ gboolean can_be_toggled;
+ GtkTreeIter iter;
+ gboolean cur_can_be_toggled;
+ gboolean cur_toggled;
+
+ can_be_toggled = FALSE;
+
+ if (gdu_presentable_is_allocated (p))
+ goto determined;
+
+ drive = gdu_presentable_get_toplevel (p);
+ if (drive == NULL)
+ goto determined;
+
+ g_object_unref (drive); /* don't own the ref */
+ if (!GDU_IS_DRIVE (drive))
+ goto determined;
+
+ size = gdu_presentable_get_size (p);
+
+ if (size < dialog->priv->total_size / dialog->priv->num_disks)
+ goto determined;
+
+ /* don't allow selecting two volumes on the same drive */
+ if (g_list_find (drives_for_selected_presentables, drive) != NULL &&
+ g_list_find (selected_presentables, p) == NULL)
+ goto determined;
+
+ can_be_toggled = TRUE;
+
+ determined:
+ if (!gdu_pool_tree_model_get_iter_for_presentable (dialog->priv->model,
+ p,
+ &iter)) {
+ g_warning ("Cannot find tree iter for presentable");
+ continue;
+ }
+
+ /* only update if there's a change - otherwise we'll cause loops */
+ gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->model),
+ &iter,
+ GDU_POOL_TREE_MODEL_COLUMN_CAN_BE_TOGGLED, &cur_can_be_toggled,
+ GDU_POOL_TREE_MODEL_COLUMN_TOGGLED, &cur_toggled,
+ -1);
+
+ if (cur_can_be_toggled != can_be_toggled) {
+ gtk_tree_store_set (GTK_TREE_STORE (dialog->priv->model),
+ &iter,
+ GDU_POOL_TREE_MODEL_COLUMN_CAN_BE_TOGGLED, can_be_toggled,
+ -1);
+ }
+ if (!can_be_toggled) {
+ if (cur_toggled) {
+ gtk_tree_store_set (GTK_TREE_STORE (dialog->priv->model),
+ &iter,
+ GDU_POOL_TREE_MODEL_COLUMN_TOGGLED, FALSE,
+ -1);
+ cur_toggled = FALSE;
+ }
+ }
+
+ if (cur_toggled)
+ num_toggled++;
+ }
+
+ /* --- */
+
+ if (num_toggled == dialog->priv->num_disks) {
+ can_create = TRUE;
+ if (tip_text == NULL) {
+ if (dialog->priv->total_size < 1000 * 1000) {
+ tip_text = g_strdup (_("Increase the size of the array."));
+ tip_stock_icon = GTK_STOCK_DIALOG_INFO;
+ can_create = FALSE;
+ } else {
+ tip_text = g_strdup (_("Array is ready to be created."));
+ tip_stock_icon = GTK_STOCK_DIALOG_INFO;
+ }
+ }
+ } else if (num_toggled < dialog->priv->num_disks) {
+ if (tip_text == NULL) {
+ tip_text = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
+ N_("Select one more component."),
+ N_("Select %d more components."),
+ dialog->priv->num_disks - num_toggled),
+ dialog->priv->num_disks - num_toggled);
+ tip_stock_icon = GTK_STOCK_DIALOG_INFO;
+ }
+ } else {
+ /* num_toggled > dialog->priv->num_disks */
+ if (tip_text == NULL) {
+ tip_text = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
+ N_("Deselect one more component."),
+ N_("Deselect %d more components."),
+ dialog->priv->num_disks - num_toggled),
+ dialog->priv->num_disks - num_toggled);
+ tip_stock_icon = GTK_STOCK_DIALOG_INFO;
+ }
+ }
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ can_create);
+
+ if (tip_text != NULL) {
+ gchar *s;
+ s = g_strconcat ("<i>",
+ tip_text,
+ "</i>",
+ NULL);
+ gtk_label_set_markup (GTK_LABEL (dialog->priv->tip_label), s);
+ g_free (s);
+ gtk_image_set_from_stock (GTK_IMAGE (dialog->priv->tip_image),
+ tip_stock_icon,
+ GTK_ICON_SIZE_MENU);
+ gtk_widget_show (dialog->priv->tip_container);
+ gtk_widget_show (dialog->priv->tip_image);
+ gtk_widget_show (dialog->priv->tip_label);
+ } else {
+ gtk_widget_hide (dialog->priv->tip_container);
+ gtk_widget_hide (dialog->priv->tip_image);
+ gtk_widget_hide (dialog->priv->tip_label);
+ }
+
+ /* --- */
+
+ g_list_foreach (presentables, (GFunc) g_object_unref, NULL);
+ g_list_free (presentables);
+ g_list_foreach (selected_presentables, (GFunc) g_object_unref, NULL);
+ g_list_free (selected_presentables);
+ g_list_free (drives_for_selected_presentables);
+ g_hash_table_unref (map_disks_to_biggest_component_size);
+ g_free (tip_text);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/gdu-gtk/gdu-create-linux-md-dialog.h b/src/gdu-gtk/gdu-create-linux-md-dialog.h
index 7fad710..51420e6 100644
--- a/src/gdu-gtk/gdu-create-linux-md-dialog.h
+++ b/src/gdu-gtk/gdu-create-linux-md-dialog.h
@@ -27,12 +27,12 @@
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))
+#define GDU_TYPE_CREATE_LINUX_MD_DIALOG (gdu_create_linux_md_dialog_get_type())
+#define GDU_CREATE_LINUX_MD_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_CREATE_LINUX_MD_DIALOG, GduCreateLinuxMdDialog))
+#define GDU_CREATE_LINUX_MD_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GDU_TYPE_CREATE_LINUX_MD_DIALOG, GduCreateLinuxMdDialogClass))
+#define GDU_IS_CREATE_LINUX_MD_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_CREATE_LINUX_MD_DIALOG))
+#define GDU_IS_CREATE_LINUX_MD_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDU_TYPE_CREATE_LINUX_MD_DIALOG))
+#define GDU_CREATE_LINUX_MD_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDU_TYPE_CREATE_LINUX_MD_DIALOG, GduCreateLinuxMdDialogClass))
typedef struct GduCreateLinuxMdDialogClass GduCreateLinuxMdDialogClass;
typedef struct GduCreateLinuxMdDialogPrivate GduCreateLinuxMdDialogPrivate;
@@ -51,10 +51,10 @@ struct GduCreateLinuxMdDialogClass
};
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);
+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
diff --git a/src/gdu-gtk/gdu-gtk-enums.h b/src/gdu-gtk/gdu-gtk-enums.h
new file mode 100644
index 0000000..9f2cc66
--- /dev/null
+++ b/src/gdu-gtk/gdu-gtk-enums.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* gdu-gtk-enums.h
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * 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.
+ */
+
+#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_GTK_ENUMS_H
+#define GDU_GTK_ENUMS_H
+
+#include <glib-object.h>
+
+/**
+ * GduPoolTreeModelColumn:
+ * @GDU_POOL_TREE_MODEL_COLUMN_ICON: The icon for the presentable.
+ * @GDU_POOL_TREE_MODEL_COLUMN_VPD_NAME: Name for the presentable derived from Vital Product Data,
+ * e.g. "ATA INTEL SSDSA2MH080G1GC".
+ * @GDU_POOL_TREE_MODEL_COLUMN_NAME: Human readable name of the presentable, e.g. "80 GB Solid-state Disk" or
+ * "Fedora (Rawhide)".
+ * @GDU_POOL_TREE_MODEL_COLUMN_DESCRIPTION: Human readable description of the presentable, e.g. "MBR Partition Table"
+ * or "32GB Linux ext3".
+ * @GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE: The #GduPresentable object.
+ * @GDU_POOL_TREE_MODEL_COLUMN_TOGGLED: Whether the item can be toggled.
+ * @GDU_POOL_TREE_MODEL_COLUMN_CAN_BE_TOGGLED: Whether the item is toggled.
+ *
+ * Columns used in #GduPoolTreeModel.
+ */
+typedef enum {
+ GDU_POOL_TREE_MODEL_COLUMN_ICON,
+ GDU_POOL_TREE_MODEL_COLUMN_VPD_NAME,
+ GDU_POOL_TREE_MODEL_COLUMN_NAME,
+ GDU_POOL_TREE_MODEL_COLUMN_DESCRIPTION,
+ GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE,
+ GDU_POOL_TREE_MODEL_COLUMN_TOGGLED,
+ GDU_POOL_TREE_MODEL_COLUMN_CAN_BE_TOGGLED,
+} GduPoolTreeModelColumn;
+
+typedef enum {
+ GDU_POOL_TREE_VIEW_FLAGS_NONE = 0,
+ GDU_POOL_TREE_VIEW_FLAGS_SHOW_TOGGLE = (1<<0),
+} GduPoolTreeViewFlags;
+
+#endif /* GDU_GTK_ENUMS_H */
diff --git a/src/gdu-gtk/gdu-gtk-enumtypes.c.template b/src/gdu-gtk/gdu-gtk-enumtypes.c.template
new file mode 100644
index 0000000..9ffe156
--- /dev/null
+++ b/src/gdu-gtk/gdu-gtk-enumtypes.c.template
@@ -0,0 +1,39 @@
+/*** BEGIN file-header ***/
+#include <gdu-gtk/gdu-gtk.h>
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+ enum_name@_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const G Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_ type@_register_static (g_intern_static_string ("@EnumName@"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+/*** END value-tail ***/
+
+/*** BEGIN file-tail ***/
+/*** END file-tail ***/
diff --git a/src/gdu-gtk/gdu-gtk-enumtypes.h.template b/src/gdu-gtk/gdu-gtk-enumtypes.h.template
new file mode 100644
index 0000000..4737f89
--- /dev/null
+++ b/src/gdu-gtk/gdu-gtk-enumtypes.h.template
@@ -0,0 +1,24 @@
+/*** BEGIN file-header ***/
+#ifndef __GDU_GTK_ENUM_TYPES_H__
+#define __GDU_GTK_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name _get_type (void) G_GNUC_CONST;
+#define @ENUMPREFIX _TYPE_@ENUMSHORT@ (@enum_name _get_type ())
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif /* __GDU_GTK_ENUM_TYPES_H__ */
+/*** END file-tail ***/
diff --git a/src/gdu-gtk/gdu-gtk-types.h b/src/gdu-gtk/gdu-gtk-types.h
index e419d75..ca89682 100644
--- a/src/gdu-gtk/gdu-gtk-types.h
+++ b/src/gdu-gtk/gdu-gtk-types.h
@@ -29,6 +29,7 @@
#include <glib-object.h>
#include <gdu/gdu.h>
#include <gtk/gtk.h>
+#include <gdu-gtk/gdu-gtk-enums.h>
G_BEGIN_DECLS
@@ -44,6 +45,9 @@ typedef struct GduPoolTreeView GduPoolTreeView;
struct GduCreateLinuxMdDialog;
typedef struct GduCreateLinuxMdDialog GduCreateLinuxMdDialog;
+struct GduSizeWidget;
+typedef struct GduSizeWidget GduSizeWidget;
+
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 85965e2..054b054 100644
--- a/src/gdu-gtk/gdu-gtk.h
+++ b/src/gdu-gtk/gdu-gtk.h
@@ -28,9 +28,11 @@
#define __GDU_GTK_INSIDE_GDU_GTK_H
#include <gdu-gtk/gdu-gtk-types.h>
+#include <gdu-gtk/gdu-gtk-enumtypes.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-size-widget.h>
#include <gdu-gtk/gdu-create-linux-md-dialog.h>
#undef __GDU_GTK_INSIDE_GDU_GTK_H
diff --git a/src/gdu-gtk/gdu-pool-tree-model.c b/src/gdu-gtk/gdu-pool-tree-model.c
index d29c8a2..56368fa 100644
--- a/src/gdu-gtk/gdu-pool-tree-model.c
+++ b/src/gdu-gtk/gdu-pool-tree-model.c
@@ -142,14 +142,17 @@ static void
gdu_pool_tree_model_constructed (GObject *object)
{
GduPoolTreeModel *model = GDU_POOL_TREE_MODEL (object);
- GType column_types[4];
+ GType column_types[7];
GList *presentables;
GList *l;
column_types[0] = GDK_TYPE_PIXBUF;
column_types[1] = G_TYPE_STRING;
- column_types[2] = GDU_TYPE_PRESENTABLE;
+ column_types[2] = G_TYPE_STRING;
column_types[3] = G_TYPE_STRING;
+ column_types[4] = GDU_TYPE_PRESENTABLE;
+ column_types[5] = G_TYPE_BOOLEAN;
+ column_types[6] = G_TYPE_BOOLEAN;
gtk_tree_store_set_column_types (GTK_TREE_STORE (object),
G_N_ELEMENTS (column_types),
@@ -297,6 +300,49 @@ gdu_pool_tree_model_get_iter_for_presentable (GduPoolTreeModel *model,
/* ---------------------------------------------------------------------------------------------------- */
static void
+set_data_for_presentable (GduPoolTreeModel *model,
+ GtkTreeIter *iter,
+ GduPresentable *presentable)
+{
+ GduDevice *device;
+ GdkPixbuf *pixbuf;
+ gchar *vpd_name;
+ gchar *name;
+ gchar *desc;
+
+ device = gdu_presentable_get_device (presentable);
+
+ name = gdu_presentable_get_name (presentable);
+ desc = gdu_presentable_get_description (presentable);
+
+ // TODO:
+ //vpd_name = gdu_presentable_get_vpd_name (presentable);
+ vpd_name = g_strdup ("foo");
+
+ pixbuf = gdu_util_get_pixbuf_for_presentable (presentable, GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+ /* TODO: insert NAME */
+ gtk_tree_store_set (GTK_TREE_STORE (model),
+ iter,
+ GDU_POOL_TREE_MODEL_COLUMN_ICON, pixbuf,
+ GDU_POOL_TREE_MODEL_COLUMN_VPD_NAME, vpd_name,
+ GDU_POOL_TREE_MODEL_COLUMN_NAME, name,
+ GDU_POOL_TREE_MODEL_COLUMN_DESCRIPTION, desc,
+ GDU_POOL_TREE_MODEL_COLUMN_PRESENTABLE, presentable,
+ GDU_POOL_TREE_MODEL_COLUMN_TOGGLED, FALSE,
+ GDU_POOL_TREE_MODEL_COLUMN_CAN_BE_TOGGLED, FALSE,
+ -1);
+
+ if (pixbuf != NULL)
+ g_object_unref (pixbuf);
+ g_free (vpd_name);
+ g_free (name);
+ g_free (desc);
+ if (device != NULL)
+ g_object_unref (device);
+}
+
+static void
add_presentable (GduPoolTreeModel *model,
GduPresentable *presentable,
GtkTreeIter *iter_out)
@@ -304,8 +350,6 @@ add_presentable (GduPoolTreeModel *model,
GtkTreeIter iter;
GtkTreeIter iter2;
GtkTreeIter *parent_iter;
- GdkPixbuf *pixbuf;
- char *name;
GduPresentable *enclosing_presentable;
/* check to see if presentable is already added */
@@ -327,28 +371,21 @@ add_presentable (GduPoolTreeModel *model,
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);
+
+ set_data_for_presentable (model,
+ &iter,
+ presentable);
+
if (iter_out != NULL)
*iter_out = iter;
- g_free (name);
- if (pixbuf != NULL)
- g_object_unref (pixbuf);
-
out:
;
}
@@ -382,29 +419,13 @@ on_presentable_changed (GduPool *pool,
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);
+ set_data_for_presentable (model,
+ &iter,
+ presentable);
}
}
diff --git a/src/gdu-gtk/gdu-pool-tree-model.h b/src/gdu-gtk/gdu-pool-tree-model.h
index 1a492fb..2e911de 100644
--- a/src/gdu-gtk/gdu-pool-tree-model.h
+++ b/src/gdu-gtk/gdu-pool-tree-model.h
@@ -39,12 +39,6 @@
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;
diff --git a/src/gdu-gtk/gdu-pool-tree-view.c b/src/gdu-gtk/gdu-pool-tree-view.c
index b1084e7..ccb1264 100644
--- a/src/gdu-gtk/gdu-pool-tree-view.c
+++ b/src/gdu-gtk/gdu-pool-tree-view.c
@@ -26,11 +26,12 @@
#include "gdu-pool-tree-view.h"
#include "gdu-pool-tree-model.h"
-
+#include "gdu-gtk-enumtypes.h"
struct GduPoolTreeViewPrivate
{
GduPoolTreeModel *model;
+ GduPoolTreeViewFlags flags;
};
G_DEFINE_TYPE (GduPoolTreeView, gdu_pool_tree_view, GTK_TYPE_TREE_VIEW)
@@ -38,6 +39,7 @@ G_DEFINE_TYPE (GduPoolTreeView, gdu_pool_tree_view, GTK_TYPE_TREE_VIEW)
enum {
PROP_0,
PROP_POOL_TREE_MODEL,
+ PROP_FLAGS,
};
static void
@@ -53,6 +55,10 @@ gdu_pool_tree_view_set_property (GObject *object,
view->priv->model = g_value_dup_object (value);
break;
+ case PROP_FLAGS:
+ view->priv->flags = g_value_get_flags (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -72,6 +78,10 @@ gdu_pool_tree_view_get_property (GObject *object,
g_value_set_object (value, view->priv->model);
break;
+ case PROP_FLAGS:
+ g_value_set_flags (value, view->priv->flags);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -101,6 +111,97 @@ on_row_inserted (GtkTreeModel *tree_model,
}
static void
+on_toggled (GtkCellRendererToggle *renderer,
+ const gchar *path_string,
+ gpointer user_data)
+{
+ GduPoolTreeView *view = GDU_POOL_TREE_VIEW (user_data);
+ GtkTreeIter iter;
+ gboolean value;
+
+ if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (view->priv->model),
+ &iter,
+ path_string))
+ goto out;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (view->priv->model),
+ &iter,
+ GDU_POOL_TREE_MODEL_COLUMN_TOGGLED, &value,
+ -1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (view->priv->model),
+ &iter,
+ GDU_POOL_TREE_MODEL_COLUMN_TOGGLED, !value,
+ -1);
+ out:
+ ;
+}
+
+static void
+format_markup (GtkCellLayout *cell_layout,
+ GtkCellRenderer *renderer,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ GduPoolTreeView *view = GDU_POOL_TREE_VIEW (user_data);
+ GtkTreeSelection *tree_selection;
+ gchar *name;
+ gchar *desc;
+ gchar *markup;
+ GtkStyle *style;
+ GdkColor desc_gdk_color = {0};
+ gchar *desc_color;
+ GtkStateType state;
+
+ tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
+
+ gtk_tree_model_get (tree_model,
+ iter,
+ GDU_POOL_TREE_MODEL_COLUMN_NAME, &name,
+ GDU_POOL_TREE_MODEL_COLUMN_DESCRIPTION, &desc,
+ -1);
+
+ /* This color business shouldn't be this hard... */
+ style = gtk_widget_get_style (GTK_WIDGET (view));
+ if (gtk_tree_selection_iter_is_selected (tree_selection, iter)) {
+ if (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (view)))
+ state = GTK_STATE_SELECTED;
+ else
+ state = GTK_STATE_ACTIVE;
+ } else {
+ state = GTK_STATE_NORMAL;
+ }
+#define BLEND_FACTOR 0.7
+ desc_gdk_color.red = style->text[state].red * BLEND_FACTOR +
+ style->base[state].red * (1.0 - BLEND_FACTOR);
+ desc_gdk_color.green = style->text[state].green * BLEND_FACTOR +
+ style->base[state].green * (1.0 - BLEND_FACTOR);
+ desc_gdk_color.blue = style->text[state].blue * BLEND_FACTOR +
+ style->base[state].blue * (1.0 - BLEND_FACTOR);
+#undef BLEND_FACTOR
+ desc_color = g_strdup_printf ("#%02x%02x%02x",
+ (desc_gdk_color.red >> 8),
+ (desc_gdk_color.green >> 8),
+ (desc_gdk_color.blue >> 8));
+
+ markup = g_strdup_printf ("<b>%s</b>\n"
+ "<span fgcolor=\"%s\"><small>%s</small></span>",
+ name,
+ desc_color,
+ desc);
+
+ g_object_set (renderer,
+ "markup", markup,
+ NULL);
+
+ g_free (name);
+ g_free (desc);
+ g_free (markup);
+ g_free (desc_color);
+}
+
+static void
gdu_pool_tree_view_constructed (GObject *object)
{
GduPoolTreeView *view = GDU_POOL_TREE_VIEW (object);
@@ -111,17 +212,51 @@ gdu_pool_tree_view_constructed (GObject *object)
GTK_TREE_MODEL (view->priv->model));
column = gtk_tree_view_column_new ();
- gtk_tree_view_column_set_title (column, "Title");
+ if (view->priv->flags & GDU_POOL_TREE_VIEW_FLAGS_SHOW_TOGGLE) {
+ renderer = gtk_cell_renderer_toggle_new ();
+ gtk_tree_view_column_pack_start (column,
+ renderer,
+ FALSE);
+ gtk_tree_view_column_set_attributes (column,
+ renderer,
+ "visible", GDU_POOL_TREE_MODEL_COLUMN_CAN_BE_TOGGLED,
+ "active", GDU_POOL_TREE_MODEL_COLUMN_TOGGLED,
+ NULL);
+ g_signal_connect (renderer,
+ "toggled",
+ G_CALLBACK (on_toggled),
+ view);
+ }
+
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_set_attributes (column, renderer,
+ gtk_tree_view_column_set_attributes (column,
+ renderer,
"pixbuf", GDU_POOL_TREE_MODEL_COLUMN_ICON,
NULL);
+ if (view->priv->flags & GDU_POOL_TREE_VIEW_FLAGS_SHOW_TOGGLE) {
+ gtk_tree_view_column_add_attribute (column,
+ renderer,
+ "sensitive", GDU_POOL_TREE_MODEL_COLUMN_CAN_BE_TOGGLED);
+ }
+
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_column_set_attributes (column,
+ // renderer,
+ // "markup", GDU_POOL_TREE_MODEL_COLUMN_NAME,
+ // NULL);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (column),
+ renderer,
+ format_markup,
+ view,
+ NULL);
+
+ if (view->priv->flags & GDU_POOL_TREE_VIEW_FLAGS_SHOW_TOGGLE) {
+ gtk_tree_view_column_add_attribute (column,
+ renderer,
+ "sensitive", GDU_POOL_TREE_MODEL_COLUMN_CAN_BE_TOGGLED);
+ }
gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
@@ -166,6 +301,23 @@ gdu_pool_tree_view_class_init (GduPoolTreeViewClass *klass)
G_PARAM_WRITABLE |
G_PARAM_READABLE |
G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * GduPoolTreeView:flags:
+ *
+ * Flags from the #GduPoolTreeViewFlags enumeration to
+ * customize behavior of the view.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_FLAGS,
+ g_param_spec_flags ("flags",
+ NULL,
+ NULL,
+ GDU_TYPE_POOL_TREE_VIEW_FLAGS,
+ GDU_POOL_TREE_VIEW_FLAGS_NONE,
+ G_PARAM_WRITABLE |
+ G_PARAM_READABLE |
+ G_PARAM_CONSTRUCT_ONLY));
}
static void
@@ -175,10 +327,12 @@ gdu_pool_tree_view_init (GduPoolTreeView *view)
}
GtkWidget *
-gdu_pool_tree_view_new (GduPoolTreeModel *model)
+gdu_pool_tree_view_new (GduPoolTreeModel *model,
+ GduPoolTreeViewFlags flags)
{
return GTK_WIDGET (g_object_new (GDU_TYPE_POOL_TREE_VIEW,
"pool-tree-model", model,
+ "flags", flags,
NULL));
}
@@ -216,18 +370,19 @@ gdu_pool_tree_view_select_presentable (GduPoolTreeView *view,
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;
+ if (presentable == NULL) {
+ gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)));
+ } else {
+ 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;
+ 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);
+ 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
index 71c3828..2f5499e 100644
--- a/src/gdu-gtk/gdu-pool-tree-view.h
+++ b/src/gdu-gtk/gdu-pool-tree-view.h
@@ -52,12 +52,12 @@ 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);
+GtkWidget *gdu_pool_tree_view_new (GduPoolTreeModel *model,
+ GduPoolTreeViewFlags flags);
+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/gdu-gtk/gdu-size-widget.c b/src/gdu-gtk/gdu-size-widget.c
new file mode 100644
index 0000000..a5f9c17
--- /dev/null
+++ b/src/gdu-gtk/gdu-size-widget.c
@@ -0,0 +1,408 @@
+/* -*- 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>
+ */
+
+#define _GNU_SOURCE
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <math.h>
+
+#include "gdu-size-widget.h"
+
+struct GduSizeWidgetPrivate
+{
+ guint64 size;
+ guint64 min_size;
+ guint64 max_size;
+ GtkWidget *hscale;
+};
+
+enum
+{
+ PROP_0,
+ PROP_SIZE,
+ PROP_MIN_SIZE,
+ PROP_MAX_SIZE,
+};
+
+enum
+{
+ CHANGED_SIGNAL,
+ LAST_SIGNAL,
+};
+
+guint signals[LAST_SIGNAL] = {0,};
+
+G_DEFINE_TYPE (GduSizeWidget, gdu_size_widget, GTK_TYPE_HBOX)
+
+static void
+gdu_size_widget_finalize (GObject *object)
+{
+ //GduSizeWidget *widget = GDU_SIZE_WIDGET (object);
+
+ if (G_OBJECT_CLASS (gdu_size_widget_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (gdu_size_widget_parent_class)->finalize (object);
+}
+
+static void
+gdu_size_widget_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GduSizeWidget *widget = GDU_SIZE_WIDGET (object);
+
+ switch (property_id) {
+ case PROP_SIZE:
+ g_value_set_uint64 (value, widget->priv->size);
+ break;
+
+ case PROP_MIN_SIZE:
+ g_value_set_uint64 (value, widget->priv->min_size);
+ break;
+
+ case PROP_MAX_SIZE:
+ g_value_set_uint64 (value, widget->priv->max_size);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gdu_size_widget_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GduSizeWidget *widget = GDU_SIZE_WIDGET (object);
+
+ switch (property_id) {
+ case PROP_SIZE:
+ gdu_size_widget_set_size (widget, g_value_get_uint64 (value));
+ break;
+
+ case PROP_MIN_SIZE:
+ gdu_size_widget_set_min_size (widget, g_value_get_uint64 (value));
+ break;
+
+ case PROP_MAX_SIZE:
+ gdu_size_widget_set_max_size (widget, g_value_get_uint64 (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static gchar *
+on_hscale_format_value (GtkScale *scale,
+ gdouble value,
+ gpointer user_data)
+{
+ gchar *ret;
+
+ ret = gdu_util_get_size_for_display ((guint64 ) value, FALSE);
+
+ return ret;
+}
+
+static void
+on_hscale_value_changed (GtkRange *range,
+ gpointer user_data)
+{
+ GduSizeWidget *widget = GDU_SIZE_WIDGET (user_data);
+ guint64 old_size;
+
+ old_size = widget->priv->size;
+ widget->priv->size = (guint64) gtk_range_get_value (range);
+
+ if (old_size != widget->priv->size) {
+ g_signal_emit (widget,
+ signals[CHANGED_SIGNAL],
+ 0);
+ g_object_notify (G_OBJECT (widget), "size");
+ }
+}
+
+static void
+gdu_size_widget_init (GduSizeWidget *widget)
+{
+ widget->priv = G_TYPE_INSTANCE_GET_PRIVATE (widget,
+ GDU_TYPE_SIZE_WIDGET,
+ GduSizeWidgetPrivate);
+
+ widget->priv->hscale = gtk_hscale_new_with_range (0,
+ 10,
+ 1);
+ gtk_scale_set_draw_value (GTK_SCALE (widget->priv->hscale), TRUE);
+}
+
+static gboolean
+on_query_tooltip (GtkWidget *w,
+ gint x,
+ gint y,
+ gboolean keyboard_mode,
+ GtkTooltip *tooltip,
+ gpointer user_data)
+{
+ GduSizeWidget *widget = GDU_SIZE_WIDGET (w);
+ gchar *s;
+ gchar *s1;
+
+ s1 = gdu_util_get_size_for_display (widget->priv->size, TRUE);
+ /* TODO: handle this use-case
+ s = g_strdup_printf ("<b>%s</b>\n"
+ "\n"
+ "%s",
+ s1,
+ _("Right click to specify an exact size."));*/
+ s = g_strdup_printf ("%s", s1);
+ g_free (s1);
+ gtk_tooltip_set_markup (tooltip, s);
+ g_free (s);
+
+ return TRUE;
+}
+
+static void
+gdu_size_widget_constructed (GObject *object)
+{
+ GduSizeWidget *widget = GDU_SIZE_WIDGET (object);
+
+ gtk_widget_show (widget->priv->hscale);
+ gtk_box_pack_start (GTK_BOX (widget),
+ widget->priv->hscale,
+ TRUE,
+ TRUE,
+ 0);
+
+ g_signal_connect (widget->priv->hscale,
+ "format-value",
+ G_CALLBACK (on_hscale_format_value),
+ widget);
+ g_signal_connect (widget->priv->hscale,
+ "value-changed",
+ G_CALLBACK (on_hscale_value_changed),
+ widget);
+
+ gtk_widget_set_has_tooltip (GTK_WIDGET (widget),
+ TRUE);
+ g_signal_connect (widget,
+ "query-tooltip",
+ G_CALLBACK (on_query_tooltip),
+ widget);
+
+ if (G_OBJECT_CLASS (gdu_size_widget_parent_class)->constructed != NULL)
+ G_OBJECT_CLASS (gdu_size_widget_parent_class)->constructed (object);
+}
+
+static void
+gdu_size_widget_class_init (GduSizeWidgetClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GduSizeWidgetPrivate));
+
+ gobject_class->get_property = gdu_size_widget_get_property;
+ gobject_class->set_property = gdu_size_widget_set_property;
+ gobject_class->constructed = gdu_size_widget_constructed;
+ gobject_class->finalize = gdu_size_widget_finalize;
+
+ g_object_class_install_property (gobject_class,
+ PROP_SIZE,
+ g_param_spec_uint64 ("size",
+ _("Size"),
+ _("The currently selected size"),
+ 0,
+ G_MAXUINT64,
+ 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property (gobject_class,
+ PROP_MIN_SIZE,
+ g_param_spec_uint64 ("min-size",
+ _("Minimum Size"),
+ _("The minimum size that can be selected"),
+ 0,
+ G_MAXUINT64,
+ 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property (gobject_class,
+ PROP_MAX_SIZE,
+ g_param_spec_uint64 ("max-size",
+ _("Maximum Size"),
+ _("The maximum size that can be selected"),
+ 0,
+ G_MAXUINT64,
+ 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ signals[CHANGED_SIGNAL] = g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GduSizeWidgetClass, changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+GtkWidget *
+gdu_size_widget_new (guint64 size,
+ guint64 min_size,
+ guint64 max_size)
+{
+ return GTK_WIDGET (g_object_new (GDU_TYPE_SIZE_WIDGET,
+ "size", size,
+ "min-size", min_size,
+ "max-size", max_size,
+ NULL));
+}
+
+static void
+update_stepping (GduSizeWidget *widget)
+{
+ gdouble extent;
+
+ extent = widget->priv->max_size - widget->priv->min_size;
+
+ /* set steps in hscale according to magnitude of extent und so weiter */
+ if (extent > 0) {
+ gdouble increment;
+ increment = exp10 (floor (log10 (extent))) / 10.0;
+ gtk_range_set_increments (GTK_RANGE (widget->priv->hscale),
+ increment,
+ increment * 10.0);
+ }
+
+
+ /* add markers at 0, 25%, 50%, 75% and 100% */
+ gtk_scale_clear_marks (GTK_SCALE (widget->priv->hscale));
+ gtk_scale_add_mark (GTK_SCALE (widget->priv->hscale),
+ widget->priv->min_size,
+ GTK_POS_BOTTOM,
+ NULL);
+ gtk_scale_add_mark (GTK_SCALE (widget->priv->hscale),
+ widget->priv->min_size + extent * 0.25,
+ GTK_POS_BOTTOM,
+ NULL);
+ gtk_scale_add_mark (GTK_SCALE (widget->priv->hscale),
+ widget->priv->min_size + extent * 0.50,
+ GTK_POS_BOTTOM,
+ NULL);
+ gtk_scale_add_mark (GTK_SCALE (widget->priv->hscale),
+ widget->priv->min_size + extent * 0.75,
+ GTK_POS_BOTTOM,
+ NULL);
+ gtk_scale_add_mark (GTK_SCALE (widget->priv->hscale),
+ widget->priv->min_size + extent * 1.0,
+ GTK_POS_BOTTOM,
+ NULL);
+}
+
+void
+gdu_size_widget_set_size (GduSizeWidget *widget,
+ guint64 size)
+{
+ g_return_if_fail (GDU_IS_SIZE_WIDGET (widget));
+ if (widget->priv->size != size) {
+ gtk_range_set_value (GTK_RANGE (widget->priv->hscale),
+ size);
+ }
+}
+
+void
+gdu_size_widget_set_min_size (GduSizeWidget *widget,
+ guint64 min_size)
+{
+ g_return_if_fail (GDU_IS_SIZE_WIDGET (widget));
+ if (widget->priv->min_size != min_size) {
+ widget->priv->min_size = min_size;
+ gtk_range_set_range (GTK_RANGE (widget->priv->hscale),
+ widget->priv->min_size,
+ widget->priv->max_size);
+ update_stepping (widget);
+ g_signal_emit (widget,
+ signals[CHANGED_SIGNAL],
+ 0);
+ g_object_notify (G_OBJECT (widget), "min-size");
+ }
+}
+
+void
+gdu_size_widget_set_max_size (GduSizeWidget *widget,
+ guint64 max_size)
+{
+ g_return_if_fail (GDU_IS_SIZE_WIDGET (widget));
+ if (widget->priv->max_size != max_size) {
+ widget->priv->max_size = max_size;
+ gtk_range_set_range (GTK_RANGE (widget->priv->hscale),
+ widget->priv->min_size,
+ widget->priv->max_size);
+ update_stepping (widget);
+ g_signal_emit (widget,
+ signals[CHANGED_SIGNAL],
+ 0);
+ g_object_notify (G_OBJECT (widget), "max-size");
+ }
+}
+
+guint64
+gdu_size_widget_get_size (GduSizeWidget *widget)
+{
+ g_return_val_if_fail (GDU_IS_SIZE_WIDGET (widget), 0);
+ return widget->priv->size;
+}
+
+guint64
+gdu_size_widget_get_min_size (GduSizeWidget *widget)
+{
+ g_return_val_if_fail (GDU_IS_SIZE_WIDGET (widget), 0);
+ return widget->priv->min_size;
+}
+
+guint64
+gdu_size_widget_get_max_size (GduSizeWidget *widget)
+{
+ g_return_val_if_fail (GDU_IS_SIZE_WIDGET (widget), 0);
+ return widget->priv->max_size;
+}
+
diff --git a/src/gdu-gtk/gdu-size-widget.h b/src/gdu-gtk/gdu-size-widget.h
new file mode 100644
index 0000000..5cd7578
--- /dev/null
+++ b/src/gdu-gtk/gdu-size-widget.h
@@ -0,0 +1,72 @@
+/* -*- 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_SIZE_WIDGET_H
+#define __GDU_SIZE_WIDGET_H
+
+#include <gdu-gtk/gdu-gtk.h>
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_SIZE_WIDGET (gdu_size_widget_get_type())
+#define GDU_SIZE_WIDGET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_SIZE_WIDGET, GduSizeWidget))
+#define GDU_SIZE_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GDU_TYPE_SIZE_WIDGET, GduSizeWidgetClass))
+#define GDU_IS_SIZE_WIDGET(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_SIZE_WIDGET))
+#define GDU_IS_SIZE_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDU_TYPE_SIZE_WIDGET))
+#define GDU_SIZE_WIDGET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDU_TYPE_SIZE_WIDGET, GduSizeWidgetClass))
+
+typedef struct GduSizeWidgetClass GduSizeWidgetClass;
+typedef struct GduSizeWidgetPrivate GduSizeWidgetPrivate;
+
+struct GduSizeWidget
+{
+ GtkHBox parent;
+
+ /*< private >*/
+ GduSizeWidgetPrivate *priv;
+};
+
+struct GduSizeWidgetClass
+{
+ GtkHBoxClass parent_class;
+
+ void (*changed) (GduSizeWidget *widget);
+};
+
+GType gdu_size_widget_get_type (void) G_GNUC_CONST;
+GtkWidget* gdu_size_widget_new (guint64 size,
+ guint64 min_size,
+ guint64 max_size);
+void gdu_size_widget_set_size (GduSizeWidget *widget,
+ guint64 size);
+void gdu_size_widget_set_min_size (GduSizeWidget *widget,
+ guint64 min_size);
+void gdu_size_widget_set_max_size (GduSizeWidget *widget,
+ guint64 max_size);
+guint64 gdu_size_widget_get_size (GduSizeWidget *widget);
+guint64 gdu_size_widget_get_min_size (GduSizeWidget *widget);
+guint64 gdu_size_widget_get_max_size (GduSizeWidget *widget);
+
+G_END_DECLS
+
+#endif /* __GDU_SIZE_WIDGET_H */
+
diff --git a/src/gdu/gdu-drive.c b/src/gdu/gdu-drive.c
index 010c36b..e825355 100644
--- a/src/gdu/gdu-drive.c
+++ b/src/gdu/gdu-drive.c
@@ -242,23 +242,27 @@ gdu_drive_get_enclosing_presentable (GduPresentable *presentable)
return NULL;
}
-static char *
+static gchar *
gdu_drive_get_name (GduPresentable *presentable)
{
GduDrive *drive = GDU_DRIVE (presentable);
- const char *vendor;
- const char *model;
+ const gchar *vendor;
+ const gchar *model;
const char *presentation_name;
+ const gchar* const *media_compat;
guint64 size;
gboolean is_removable;
- char *strsize;
- char *result;
+ GString *result;
+ gboolean is_rotational;
+ gboolean has_media;
+ gchar *strsize;
strsize = NULL;
+ result = g_string_new (NULL);
presentation_name = gdu_device_get_presentation_name (drive->priv->device);
if (presentation_name != NULL && strlen (presentation_name) > 0) {
- result = g_strdup (presentation_name);
+ g_string_append (result, presentation_name);
goto out;
}
@@ -266,33 +270,199 @@ gdu_drive_get_name (GduPresentable *presentable)
model = gdu_device_drive_get_model (drive->priv->device);
size = gdu_device_get_size (drive->priv->device);
is_removable = gdu_device_is_removable (drive->priv->device);
+ media_compat = (const gchar* const *) gdu_device_drive_get_media_compatibility (drive->priv->device);
+ has_media = gdu_device_is_media_available (drive->priv->device);
+ is_rotational = TRUE; /* TODO: add support in DKD for this */
- if (vendor != NULL && strlen (vendor) == 0)
- vendor = NULL;
-
- if (model != NULL && strlen (model) == 0)
- model = NULL;
-
- if (!is_removable && size > 0) {
+ if (has_media && size > 0) {
strsize = gdu_util_get_size_for_display (size, FALSE);
}
- if (strsize != NULL) {
- result = g_strdup_printf ("%s %s%s%s",
- strsize,
- vendor != NULL ? vendor : "",
- vendor != NULL ? " " : "",
- model != NULL ? model : "");
+
+ if (is_removable) {
+ guint n;
+ gboolean optical_cd;
+ gboolean optical_dvd;
+ gboolean optical_bd;
+ gboolean optical_hddvd;
+
+ /* TODO: should move to gdu-util.c */
+ optical_cd = FALSE;
+ optical_dvd = FALSE;
+ optical_bd = FALSE;
+ optical_hddvd = FALSE;
+ for (n = 0; media_compat != NULL && media_compat[n] != NULL; n++) {
+ const gchar *media_name;
+ const gchar *media;
+
+ media = media_compat[n];
+ media_name = NULL;
+ if (g_strcmp0 (media, "flash_cf") == 0) {
+ media_name = _("CompactFlash");
+ } else if (g_strcmp0 (media, "flash_ms") == 0) {
+ media_name = _("MemoryStick");
+ } else if (g_strcmp0 (media, "flash_sm") == 0) {
+ media_name = _("SmartMedia");
+ } else if (g_strcmp0 (media, "flash_sd") == 0) {
+ media_name = _("SecureDigital");
+ } else if (g_strcmp0 (media, "flash_sdhc") == 0) {
+ media_name = _("SD High Capcity");
+ } else if (g_strcmp0 (media, "floppy") == 0) {
+ media_name = _("Floppy");
+ } else if (g_strcmp0 (media, "floppy_zip") == 0) {
+ media_name = _("Zip");
+ } else if (g_strcmp0 (media, "floppy_jaz") == 0) {
+ media_name = _("Jaz");
+ } else if (g_str_has_prefix (media, "flash")) {
+ media_name = _("Flash");
+ } else if (g_str_has_prefix (media, "optical_cd")) {
+ optical_cd = TRUE;
+ } else if (g_str_has_prefix (media, "optical_dvd")) {
+ optical_dvd = TRUE;
+ } else if (g_str_has_prefix (media, "optical_bd")) {
+ optical_bd = TRUE;
+ } else if (g_str_has_prefix (media, "optical_hddvd")) {
+ optical_hddvd = TRUE;
+ }
+
+ if (media_name != NULL) {
+ if (result->len > 0)
+ g_string_append_c (result, '/');
+ g_string_append (result, media_name);
+ }
+ }
+ if (optical_cd) {
+ if (result->len > 0)
+ g_string_append_c (result, '/');
+ g_string_append (result, _("CD"));
+ }
+ if (optical_dvd) {
+ if (result->len > 0)
+ g_string_append_c (result, '/');
+ g_string_append (result, _("DVD"));
+ }
+ if (optical_bd) {
+ if (result->len > 0)
+ g_string_append_c (result, '/');
+ g_string_append (result, _("Blu-Ray"));
+ }
+ if (optical_hddvd) {
+ if (result->len > 0)
+ g_string_append_c (result, '/');
+ g_string_append (result, _("HDDVD"));
+ }
+
+ /* If we know the media type, just append Drive */
+ if (result->len > 0) {
+ g_string_append_c (result, ' ');
+ g_string_append (result, _("Drive"));
+ } else {
+ /* Otherwise use Vendor/Model */
+ if (vendor != NULL && strlen (vendor) == 0)
+ vendor = NULL;
+
+ if (model != NULL && strlen (model) == 0)
+ model = NULL;
+
+ g_string_append_printf (result,
+ "%s%s%s",
+ vendor != NULL ? vendor : "",
+ vendor != NULL ? " " : "",
+ model != NULL ? model : "");
+ }
+
} else {
- result = g_strdup_printf ("%s%s%s",
- vendor != NULL ? vendor : "",
- vendor != NULL ? " " : "",
- model != NULL ? model : "");
+ /* Media is not removable, use "Hard Disk" resp. "Solid-State Disk" */
+
+ if (is_rotational) {
+ if (strsize != NULL) {
+ g_string_append_printf (result,
+ _("%s Hard Disk"),
+ strsize);
+ } else {
+ g_string_append (result,
+ _("%s Hard Disk"));
+ }
+ } else {
+ if (strsize != NULL) {
+ g_string_append_printf (result,
+ _("%s Solid-State Disk"),
+ strsize);
+ } else {
+ g_string_append (result,
+ _("%s Solid-State Disk"));
+ }
+ }
}
out:
g_free (strsize);
- return result;
+ return g_string_free (result, FALSE);
+}
+
+static gchar *
+gdu_drive_get_description (GduPresentable *presentable)
+{
+ GduDrive *drive = GDU_DRIVE (presentable);
+ const gchar *vendor;
+ const gchar *model;
+ const gchar *part_table_scheme;
+ GString *result;
+ guint64 size;
+ gboolean is_removable;
+ gboolean has_media;
+
+ result = g_string_new (NULL);
+
+ vendor = gdu_device_drive_get_vendor (drive->priv->device);
+ model = gdu_device_drive_get_model (drive->priv->device);
+
+ size = gdu_device_get_size (drive->priv->device);
+ is_removable = gdu_device_is_removable (drive->priv->device);
+ has_media = gdu_device_is_media_available (drive->priv->device);
+ part_table_scheme = gdu_device_partition_table_get_scheme (drive->priv->device);
+
+ /* If removable, include size of media or the fact there is no media */
+ if (is_removable) {
+ if (has_media && size > 0) {
+ gchar *strsize;
+ strsize = gdu_util_get_size_for_display (size, FALSE);
+ g_string_append_printf (result,
+ _("%s Media"),
+ strsize);
+ g_free (strsize);
+ } else {
+ g_string_append_printf (result,
+ _("No Media Detected"));
+ }
+ }
+
+ /* If we have media, include whether partitioned or not */
+ if (has_media && size > 0) {
+ if (result->len > 0)
+ g_string_append (result, ", ");
+ if (gdu_device_is_partition_table (drive->priv->device)) {
+ if (g_strcmp0 (part_table_scheme, "mbr") == 0) {
+ g_string_append (result,
+ _("MBR Partition Table"));
+ } else if (g_strcmp0 (part_table_scheme, "gpt") == 0) {
+ g_string_append (result,
+ _("GUID Partition Table"));
+ } else if (g_strcmp0 (part_table_scheme, "apm") == 0) {
+ g_string_append (result,
+ _("Apple Partition Table"));
+ } else {
+ g_string_append (result,
+ _("Partitioned"));
+ }
+ } else {
+ g_string_append (result,
+ _("Not Partitioned"));
+ }
+ }
+
+
+ return g_string_free (result, FALSE);
}
static gboolean
@@ -465,6 +635,7 @@ gdu_drive_presentable_iface_init (GduPresentableIface *iface)
iface->get_device = gdu_drive_get_device;
iface->get_enclosing_presentable = gdu_drive_get_enclosing_presentable;
iface->get_name = gdu_drive_get_name;
+ iface->get_description = gdu_drive_get_description;
iface->get_icon = gdu_drive_get_icon;
iface->get_offset = gdu_drive_get_offset;
iface->get_size = gdu_drive_get_size;
diff --git a/src/gdu/gdu-linux-md-drive.c b/src/gdu/gdu-linux-md-drive.c
index 614ac9d..f250c39 100644
--- a/src/gdu/gdu-linux-md-drive.c
+++ b/src/gdu/gdu-linux-md-drive.c
@@ -467,13 +467,15 @@ gdu_linux_md_drive_get_enclosing_presentable (GduPresentable *presentable)
return NULL;
}
-static char *
-gdu_linux_md_drive_get_name (GduPresentable *presentable)
+static gchar *
+get_name_and_desc (GduPresentable *presentable,
+ gchar **out_desc)
{
GduLinuxMdDrive *drive = GDU_LINUX_MD_DRIVE (presentable);
- GduDevice *device;
- char *ret;
- char *level_str;
+ GduDevice *component_device;
+ gchar *ret;
+ gchar *ret_desc;
+ gchar *level_str;
guint64 component_size;
int num_slaves;
int num_raid_devices;
@@ -481,30 +483,86 @@ gdu_linux_md_drive_get_name (GduPresentable *presentable)
const char *name;
ret = NULL;
+ ret_desc = NULL;
if (drive->priv->slaves != NULL) {
- device = GDU_DEVICE (drive->priv->slaves->data);
+ guint64 size;
+ gchar *strsize;
+
+ component_device = GDU_DEVICE (drive->priv->slaves->data);
- level = gdu_device_linux_md_component_get_level (device);
- name = gdu_device_linux_md_component_get_name (device);
- num_raid_devices = gdu_device_linux_md_component_get_num_raid_devices (device);
+ level = gdu_device_linux_md_component_get_level (component_device);
+ name = gdu_device_linux_md_component_get_name (component_device);
+ num_raid_devices = gdu_device_linux_md_component_get_num_raid_devices (component_device);
num_slaves = g_list_length (drive->priv->slaves);
- component_size = gdu_device_get_size (device);
+ component_size = gdu_device_get_size (component_device);
level_str = gdu_linux_md_get_raid_level_for_display (level);
+ strsize = NULL;
+ if (drive->priv->device != NULL) {
+ size = gdu_device_get_size (component_device);
+ strsize = gdu_util_get_size_for_display (size, FALSE);
+ }
+ /* TODO: Maybe guess size from level, num_raid_devices and component_size? */
+
if (name == NULL || strlen (name) == 0) {
- /* Translators: %s is a RAID level, e.g. 'RAID-5' */
- ret = g_strdup_printf (_("%s Drive"), level_str);
+ if (strsize != NULL) {
+ /* Translators: First %s is the size, second %s is a RAID level, e.g. 'RAID-5' */
+ ret = g_strdup_printf (_("%s %s Drive"),
+ strsize,
+ level_str);
+ } else {
+ /* Translators: %s is a RAID level, e.g. 'RAID-5' */
+ ret = g_strdup_printf (_("%s Drive"),
+ level_str);
+ }
} else {
- /* Translators: First %s is a RAID level, e.g. 'RAID-5'
- * second %s is a drive name
- */
- ret = g_strdup_printf (_("%s (%s)"), name, level_str);
+ ret = g_strdup (name);
+ if (strsize != NULL) {
+ ret_desc = g_strdup_printf ("%s %s",
+ strsize,
+ level_str);
+ } else {
+ ret_desc = g_strdup (level_str);
+ }
+ }
+
+ if (drive->priv->device != NULL && gdu_device_is_partition_table (drive->priv->device)) {
+ const gchar *part_table_scheme;
+ const gchar *scheme_str;
+
+ part_table_scheme = gdu_device_partition_table_get_scheme (drive->priv->device);
+
+ if (g_strcmp0 (part_table_scheme, "mbr") == 0) {
+ scheme_str = _("MBR Partition Table");
+ } else if (g_strcmp0 (part_table_scheme, "gpt") == 0) {
+ scheme_str = _("GUID Partition Table");
+ } else if (g_strcmp0 (part_table_scheme, "apm") == 0) {
+ scheme_str = _("Apple Partition Table");
+ } else {
+ scheme_str = _("Partitioned");
+ }
+
+ if (ret_desc != NULL) {
+ gchar *tmp;
+ tmp = ret_desc;
+ ret_desc = g_strconcat (ret_desc,
+ ", ",
+ scheme_str,
+ NULL);
+ g_free (tmp);
+ } else {
+ ret_desc = g_strdup (scheme_str);
+ }
}
g_free (level_str);
+ /* lame fallback */
+ if (ret_desc == NULL)
+ ret_desc = g_strdup (_("RAID Array"));
+
} else if (drive->priv->device != NULL) {
/* Translators: First %s is a device file such as /dev/sda4
* second %s is the state of the device
@@ -520,9 +578,32 @@ gdu_linux_md_drive_get_name (GduPresentable *presentable)
ret = g_strdup_printf (_("RAID device %s"), drive->priv->device_file);
}
+ if (out_desc != NULL)
+ *out_desc = ret_desc;
+ else
+ g_free (ret_desc);
+
return ret;
}
+static char *
+gdu_linux_md_drive_get_name (GduPresentable *presentable)
+{
+ return get_name_and_desc (presentable, NULL);
+}
+
+static gchar *
+gdu_linux_md_drive_get_description (GduPresentable *presentable)
+{
+ gchar *desc;
+ gchar *name;
+
+ name = get_name_and_desc (presentable, &desc);
+ g_free (name);
+
+ return desc;
+}
+
static GIcon *
gdu_linux_md_drive_get_icon (GduPresentable *presentable)
{
@@ -617,6 +698,7 @@ gdu_linux_md_drive_presentable_iface_init (GduPresentableIface *iface)
iface->get_device = gdu_linux_md_drive_get_device;
iface->get_enclosing_presentable = gdu_linux_md_drive_get_enclosing_presentable;
iface->get_name = gdu_linux_md_drive_get_name;
+ iface->get_description = gdu_linux_md_drive_get_description;
iface->get_icon = gdu_linux_md_drive_get_icon;
iface->get_offset = gdu_linux_md_drive_get_offset;
iface->get_size = gdu_linux_md_drive_get_size;
diff --git a/src/gdu/gdu-presentable.c b/src/gdu/gdu-presentable.c
index 002792b..8f75afb 100644
--- a/src/gdu/gdu-presentable.c
+++ b/src/gdu/gdu-presentable.c
@@ -320,7 +320,7 @@ gdu_presentable_get_enclosing_presentable (GduPresentable *presentable)
*
* Returns: The name. Caller must free the string with g_free().
**/
-char *
+gchar *
gdu_presentable_get_name (GduPresentable *presentable)
{
GduPresentableIface *iface;
@@ -333,6 +333,27 @@ gdu_presentable_get_name (GduPresentable *presentable)
}
/**
+ * gdu_presentable_get_description:
+ * @presentable: A #GduPresentable.
+ *
+ * Gets a description for @presentable suitable for presentation in an user
+ * interface.
+ *
+ * Returns: The description. Caller must free the string with g_free().
+ */
+gchar *
+gdu_presentable_get_description (GduPresentable *presentable)
+{
+ GduPresentableIface *iface;
+
+ g_return_val_if_fail (GDU_IS_PRESENTABLE (presentable), NULL);
+
+ iface = GDU_PRESENTABLE_GET_IFACE (presentable);
+
+ return (* iface->get_description) (presentable);
+}
+
+/**
* gdu_presentable_get_icon:
* @presentable: A #GduPresentable.
*
diff --git a/src/gdu/gdu-presentable.h b/src/gdu/gdu-presentable.h
index 8f8cff1..2a384e7 100644
--- a/src/gdu/gdu-presentable.h
+++ b/src/gdu/gdu-presentable.h
@@ -69,7 +69,8 @@ struct _GduPresentableIface
const gchar * (*get_id) (GduPresentable *presentable);
GduDevice * (*get_device) (GduPresentable *presentable);
GduPresentable * (*get_enclosing_presentable) (GduPresentable *presentable);
- char * (*get_name) (GduPresentable *presentable);
+ gchar * (*get_name) (GduPresentable *presentable);
+ gchar * (*get_description) (GduPresentable *presentable);
GIcon * (*get_icon) (GduPresentable *presentable);
guint64 (*get_offset) (GduPresentable *presentable);
guint64 (*get_size) (GduPresentable *presentable);
@@ -82,7 +83,8 @@ GType gdu_presentable_get_type (void) G_GNUC_CONST;
const gchar *gdu_presentable_get_id (GduPresentable *presentable);
GduDevice *gdu_presentable_get_device (GduPresentable *presentable);
GduPresentable *gdu_presentable_get_enclosing_presentable (GduPresentable *presentable);
-char *gdu_presentable_get_name (GduPresentable *presentable);
+gchar *gdu_presentable_get_name (GduPresentable *presentable);
+gchar *gdu_presentable_get_description (GduPresentable *presentable);
GIcon *gdu_presentable_get_icon (GduPresentable *presentable);
guint64 gdu_presentable_get_offset (GduPresentable *presentable);
guint64 gdu_presentable_get_size (GduPresentable *presentable);
diff --git a/src/gdu/gdu-volume-hole.c b/src/gdu/gdu-volume-hole.c
index d94db02..cef5dab 100644
--- a/src/gdu/gdu-volume-hole.c
+++ b/src/gdu/gdu-volume-hole.c
@@ -147,12 +147,18 @@ gdu_volume_hole_get_name (GduPresentable *presentable)
/* Translators: label for an unallocated space on a disk
* %s is the size, formatted like '45 GB'
*/
- result = g_strdup_printf (_("%s Unallocated"), strsize);
+ result = g_strdup_printf (_("%s Free"), strsize);
g_free (strsize);
return result;
}
+static gchar *
+gdu_volume_hole_get_description (GduPresentable *presentable)
+{
+ return g_strdup (_("Unallocated Space"));
+}
+
static GIcon *
gdu_volume_hole_get_icon (GduPresentable *presentable)
{
@@ -298,6 +304,7 @@ gdu_volume_hole_presentable_iface_init (GduPresentableIface *iface)
iface->get_device = gdu_volume_hole_get_device;
iface->get_enclosing_presentable = gdu_volume_hole_get_enclosing_presentable;
iface->get_name = gdu_volume_hole_get_name;
+ iface->get_description = gdu_volume_hole_get_description;
iface->get_icon = gdu_volume_hole_get_icon;
iface->get_offset = gdu_volume_hole_get_offset;
iface->get_size = gdu_volume_hole_get_size;
diff --git a/src/gdu/gdu-volume.c b/src/gdu/gdu-volume.c
index 6e91d22..d0f51f1 100644
--- a/src/gdu/gdu-volume.c
+++ b/src/gdu/gdu-volume.c
@@ -196,7 +196,8 @@ gdu_volume_get_enclosing_presentable (GduPresentable *presentable)
}
static char *
-gdu_volume_get_name (GduPresentable *presentable)
+get_name_and_desc (GduPresentable *presentable,
+ gchar **out_desc)
{
GduVolume *volume = GDU_VOLUME (presentable);
GduPresentable *drive_presentable;
@@ -204,6 +205,7 @@ gdu_volume_get_name (GduPresentable *presentable)
const char *label;
const char *usage;
const char *type;
+ const char *version;
const char *drive_media;
const char *presentation_name;
char *result;
@@ -211,20 +213,16 @@ gdu_volume_get_name (GduPresentable *presentable)
char *strsize;
guint64 size;
guint n;
+ gchar *result_desc;
result = NULL;
+ result_desc = NULL;
drive_presentable = NULL;
drive_device = NULL;
drive_media = NULL;
strsize = NULL;
- presentation_name = gdu_device_get_presentation_name (volume->priv->device);
- if (presentation_name != NULL && strlen (presentation_name) > 0) {
- result = g_strdup (presentation_name);
- goto out;
- }
-
drive_presentable = gdu_presentable_get_toplevel (presentable);
if (drive_presentable != NULL) {
drive_device = gdu_presentable_get_device (drive_presentable);
@@ -238,18 +236,25 @@ gdu_volume_get_name (GduPresentable *presentable)
size = gdu_device_get_size (volume->priv->device);
strsize = gdu_util_get_size_for_display (size, FALSE);
+ presentation_name = gdu_device_get_presentation_name (volume->priv->device);
+ if (presentation_name != NULL && strlen (presentation_name) > 0) {
+ result = g_strdup (presentation_name);
+ goto out;
+ }
+
/* see comment in gdu_pool_add_device_by_object_path() for how to avoid hardcoding 0x05 etc. types */
is_extended_partition = FALSE;
if (gdu_device_is_partition (volume->priv->device) &&
strcmp (gdu_device_partition_get_scheme (volume->priv->device), "mbr") == 0) {
- int type;
- type = strtol (gdu_device_partition_get_type (volume->priv->device), NULL, 0);
- if (type == 0x05 || type == 0x0f || type == 0x85)
+ int part_type;
+ part_type = strtol (gdu_device_partition_get_type (volume->priv->device), NULL, 0);
+ if (part_type == 0x05 || part_type == 0x0f || part_type == 0x85)
is_extended_partition = TRUE;
}
usage = gdu_device_id_get_usage (volume->priv->device);
type = gdu_device_id_get_type (volume->priv->device);
+ version = gdu_device_id_get_version (volume->priv->device);
/* handle optical discs */
if (gdu_device_is_optical_disc (volume->priv->device) &&
@@ -276,7 +281,13 @@ gdu_volume_get_name (GduPresentable *presentable)
result = g_strdup_printf (_("%s Extended"), strsize);
} else if ((usage != NULL && strcmp (usage, "filesystem") == 0) &&
(label != NULL && strlen (label) > 0)) {
+ gchar *fsdesc;
result = g_strdup (label);
+ fsdesc = gdu_util_get_fstype_for_display (type, version, TRUE);
+ result_desc = g_strdup_printf ("%s %s",
+ strsize,
+ fsdesc);
+ g_free (fsdesc);
} else if (usage != NULL) {
if (strcmp (usage, "crypto") == 0) {
/* Translators: Label for an extended partition
@@ -299,6 +310,7 @@ gdu_volume_get_name (GduPresentable *presentable)
* %s is the size, formatted like '45 GB'
*/
result = g_strdup_printf (_("%s Filesystem"), strsize);
+ result_desc = gdu_util_get_fstype_for_display (type, version, TRUE);
} else if (strcmp (usage, "partitiontable") == 0) {
/* Translators: Label for a partition table
* %s is the size, formatted like '45 GB'
@@ -327,16 +339,21 @@ gdu_volume_get_name (GduPresentable *presentable)
if (array_name != NULL && strlen (array_name) > 0) {
/* Translators: label for a RAID component
* First %s is the size, formatted like '45 GB'
+ */
+ result = g_strdup_printf (_("%s RAID Component"), strsize);
+ /* Translators: description for a RAID component
+ * First %s is the array name, e.g. 'My Photos RAID',
* second %s is the RAID level string, e.g 'RAID-5'
- * third %s is the name of the array
*/
- result = g_strdup_printf (_("%s %s (%s)"), strsize, level_str, array_name);
+ result_desc = g_strdup_printf (_("Part of \"%s\" %s array"),
+ array_name,
+ level_str);
} else {
/* Translators: label for a RAID component
* First %s is the size, formatted like '45 GB'
- * second %s is the RAID level string, e.g 'RAID-5'
*/
- result = g_strdup_printf (_("%s %s"), strsize, level_str);
+ result = g_strdup_printf (_("%s RAID Component"), strsize);
+ result_desc = g_strdup (level_str);
}
g_free (level_str);
@@ -358,6 +375,7 @@ gdu_volume_get_name (GduPresentable *presentable)
* %s is the size, formatted like '45 GB'
*/
result = g_strdup_printf (_("%s Unrecognized"), strsize);
+ result_desc = g_strdup (_("Unknown or Unused"));
}
} else {
if (gdu_device_is_partition (volume->priv->device)) {
@@ -374,16 +392,43 @@ gdu_volume_get_name (GduPresentable *presentable)
result = g_strdup_printf (_("%s Unrecognized"), strsize);
out:
- g_free (strsize);
-
if (drive_device != NULL)
g_object_unref (drive_device);
if (drive_presentable != NULL)
g_object_unref (drive_presentable);
+ if (result_desc == NULL) {
+ result_desc = g_strdup (strsize);
+ }
+
+ if (out_desc != NULL)
+ *out_desc = result_desc;
+ else
+ g_free (result_desc);
+
+ g_free (strsize);
+
return result;
}
+static char *
+gdu_volume_get_name (GduPresentable *presentable)
+{
+ return get_name_and_desc (presentable, NULL);
+}
+
+static gchar *
+gdu_volume_get_description (GduPresentable *presentable)
+{
+ gchar *desc;
+ gchar *name;
+
+ name = get_name_and_desc (presentable, &desc);
+ g_free (name);
+
+ return desc;
+}
+
static GIcon *
gdu_volume_get_icon (GduPresentable *presentable)
{
@@ -617,6 +662,7 @@ gdu_volume_presentable_iface_init (GduPresentableIface *iface)
iface->get_device = gdu_volume_get_device;
iface->get_enclosing_presentable = gdu_volume_get_enclosing_presentable;
iface->get_name = gdu_volume_get_name;
+ iface->get_description = gdu_volume_get_description;
iface->get_icon = gdu_volume_get_icon;
iface->get_offset = gdu_volume_get_offset;
iface->get_size = gdu_volume_get_size;
diff --git a/src/palimpsest/gdu-section-linux-md-drive.c b/src/palimpsest/gdu-section-linux-md-drive.c
index 976512b..edc2a76 100644
--- a/src/palimpsest/gdu-section-linux-md-drive.c
+++ b/src/palimpsest/gdu-section-linux-md-drive.c
@@ -171,7 +171,7 @@ on_add_clicked (GtkButton *button,
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
GTK_SHADOW_IN);
model = gdu_pool_tree_model_new (pool);
- tree_view = gdu_pool_tree_view_new (model);
+ tree_view = gdu_pool_tree_view_new (model, GDU_POOL_TREE_VIEW_FLAGS_NONE);
g_object_unref (model);
gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
diff --git a/src/palimpsest/gdu-shell.c b/src/palimpsest/gdu-shell.c
index df32b7e..2da8eb3 100644
--- a/src/palimpsest/gdu-shell.c
+++ b/src/palimpsest/gdu-shell.c
@@ -1922,7 +1922,8 @@ create_window (GduShell *shell)
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (tree_view_scrolled_window),
GTK_SHADOW_IN);
model = gdu_pool_tree_model_new (shell->priv->pool);
- shell->priv->tree_view = gdu_pool_tree_view_new (model);
+ shell->priv->tree_view = gdu_pool_tree_view_new (model,
+ GDU_POOL_TREE_VIEW_FLAGS_NONE);
g_object_unref (model);
gtk_container_add (GTK_CONTAINER (tree_view_scrolled_window), shell->priv->tree_view);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]