[gnome-disk-utility/new-ui] Implement the "Create Partition" dialog
- From: David Zeuthen <davidz src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-disk-utility/new-ui] Implement the "Create Partition" dialog
- Date: Tue, 27 Oct 2009 00:59:27 +0000 (UTC)
commit 6eb9e7baa184eea71c3713e7833207f3147d5ff9
Author: David Zeuthen <davidz redhat com>
Date: Mon Oct 26 20:59:02 2009 -0400
Implement the "Create Partition" dialog
src/gdu-gtk/Makefile.am | 2 +
src/gdu-gtk/gdu-create-partition-dialog.c | 246 +++++++++++++++++++++++++++
src/gdu-gtk/gdu-create-partition-dialog.h | 69 ++++++++
src/gdu-gtk/gdu-format-dialog.c | 57 ++++++-
src/gdu-gtk/gdu-format-dialog.h | 2 +
src/gdu-gtk/gdu-gtk-enums.h | 2 +
src/gdu-gtk/gdu-gtk-types.h | 1 +
src/gdu-gtk/gdu-gtk.h | 1 +
src/gdu-gtk/gdu-size-widget.c | 42 +++--
src/gdu/gdu-drive.c | 77 +++++++++
src/gdu/gdu-drive.h | 4 +
src/palimpsest/gdu-section-volumes.c | 262 ++++++++++++++++++++++++++++-
12 files changed, 740 insertions(+), 25 deletions(-)
---
diff --git a/src/gdu-gtk/Makefile.am b/src/gdu-gtk/Makefile.am
index edf227c..2710b75 100644
--- a/src/gdu-gtk/Makefile.am
+++ b/src/gdu-gtk/Makefile.am
@@ -48,6 +48,7 @@ libgdu_gtkinclude_HEADERS = \
gdu-edit-partition-dialog.h \
gdu-format-dialog.h \
gdu-partition-dialog.h \
+ gdu-create-partition-dialog.h \
$(NULL)
libgdu_gtk_la_SOURCES = \
@@ -73,6 +74,7 @@ libgdu_gtk_la_SOURCES = \
gdu-edit-partition-dialog.h gdu-edit-partition-dialog.c \
gdu-format-dialog.h gdu-format-dialog.c \
gdu-partition-dialog.h gdu-partition-dialog.c \
+ gdu-create-partition-dialog.h gdu-create-partition-dialog.c \
$(NULL)
libgdu_gtk_la_CPPFLAGS = \
diff --git a/src/gdu-gtk/gdu-create-partition-dialog.c b/src/gdu-gtk/gdu-create-partition-dialog.c
new file mode 100644
index 0000000..4a6d7b4
--- /dev/null
+++ b/src/gdu-gtk/gdu-create-partition-dialog.c
@@ -0,0 +1,246 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * format-window.c
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Tomas Bzatek <tbzatek redhat com>
+ * David Zeuthen <davidz redhat com>
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gdu/gdu.h>
+#include <gdu-gtk/gdu-gtk.h>
+
+#include "gdu-format-dialog.h"
+
+struct GduCreatePartitionDialogPrivate
+{
+ guint64 max_size;
+ GtkWidget *size_widget;
+ GduPresentable *drive;
+};
+
+enum
+{
+ PROP_0,
+ PROP_SIZE,
+ PROP_MAX_SIZE,
+ PROP_DRIVE
+};
+
+static void gdu_create_partition_dialog_constructed (GObject *object);
+
+G_DEFINE_TYPE (GduCreatePartitionDialog, gdu_create_partition_dialog, GDU_TYPE_FORMAT_DIALOG)
+
+static void
+gdu_create_partition_dialog_finalize (GObject *object)
+{
+ //GduCreatePartitionDialog *dialog = GDU_CREATE_PARTITION_DIALOG (object);
+
+ if (G_OBJECT_CLASS (gdu_create_partition_dialog_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (gdu_create_partition_dialog_parent_class)->finalize (object);
+}
+
+static void
+gdu_create_partition_dialog_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GduCreatePartitionDialog *dialog = GDU_CREATE_PARTITION_DIALOG (object);
+
+ switch (property_id) {
+ case PROP_SIZE:
+ g_value_set_uint64 (value, gdu_create_partition_dialog_get_size (dialog));
+ break;
+
+ case PROP_MAX_SIZE:
+ g_value_set_uint64 (value, dialog->priv->max_size);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gdu_create_partition_dialog_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GduCreatePartitionDialog *dialog = GDU_CREATE_PARTITION_DIALOG (object);
+
+ switch (property_id) {
+ case PROP_MAX_SIZE:
+ dialog->priv->max_size = g_value_get_uint64 (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gdu_create_partition_dialog_class_init (GduCreatePartitionDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GduCreatePartitionDialogPrivate));
+
+ object_class->get_property = gdu_create_partition_dialog_get_property;
+ object_class->set_property = gdu_create_partition_dialog_set_property;
+ object_class->constructed = gdu_create_partition_dialog_constructed;
+ object_class->finalize = gdu_create_partition_dialog_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_MAX_SIZE,
+ g_param_spec_uint64 ("max-size",
+ _("Maximum Partition Size"),
+ _("The maximum possible partition size"),
+ 0,
+ G_MAXUINT64,
+ 0,
+ 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_SIZE,
+ g_param_spec_uint64 ("size",
+ _("Partition Size"),
+ _("The requested partition size"),
+ 0,
+ G_MAXUINT64,
+ 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+}
+
+static void
+gdu_create_partition_dialog_init (GduCreatePartitionDialog *dialog)
+{
+ dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
+ GDU_TYPE_CREATE_PARTITION_DIALOG,
+ GduCreatePartitionDialogPrivate);
+}
+
+GtkWidget *
+gdu_create_partition_dialog_new (GtkWindow *parent,
+ GduPresentable *presentable,
+ guint64 max_size,
+ GduFormatDialogFlags flags)
+{
+ return GTK_WIDGET (g_object_new (GDU_TYPE_CREATE_PARTITION_DIALOG,
+ "transient-for", parent,
+ "presentable", presentable,
+ "max-size", max_size,
+ "affirmative-button-mnemonic", _("C_reate"),
+ "flags", flags,
+ NULL));
+}
+
+GtkWidget *
+gdu_create_partition_dialog_new_for_drive (GtkWindow *parent,
+ GduDevice *device,
+ guint64 max_size,
+ GduFormatDialogFlags flags)
+{
+ return GTK_WIDGET (g_object_new (GDU_TYPE_CREATE_PARTITION_DIALOG,
+ "transient-for", parent,
+ "drive-device", device,
+ "max-size", max_size,
+ "affirmative-button-mnemonic", _("C_reate"),
+ "flags", flags,
+ NULL));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+guint64
+gdu_create_partition_dialog_get_size (GduCreatePartitionDialog *dialog)
+{
+ g_return_val_if_fail (GDU_IS_CREATE_PARTITION_DIALOG (dialog), 0);
+ return gdu_size_widget_get_size (GDU_SIZE_WIDGET (dialog->priv->size_widget));
+}
+
+guint64
+gdu_create_partition_dialog_get_max_size (GduCreatePartitionDialog *dialog)
+{
+ g_return_val_if_fail (GDU_IS_CREATE_PARTITION_DIALOG (dialog), 0);
+ return dialog->priv->max_size;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+gdu_create_partition_dialog_constructed (GObject *object)
+{
+ GduCreatePartitionDialog *dialog = GDU_CREATE_PARTITION_DIALOG (object);
+ gchar *s;
+ gchar *s2;
+ GtkWidget *table;
+ GtkWidget *label;
+ GtkWidget *size_widget;
+ guint row;
+
+ table = gdu_format_dialog_get_table (GDU_FORMAT_DIALOG (dialog));
+ g_object_get (table,
+ "n-rows", &row,
+ NULL);
+
+ /* add partition size widget before other widgets in the for GduFormatDialog */
+ 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), _("_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 (0, 0, dialog->priv->max_size);
+ gdu_size_widget_set_size (GDU_SIZE_WIDGET (size_widget), dialog->priv->max_size);
+ 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);
+ dialog->priv->size_widget = size_widget;
+ row++;
+
+ /* run constructed() for parent class (GduFormatDialog) */
+ if (G_OBJECT_CLASS (gdu_create_partition_dialog_parent_class)->constructed != NULL)
+ G_OBJECT_CLASS (gdu_create_partition_dialog_parent_class)->constructed (object);
+
+ /* adjust window title */
+ s2 = gdu_presentable_get_vpd_name (gdu_dialog_get_presentable (GDU_DIALOG (dialog)));
+ /* Translators: The %s is the name of the drive */
+ s = g_strdup_printf (_("Create partition on %s"), s2);
+ gtk_window_set_title (GTK_WINDOW (dialog), s);
+ g_free (s);
+
+
+ g_free (s2);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/gdu-gtk/gdu-create-partition-dialog.h b/src/gdu-gtk/gdu-create-partition-dialog.h
new file mode 100644
index 0000000..fc01dbb
--- /dev/null
+++ b/src/gdu-gtk/gdu-create-partition-dialog.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ *
+ */
+
+#ifndef __GDU_CREATE_PARTITION_DIALOG_H
+#define __GDU_CREATE_PARTITION_DIALOG_H
+
+#include <gtk/gtk.h>
+#include <gdu-gtk/gdu-gtk.h>
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_CREATE_PARTITION_DIALOG gdu_create_partition_dialog_get_type()
+#define GDU_CREATE_PARTITION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDU_TYPE_CREATE_PARTITION_DIALOG, GduCreatePartitionDialog))
+#define GDU_CREATE_PARTITION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDU_TYPE_CREATE_PARTITION_DIALOG, GduCreatePartitionDialogClass))
+#define GDU_IS_CREATE_PARTITION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDU_TYPE_CREATE_PARTITION_DIALOG))
+#define GDU_IS_CREATE_PARTITION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDU_TYPE_CREATE_PARTITION_DIALOG))
+#define GDU_CREATE_PARTITION_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDU_TYPE_CREATE_PARTITION_DIALOG, GduCreatePartitionDialogClass))
+
+typedef struct GduCreatePartitionDialogClass GduCreatePartitionDialogClass;
+typedef struct GduCreatePartitionDialogPrivate GduCreatePartitionDialogPrivate;
+
+struct GduCreatePartitionDialog
+{
+ GduFormatDialog parent;
+
+ /*< private >*/
+ GduCreatePartitionDialogPrivate *priv;
+};
+
+struct GduCreatePartitionDialogClass
+{
+ GduFormatDialogClass parent_class;
+};
+
+GType gdu_create_partition_dialog_get_type (void) G_GNUC_CONST;
+GtkWidget *gdu_create_partition_dialog_new (GtkWindow *parent,
+ GduPresentable *presentable,
+ guint64 max_size,
+ GduFormatDialogFlags flags);
+GtkWidget *gdu_create_partition_dialog_new_for_drive (GtkWindow *parent,
+ GduDevice *device,
+ guint64 max_size,
+ GduFormatDialogFlags flags);
+guint64 gdu_create_partition_dialog_get_size (GduCreatePartitionDialog *dialog);
+guint64 gdu_create_partition_dialog_get_max_size (GduCreatePartitionDialog *dialog);
+
+G_END_DECLS
+
+#endif /* __GDU_CREATE_PARTITION_DIALOG_H */
+
diff --git a/src/gdu-gtk/gdu-format-dialog.c b/src/gdu-gtk/gdu-format-dialog.c
index 07ca3b1..c9ad5ac 100644
--- a/src/gdu-gtk/gdu-format-dialog.c
+++ b/src/gdu-gtk/gdu-format-dialog.c
@@ -34,6 +34,9 @@
struct GduFormatDialogPrivate
{
GduFormatDialogFlags flags;
+ gchar *affirmative_button_mnemonic;
+
+ GtkWidget *table;
GtkWidget *fs_label_entry;
GtkWidget *fs_type_combo_box;
@@ -58,6 +61,7 @@ enum
PROP_FS_LABEL,
PROP_ENCRYPT,
PROP_TAKE_OWNERSHIP,
+ PROP_AFFIRMATIVE_BUTTON_MNEMONIC,
};
static void gdu_format_dialog_constructed (GObject *object);
@@ -71,6 +75,7 @@ gdu_format_dialog_finalize (GObject *object)
g_free (dialog->priv->fs_type);
g_strfreev (dialog->priv->fs_options);
+ g_free (dialog->priv->affirmative_button_mnemonic);
if (dialog->priv->removed_signal_handler_id > 0) {
g_signal_handler_disconnect (gdu_dialog_get_presentable (GDU_DIALOG (dialog)),
@@ -133,6 +138,10 @@ gdu_format_dialog_set_property (GObject *object,
dialog->priv->flags = g_value_get_flags (value);
break;
+ case PROP_AFFIRMATIVE_BUTTON_MNEMONIC:
+ dialog->priv->affirmative_button_mnemonic = g_value_dup_string (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -219,12 +228,29 @@ gdu_format_dialog_class_init (GduFormatDialogClass *klass)
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property (object_class,
+ PROP_AFFIRMATIVE_BUTTON_MNEMONIC,
+ g_param_spec_string ("affirmative-button-mnemonic",
+ _("Affirmative Button Mnemonic"),
+ _("The mnemonic label for the affirmative button"),
+ /* Translators: Format is used as a verb here */
+ _("_Format"),
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
}
static void
gdu_format_dialog_init (GduFormatDialog *dialog)
{
- dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog, GDU_TYPE_FORMAT_DIALOG, GduFormatDialogPrivate);
+ dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
+ GDU_TYPE_FORMAT_DIALOG,
+ GduFormatDialogPrivate);
+
+ dialog->priv->table = gtk_table_new (2, 2, FALSE);
}
GtkWidget *
@@ -300,6 +326,14 @@ gdu_format_dialog_get_take_ownership (GduFormatDialog *dialog)
return dialog->priv->take_ownership;
}
+GtkWidget *
+gdu_format_dialog_get_table (GduFormatDialog *dialog)
+{
+ g_return_val_if_fail (GDU_IS_FORMAT_DIALOG (dialog), NULL);
+ return dialog->priv->table;
+}
+
+
/* ---------------------------------------------------------------------------------------------------- */
static void
@@ -369,7 +403,8 @@ update (GduFormatDialog *dialog)
}
if (! (dialog->priv->flags & GDU_FORMAT_DIALOG_FLAGS_SIMPLE)) {
- if (g_strcmp0 (dialog->priv->fs_type, "empty") == 0) {
+ if (g_strcmp0 (dialog->priv->fs_type, "empty") == 0 ||
+ g_strcmp0 (dialog->priv->fs_type, "msdos_extended_partition") == 0) {
gtk_widget_hide (dialog->priv->encrypt_check_button);
dialog->priv->encrypt = FALSE;
} else {
@@ -468,8 +503,7 @@ gdu_format_dialog_constructed (GObject *object)
gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (GTK_DIALOG (dialog),
- /* Translators: Format is used as a verb here */
- _("_Format"),
+ dialog->priv->affirmative_button_mnemonic,
GTK_RESPONSE_OK);
if (dialog->priv->flags & GDU_FORMAT_DIALOG_FLAGS_DISK_UTILITY_BUTTON) {
@@ -501,9 +535,10 @@ gdu_format_dialog_constructed (GObject *object)
vbox2 = gtk_vbox_new (FALSE, 6);
gtk_container_add (GTK_CONTAINER (align), vbox2);
- row = 0;
-
- table = gtk_table_new (2, 2, FALSE);
+ table = dialog->priv->table;
+ g_object_get (table,
+ "n-rows", &row,
+ NULL);
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);
@@ -532,7 +567,13 @@ gdu_format_dialog_constructed (GObject *object)
dialog->priv->encrypt = FALSE;
dialog->priv->take_ownership = FALSE;
} else {
- combo_box = gdu_util_fstype_combo_box_create (gdu_dialog_get_pool (GDU_DIALOG (dialog)), NULL);
+ const gchar *include_extended_partitions_for_scheme;
+
+ include_extended_partitions_for_scheme = NULL;
+ if (dialog->priv->flags & GDU_FORMAT_DIALOG_FLAGS_ALLOW_MSDOS_EXTENDED)
+ include_extended_partitions_for_scheme = "mbr";
+ combo_box = gdu_util_fstype_combo_box_create (gdu_dialog_get_pool (GDU_DIALOG (dialog)),
+ include_extended_partitions_for_scheme);
gdu_util_fstype_combo_box_select (combo_box, "ext4");
dialog->priv->fs_type = g_strdup ("ext4");
dialog->priv->fs_options = NULL;
diff --git a/src/gdu-gtk/gdu-format-dialog.h b/src/gdu-gtk/gdu-format-dialog.h
index 67c3ee2..29f4b9c 100644
--- a/src/gdu-gtk/gdu-format-dialog.h
+++ b/src/gdu-gtk/gdu-format-dialog.h
@@ -70,6 +70,8 @@ gchar **gdu_format_dialog_get_fs_options (GduFormatDialog *dialog);
gboolean gdu_format_dialog_get_encrypt (GduFormatDialog *dialog);
gboolean gdu_format_dialog_get_take_ownership (GduFormatDialog *dialog);
+GtkWidget *gdu_format_dialog_get_table (GduFormatDialog *dialog);
+
G_END_DECLS
#endif /* __GDU_FORMAT_DIALOG_H */
diff --git a/src/gdu-gtk/gdu-gtk-enums.h b/src/gdu-gtk/gdu-gtk-enums.h
index e5968d0..d062e1b 100644
--- a/src/gdu-gtk/gdu-gtk-enums.h
+++ b/src/gdu-gtk/gdu-gtk-enums.h
@@ -79,6 +79,7 @@ typedef enum {
* @GDU_FORMAT_DIALOG_FLAGS_NONE: No flags set.
* @GDU_FORMAT_DIALOG_FLAGS_SIMPLE: Show a simple form of the dialog.
* @GDU_FORMAT_DIALOG_FLAGS_DISK_UTILITY_BUTTON: Show a "Disk Utility" button.
+ * @GDU_FORMAT_DIALOG_FLAGS_ALLOW_MSDOS_EXTENDED: Allow selection MS-DOS extended partition instead of a file system.
*
* Flags used when creating a #GduFormatDialog.
*/
@@ -86,6 +87,7 @@ typedef enum {
GDU_FORMAT_DIALOG_FLAGS_NONE = 0,
GDU_FORMAT_DIALOG_FLAGS_SIMPLE = (1<<0),
GDU_FORMAT_DIALOG_FLAGS_DISK_UTILITY_BUTTON = (1<<1),
+ GDU_FORMAT_DIALOG_FLAGS_ALLOW_MSDOS_EXTENDED = (1<<2)
} GduFormatDialogFlags;
#endif /* GDU_GTK_ENUMS_H */
diff --git a/src/gdu-gtk/gdu-gtk-types.h b/src/gdu-gtk/gdu-gtk-types.h
index 200616f..fa183d0 100644
--- a/src/gdu-gtk/gdu-gtk-types.h
+++ b/src/gdu-gtk/gdu-gtk-types.h
@@ -55,6 +55,7 @@ typedef struct GduDialog GduDialog;
typedef struct GduEditPartitionDialog GduEditPartitionDialog;
typedef struct GduFormatDialog GduFormatDialog;
typedef struct GduPartitionDialog GduPartitionDialog;
+typedef struct GduCreatePartitionDialog GduCreatePartitionDialog;
G_END_DECLS
diff --git a/src/gdu-gtk/gdu-gtk.h b/src/gdu-gtk/gdu-gtk.h
index bc5945e..5c40c09 100644
--- a/src/gdu-gtk/gdu-gtk.h
+++ b/src/gdu-gtk/gdu-gtk.h
@@ -47,6 +47,7 @@
#include <gdu-gtk/gdu-edit-partition-dialog.h>
#include <gdu-gtk/gdu-format-dialog.h>
#include <gdu-gtk/gdu-partition-dialog.h>
+#include <gdu-gtk/gdu-create-partition-dialog.h>
#undef __GDU_GTK_INSIDE_GDU_GTK_H
G_BEGIN_DECLS
diff --git a/src/gdu-gtk/gdu-size-widget.c b/src/gdu-gtk/gdu-size-widget.c
index 20bced3..3f66aba 100644
--- a/src/gdu-gtk/gdu-size-widget.c
+++ b/src/gdu-gtk/gdu-size-widget.c
@@ -150,19 +150,6 @@ on_hscale_value_changed (GtkRange *range,
}
}
-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,
@@ -225,9 +212,34 @@ gdu_size_widget_constructed (GObject *object)
}
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
+gdu_size_widget_mnemonic_activate (GtkWidget *_widget,
+ gboolean group_cycling)
+{
+ GduSizeWidget *widget = GDU_SIZE_WIDGET (_widget);
+ return gtk_widget_mnemonic_activate (widget->priv->hscale, group_cycling);
+}
+
+static void
gdu_size_widget_class_init (GduSizeWidgetClass *klass)
{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GObjectClass *gobject_class;
+ GtkWidgetClass *widget_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ widget_class = GTK_WIDGET_CLASS (klass);
g_type_class_add_private (klass, sizeof (GduSizeWidgetPrivate));
@@ -236,6 +248,8 @@ gdu_size_widget_class_init (GduSizeWidgetClass *klass)
gobject_class->constructed = gdu_size_widget_constructed;
gobject_class->finalize = gdu_size_widget_finalize;
+ widget_class->mnemonic_activate = gdu_size_widget_mnemonic_activate;
+
g_object_class_install_property (gobject_class,
PROP_SIZE,
g_param_spec_uint64 ("size",
diff --git a/src/gdu/gdu-drive.c b/src/gdu/gdu-drive.c
index 05492a7..e9e40a1 100644
--- a/src/gdu/gdu-drive.c
+++ b/src/gdu/gdu-drive.c
@@ -239,6 +239,83 @@ gdu_drive_has_unallocated_space (GduDrive *drive,
out_presentable);
}
+/**
+ * gdu_drive_count_mbr_partitions:
+ * @drive: A #GduDrive.
+ * @out_num_primary_partitions: Return location for number of primary partitions.
+ * @out_has_extended_partition: Return location for number of extended partitions.
+ *
+ * Counts the number of primary partitions and figures out if there's an extended partition.
+ *
+ * Returns: %TRUE if @out_num_logical_partitions and @out_has_extended_partition is set, %FALSE otherwise.
+ */
+gboolean
+gdu_drive_count_mbr_partitions (GduDrive *drive,
+ guint *out_num_primary_partitions,
+ gboolean *out_has_extended_partition)
+{
+ guint num_primary_partitions;
+ gboolean has_extended_partition;
+ gboolean ret;
+ GduDevice *device;
+ GduPool *pool;
+ GList *enclosed_presentables;
+ GList *l;
+
+ ret = FALSE;
+ num_primary_partitions = 0;
+ has_extended_partition = FALSE;
+ pool = NULL;
+ device = NULL;
+
+ device = gdu_presentable_get_device (GDU_PRESENTABLE (drive));
+ if (device == NULL)
+ goto out;
+
+ pool = gdu_presentable_get_pool (GDU_PRESENTABLE (drive));
+
+ if (!gdu_device_is_partition_table (device) ||
+ g_strcmp0 (gdu_device_partition_table_get_scheme (device), "mbr") != 0) {
+ goto out;
+ }
+
+ enclosed_presentables = gdu_pool_get_enclosed_presentables (pool, GDU_PRESENTABLE (drive));
+ for (l = enclosed_presentables; l != NULL; l = l->next) {
+ GduPresentable *ep = GDU_PRESENTABLE (l->data);
+
+ if (GDU_IS_VOLUME (ep)) {
+ gint type;
+ GduDevice *ep_device;
+
+ ep_device = gdu_presentable_get_device (ep);
+
+ type = strtol (gdu_device_partition_get_type (ep_device), NULL, 0);
+ if (type == 0x05 || type == 0x0f || type == 0x85) {
+ has_extended_partition = TRUE;
+ }
+ num_primary_partitions++;
+ g_object_unref (ep_device);
+ }
+ }
+ g_list_foreach (enclosed_presentables, (GFunc) g_object_unref, NULL);
+ g_list_free (enclosed_presentables);
+
+ ret = TRUE;
+
+ out:
+ if (device != NULL)
+ g_object_unref (device);
+ if (pool != NULL)
+ g_object_unref (pool);
+
+ if (out_num_primary_partitions != NULL)
+ *out_num_primary_partitions = num_primary_partitions;
+ if (out_has_extended_partition != NULL)
+ *out_has_extended_partition = has_extended_partition;
+ return ret;
+}
+
+
static gboolean
gdu_drive_has_unallocated_space_real (GduDrive *drive,
gboolean *out_whole_disk_is_unitialized,
diff --git a/src/gdu/gdu-drive.h b/src/gdu/gdu-drive.h
index 0e5a6fe..00aad86 100644
--- a/src/gdu/gdu-drive.h
+++ b/src/gdu/gdu-drive.h
@@ -92,6 +92,10 @@ gboolean gdu_drive_has_unallocated_space (GduDrive *drive,
guint64 *out_largest_segment,
GduPresentable **out_presentable);
+gboolean gdu_drive_count_mbr_partitions (GduDrive *drive,
+ guint *out_num_primary_partitions,
+ gboolean *out_has_extended_partition);
+
G_END_DECLS
#endif /* __GDU_DRIVE_H */
diff --git a/src/palimpsest/gdu-section-volumes.c b/src/palimpsest/gdu-section-volumes.c
index 30cb196..597bfb9 100644
--- a/src/palimpsest/gdu-section-volumes.c
+++ b/src/palimpsest/gdu-section-volumes.c
@@ -837,6 +837,263 @@ on_luks_change_passphrase_button_clicked (GduButtonElement *button_element,
/* ---------------------------------------------------------------------------------------------------- */
+static gboolean
+can_create_partition (GduSectionVolumes *section,
+ GduVolumeHole *hole,
+ gboolean *out_can_create_extended)
+{
+ GduPresentable *drive;
+ GduDevice *drive_device;
+ gboolean can_create;
+ gboolean can_create_extended;
+ guint num_primary;
+ gboolean has_extended;
+ const gchar *part_scheme;
+ GduPresentable *enclosing_presentable_for_hole;
+
+ can_create = FALSE;
+ can_create_extended = FALSE;
+
+ enclosing_presentable_for_hole = NULL;
+ drive_device = NULL;
+
+ drive = gdu_section_get_presentable (GDU_SECTION (section));
+ drive_device = gdu_presentable_get_device (drive);
+ if (drive_device == NULL)
+ goto out;
+
+ part_scheme = gdu_device_partition_table_get_scheme (drive_device);
+
+ if (g_strcmp0 (part_scheme, "mbr") != 0) {
+ can_create = TRUE;
+ goto out;
+ }
+
+ enclosing_presentable_for_hole = gdu_presentable_get_enclosing_presentable (GDU_PRESENTABLE (hole));
+ if (GDU_IS_DRIVE (enclosing_presentable_for_hole)) {
+ /* hole is in primary partition space */
+ if (gdu_drive_count_mbr_partitions (GDU_DRIVE (drive), &num_primary, &has_extended)) {
+ if (num_primary < 4) {
+ can_create = TRUE;
+ if (!has_extended)
+ can_create_extended = TRUE;
+ }
+ }
+ } else {
+ /* hole is in an extended partition */
+ can_create = TRUE;
+ }
+
+ out:
+ if (enclosing_presentable_for_hole != NULL)
+ g_object_unref (enclosing_presentable_for_hole);
+
+ if (drive_device != NULL)
+ g_object_unref (drive_device);
+
+ if (out_can_create_extended)
+ *out_can_create_extended = can_create_extended;
+
+ return can_create;
+}
+
+
+typedef struct {
+ GduShell *shell;
+ GduPresentable *presentable;
+ char *encrypt_passphrase;
+ gboolean save_in_keyring;
+ gboolean save_in_keyring_session;
+} CreatePartitionData;
+
+static void
+create_partition_data_free (CreatePartitionData *data)
+{
+ if (data->shell != NULL)
+ g_object_unref (data->shell);
+ if (data->presentable != NULL)
+ g_object_unref (data->presentable);
+ if (data->encrypt_passphrase != NULL) {
+ memset (data->encrypt_passphrase, '\0', strlen (data->encrypt_passphrase));
+ g_free (data->encrypt_passphrase);
+ }
+ g_free (data);
+}
+
+static void
+partition_create_op_callback (GduDevice *device,
+ gchar *created_device_object_path,
+ GError *error,
+ gpointer user_data)
+{
+ CreatePartitionData *data = user_data;
+
+ if (error != NULL) {
+ GtkWidget *dialog;
+ dialog = gdu_error_dialog_new_for_drive (GTK_WINDOW (gdu_shell_get_toplevel (data->shell)),
+ device,
+ _("Error creating partition"),
+ error);
+ gtk_widget_show_all (dialog);
+ gtk_window_present (GTK_WINDOW (dialog));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
+ } else {
+ g_debug ("Created %s", created_device_object_path);
+
+ if (data->encrypt_passphrase != NULL) {
+ GduDevice *cleartext_device;
+ GduPool *pool;
+
+ pool = gdu_device_get_pool (device);
+ cleartext_device = gdu_pool_get_by_object_path (pool, created_device_object_path);
+ if (cleartext_device != NULL) {
+ const gchar *cryptotext_device_object_path;
+
+ cryptotext_device_object_path = gdu_device_luks_cleartext_get_slave (cleartext_device);
+ if (cryptotext_device_object_path != NULL) {
+ GduDevice *cryptotext_device;
+
+ cryptotext_device = gdu_pool_get_by_object_path (pool,
+ cryptotext_device_object_path);
+ if (cryptotext_device != NULL) {
+ /* now set the passphrase if requested */
+ if (data->save_in_keyring || data->save_in_keyring_session) {
+ gdu_util_save_secret (cryptotext_device,
+ data->encrypt_passphrase,
+ data->save_in_keyring_session);
+ }
+ g_object_unref (cryptotext_device);
+ }
+ }
+ g_object_unref (cleartext_device);
+ }
+ }
+
+ g_free (created_device_object_path);
+ }
+
+ if (data != NULL)
+ create_partition_data_free (data);
+}
+
+static void
+on_partition_create_button_clicked (GduButtonElement *button_element,
+ gpointer user_data)
+{
+ GduSectionVolumes *section = GDU_SECTION_VOLUMES (user_data);
+ GduPresentable *v;
+ GduPresentable *drive;
+ GduDevice *drive_device;
+ GtkWindow *toplevel;
+ GtkWidget *dialog;
+ gint response;
+ GduFormatDialogFlags flags;
+ const gchar *part_scheme;
+ gboolean can_create_extended;
+
+ v = NULL;
+ drive_device = NULL;
+ dialog = NULL;
+
+ v = gdu_volume_grid_get_selected (GDU_VOLUME_GRID (section->priv->grid));
+ if (v == NULL || !GDU_IS_VOLUME_HOLE (v))
+ goto out;
+
+ drive = gdu_section_get_presentable (GDU_SECTION (section));
+ drive_device = gdu_presentable_get_device (drive);
+ if (drive_device == NULL)
+ goto out;
+
+ part_scheme = gdu_device_partition_table_get_scheme (drive_device);
+
+ flags = GDU_FORMAT_DIALOG_FLAGS_NONE;
+ if (!can_create_partition (section, GDU_VOLUME_HOLE (v), &can_create_extended))
+ goto out;
+ if (can_create_extended)
+ flags |= GDU_FORMAT_DIALOG_FLAGS_ALLOW_MSDOS_EXTENDED;
+
+ toplevel = GTK_WINDOW (gdu_shell_get_toplevel (gdu_section_get_shell (GDU_SECTION (section))));
+ dialog = gdu_create_partition_dialog_new_for_drive (toplevel,
+ drive_device,
+ gdu_presentable_get_size (v),
+ flags);
+ gtk_widget_show_all (dialog);
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_hide (dialog);
+ if (response == GTK_RESPONSE_OK) {
+ CreatePartitionData *data;
+ gchar *fs_type;
+ gchar *fs_label;
+ gboolean fs_take_ownership;
+ guint64 offset;
+ guint64 size;
+ gchar *part_type;
+
+ data = g_new0 (CreatePartitionData, 1);
+ data->shell = g_object_ref (gdu_section_get_shell (GDU_SECTION (section)));
+ data->presentable = g_object_ref (v);
+
+ if (gdu_format_dialog_get_encrypt (GDU_FORMAT_DIALOG (dialog))) {
+ data->encrypt_passphrase = gdu_util_dialog_ask_for_new_secret (GTK_WIDGET (toplevel),
+ &data->save_in_keyring,
+ &data->save_in_keyring_session);
+ if (data->encrypt_passphrase == NULL) {
+ create_partition_data_free (data);
+ goto out;
+ }
+ }
+
+ fs_type = gdu_format_dialog_get_fs_type (GDU_FORMAT_DIALOG (dialog));
+ fs_label = gdu_format_dialog_get_fs_label (GDU_FORMAT_DIALOG (dialog));
+ fs_take_ownership = gdu_format_dialog_get_take_ownership (GDU_FORMAT_DIALOG (dialog));
+
+ offset = gdu_presentable_get_offset (v);
+ size = gdu_create_partition_dialog_get_size (GDU_CREATE_PARTITION_DIALOG (dialog));
+
+ if (strcmp (fs_type, "msdos_extended_partition") == 0) {
+ part_type = g_strdup ("0x05");
+ g_free (fs_type);
+ g_free (fs_label);
+ fs_type = g_strdup ("");
+ fs_label = g_strdup ("");
+ fs_take_ownership = FALSE;
+ } else {
+ part_type = gdu_util_get_default_part_type_for_scheme_and_fstype (part_scheme,
+ fs_type,
+ size);
+ }
+
+ gdu_device_op_partition_create (drive_device,
+ offset,
+ size,
+ part_type,
+ "", /* empty partition label for now */
+ NULL, /* no flags for the partition */
+ fs_type,
+ fs_label,
+ data->encrypt_passphrase,
+ fs_take_ownership,
+ partition_create_op_callback,
+ data);
+
+ g_free (fs_type);
+ g_free (fs_label);
+ g_free (part_type);
+ }
+ out:
+ if (dialog != NULL)
+ gtk_widget_destroy (dialog);
+
+ if (drive_device != NULL)
+ g_object_unref (drive_device);
+ if (v != NULL)
+ g_object_unref (v);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
gdu_section_volumes_update (GduSection *_section)
{
@@ -1111,7 +1368,8 @@ gdu_section_volumes_update (GduSection *_section)
gdu_device_get_device_file (drive_device));
g_object_unref (drive_device);
- show_partition_create_button = TRUE;
+ if (can_create_partition (section, GDU_VOLUME_HOLE (v), NULL))
+ show_partition_create_button = TRUE;
show_format_button = FALSE;
}
@@ -1270,12 +1528,10 @@ gdu_section_volumes_constructed (GObject *object)
button_element = gdu_button_element_new (GTK_STOCK_ADD,
_("_Create Partition"),
_("Create a new partition"));
-#if 0
g_signal_connect (button_element,
"clicked",
G_CALLBACK (on_partition_create_button_clicked),
section);
-#endif
g_ptr_array_add (button_elements, button_element);
section->priv->partition_create_button = button_element;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]