[gnome-disk-utility/new-ui] Add a dialog for editing partition type and flags



commit 0c1dd4761e8923296df6ab88933a89b6216c9e7e
Author: David Zeuthen <davidz redhat com>
Date:   Fri Oct 2 14:15:58 2009 -0400

    Add a dialog for editing partition type and flags

 src/gdu-gtk/Makefile.am                 |    2 +
 src/gdu-gtk/gdu-dialog.c                |   12 +-
 src/gdu-gtk/gdu-edit-partition-dialog.c |  484 +++++++++++++++++++++++++++++++
 src/gdu-gtk/gdu-edit-partition-dialog.h |   66 +++++
 src/gdu-gtk/gdu-gtk-types.h             |    1 +
 src/gdu-gtk/gdu-gtk.h                   |    1 +
 src/palimpsest/gdu-section-volumes.c    |   96 ++++++-
 7 files changed, 653 insertions(+), 9 deletions(-)
---
diff --git a/src/gdu-gtk/Makefile.am b/src/gdu-gtk/Makefile.am
index 716e7be..5980999 100644
--- a/src/gdu-gtk/Makefile.am
+++ b/src/gdu-gtk/Makefile.am
@@ -44,6 +44,7 @@ libgdu_gtkinclude_HEADERS =              				\
 	gdu-button-element.h						\
 	gdu-button-table.h						\
 	gdu-dialog.h							\
+	gdu-edit-partition-dialog.h					\
 	$(NULL)
 
 libgdu_gtk_la_SOURCES =                 	               				\
@@ -65,6 +66,7 @@ libgdu_gtk_la_SOURCES =                 	               				\
 	gdu-button-element.h			gdu-button-element.c			\
 	gdu-button-table.h			gdu-button-table.c			\
 	gdu-dialog.h				gdu-dialog.c				\
+	gdu-edit-partition-dialog.h		gdu-edit-partition-dialog.c		\
 	$(NULL)
 
 libgdu_gtk_la_CPPFLAGS = 				\
diff --git a/src/gdu-gtk/gdu-dialog.c b/src/gdu-gtk/gdu-dialog.c
index fbe4761..6704945 100644
--- a/src/gdu-gtk/gdu-dialog.c
+++ b/src/gdu-gtk/gdu-dialog.c
@@ -85,9 +85,9 @@ gdu_dialog_get_property (GObject    *object,
 
 static void
 gdu_dialog_set_property (GObject      *object,
-                               guint         property_id,
-                               const GValue *value,
-                               GParamSpec   *pspec)
+                         guint         property_id,
+                         const GValue *value,
+                         GParamSpec   *pspec)
 {
         GduDialog *dialog = GDU_DIALOG (object);
         GduDevice *device;
@@ -98,6 +98,7 @@ gdu_dialog_set_property (GObject      *object,
                 if (g_value_get_object (value) != NULL) {
                         g_warn_if_fail (dialog->priv->presentable == NULL);
                         dialog->priv->presentable = g_value_dup_object (value);
+                        dialog->priv->device = gdu_presentable_get_device (dialog->priv->presentable);
                 }
                 break;
 
@@ -107,6 +108,7 @@ gdu_dialog_set_property (GObject      *object,
                         pool = gdu_device_get_pool (device);
                         g_warn_if_fail (dialog->priv->presentable == NULL);
                         dialog->priv->presentable = gdu_pool_get_drive_by_device (pool, device);
+                        dialog->priv->device = gdu_presentable_get_device (dialog->priv->presentable);
                         g_object_unref (pool);
                 }
                 break;
@@ -117,6 +119,7 @@ gdu_dialog_set_property (GObject      *object,
                         pool = gdu_device_get_pool (device);
                         g_warn_if_fail (dialog->priv->presentable == NULL);
                         dialog->priv->presentable = gdu_pool_get_volume_by_device (pool, device);
+                        dialog->priv->device = gdu_presentable_get_device (dialog->priv->presentable);
                         g_object_unref (pool);
                 }
                 break;
@@ -184,9 +187,6 @@ gdu_dialog_get_presentable (GduDialog *dialog)
 GduDevice *
 gdu_dialog_get_device (GduDialog *dialog)
 {
-        if (dialog->priv->device == NULL) {
-                dialog->priv->device = gdu_presentable_get_device (dialog->priv->presentable);
-        }
         return dialog->priv->device;
 }
 
diff --git a/src/gdu-gtk/gdu-edit-partition-dialog.c b/src/gdu-gtk/gdu-edit-partition-dialog.c
new file mode 100644
index 0000000..293dfec
--- /dev/null
+++ b/src/gdu-gtk/gdu-edit-partition-dialog.c
@@ -0,0 +1,484 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* gdu-edit-partition-dialog.c
+ *
+ * Copyright (C) 2009 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.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <atasmart.h>
+#include <glib/gstdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "gdu-gtk.h"
+#include "gdu-edit-partition-dialog.h"
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+struct GduEditPartitionDialogPrivate
+{
+        GtkWidget *part_label_entry;
+        GtkWidget *part_type_combo_box;
+        GtkWidget *part_flag_boot_check_button;
+        GtkWidget *part_flag_required_check_button;
+};
+
+enum {
+        PROP_0,
+        PROP_PARTITION_LABEL,
+        PROP_PARTITION_TYPE,
+        PROP_PARTITION_FLAGS,
+};
+
+G_DEFINE_TYPE (GduEditPartitionDialog, gdu_edit_partition_dialog, GDU_TYPE_DIALOG)
+
+static void
+gdu_edit_partition_dialog_finalize (GObject *object)
+{
+        //GduEditPartitionDialog *dialog = GDU_EDIT_PARTITION_DIALOG (object);
+
+        if (G_OBJECT_CLASS (gdu_edit_partition_dialog_parent_class)->finalize != NULL)
+                G_OBJECT_CLASS (gdu_edit_partition_dialog_parent_class)->finalize (object);
+}
+
+static void
+gdu_edit_partition_dialog_get_property (GObject    *object,
+                                        guint       property_id,
+                                        GValue     *value,
+                                        GParamSpec *pspec)
+{
+        GduEditPartitionDialog *dialog = GDU_EDIT_PARTITION_DIALOG (object);
+
+        switch (property_id) {
+        case PROP_PARTITION_LABEL:
+                g_value_take_string (value, gdu_edit_partition_dialog_get_partition_label (dialog));
+                break;
+
+        case PROP_PARTITION_TYPE:
+                g_value_take_string (value, gdu_edit_partition_dialog_get_partition_type (dialog));
+                break;
+
+        case PROP_PARTITION_FLAGS:
+                g_value_take_boxed (value, gdu_edit_partition_dialog_get_partition_flags (dialog));
+                break;
+
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+                break;
+        }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+has_flag (char **flags, const char *flag)
+{
+        int n;
+
+        n = 0;
+        while (flags != NULL && flags[n] != NULL) {
+                if (strcmp (flags[n], flag) == 0)
+                        return TRUE;
+                n++;
+        }
+        return FALSE;
+}
+
+static void
+update_apply_sensitivity (GduEditPartitionDialog *dialog)
+{
+        gboolean label_differ;
+        gboolean type_differ;
+        gboolean flags_differ;
+        char *selected_type;
+        GduDevice *device;
+        char **flags;
+
+        device = gdu_dialog_get_device (GDU_DIALOG (dialog));
+
+        label_differ = FALSE;
+        type_differ = FALSE;
+        flags_differ = FALSE;
+
+        if (strcmp (gdu_device_partition_get_scheme (device), "gpt") == 0 ||
+            strcmp (gdu_device_partition_get_scheme (device), "apm") == 0) {
+                if (strcmp (gdu_device_partition_get_label (device),
+                            gtk_entry_get_text (GTK_ENTRY (dialog->priv->part_label_entry))) != 0) {
+                        label_differ = TRUE;
+                }
+        }
+
+        flags = gdu_device_partition_get_flags (device);
+        if (has_flag (flags, "boot") !=
+            gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->part_flag_boot_check_button)))
+                flags_differ = TRUE;
+        if (has_flag (flags, "required") !=
+            gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->part_flag_required_check_button)))
+                flags_differ = TRUE;
+
+        selected_type = gdu_util_part_type_combo_box_get_selected (dialog->priv->part_type_combo_box);
+        if (selected_type != NULL && strcmp (gdu_device_partition_get_type (device), selected_type) != 0) {
+                type_differ = TRUE;
+        }
+        g_free (selected_type);
+
+        if (label_differ || type_differ || flags_differ) {
+                gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY, TRUE);
+        } else {
+                gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY, FALSE);
+        }
+}
+
+static void
+update (GduEditPartitionDialog *dialog)
+{
+        gboolean show_flag_boot;
+        gboolean show_flag_required;
+        gboolean can_edit_part_label;
+        GduDevice *device;
+        const char *scheme;
+        guint64 size;
+        char **flags;
+
+        device = gdu_dialog_get_device (GDU_DIALOG (dialog));
+
+        size = gdu_device_partition_get_size (device);
+        scheme = gdu_device_partition_get_scheme (device);
+
+        gdu_util_part_type_combo_box_rebuild (dialog->priv->part_type_combo_box, scheme);
+        gdu_util_part_type_combo_box_select (dialog->priv->part_type_combo_box,
+                                             gdu_device_partition_get_type (device));
+
+        can_edit_part_label = FALSE;
+        show_flag_boot = FALSE;
+        show_flag_required = FALSE;
+
+        if (strcmp (scheme, "mbr") == 0) {
+                show_flag_boot = TRUE;
+        }
+
+        if (strcmp (scheme, "gpt") == 0) {
+                can_edit_part_label = TRUE;
+                show_flag_required = TRUE;
+        }
+
+        if (strcmp (scheme, "apm") == 0) {
+                can_edit_part_label = TRUE;
+                show_flag_boot = TRUE;
+        }
+
+        if (show_flag_boot)
+                gtk_widget_show (dialog->priv->part_flag_boot_check_button);
+        else
+                gtk_widget_hide (dialog->priv->part_flag_boot_check_button);
+
+        if (show_flag_required)
+                gtk_widget_show (dialog->priv->part_flag_required_check_button);
+        else
+                gtk_widget_hide (dialog->priv->part_flag_required_check_button);
+
+        flags = gdu_device_partition_get_flags (device);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->part_flag_boot_check_button),
+                                      has_flag (flags, "boot"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->part_flag_required_check_button),
+                                      has_flag (flags, "required"));
+
+        gtk_widget_set_sensitive (dialog->priv->part_label_entry, can_edit_part_label);
+        if (can_edit_part_label) {
+                gtk_entry_set_text (GTK_ENTRY (dialog->priv->part_label_entry),
+                                    gdu_device_partition_get_label (device));
+                /* TODO: check real max length */
+                gtk_entry_set_max_length (GTK_ENTRY (dialog->priv->part_label_entry), 31);
+        } else {
+                gtk_entry_set_text (GTK_ENTRY (dialog->priv->part_label_entry), "");
+        }
+
+        update_apply_sensitivity (dialog);
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+part_type_combo_box_changed (GtkWidget *combo_box,
+                             gpointer   user_data)
+{
+        GduEditPartitionDialog *dialog = GDU_EDIT_PARTITION_DIALOG (user_data);
+        update_apply_sensitivity (dialog);
+}
+
+static void
+part_label_entry_changed (GtkWidget *combo_box,
+                          gpointer   user_data)
+{
+        GduEditPartitionDialog *dialog = GDU_EDIT_PARTITION_DIALOG (user_data);
+        update_apply_sensitivity (dialog);
+}
+
+static void
+part_flag_check_button_clicked (GtkWidget *check_button,
+                                gpointer   user_data)
+{
+        GduEditPartitionDialog *dialog = GDU_EDIT_PARTITION_DIALOG (user_data);
+        update_apply_sensitivity (dialog);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+gdu_edit_partition_dialog_constructed (GObject *object)
+{
+        GduEditPartitionDialog *dialog = GDU_EDIT_PARTITION_DIALOG (object);
+        GtkWidget *content_area;
+        GtkWidget *hbox;
+        GtkWidget *vbox;
+        GtkWidget *image;
+        GtkWidget *label;
+        gchar *s;
+        GIcon *icon;
+        gchar *drive_vpd_name;
+        GduPresentable *p;
+        GduDevice *d;
+        GduPool *pool;
+        GduPresentable *drive;
+        GduDevice *drive_device;
+
+        gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+        gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
+
+        gtk_dialog_add_button (GTK_DIALOG (dialog),
+                               GTK_STOCK_CLOSE,
+                               GTK_RESPONSE_CLOSE);
+
+        gtk_dialog_add_button (GTK_DIALOG (dialog),
+                               GTK_STOCK_APPLY,
+                               GTK_RESPONSE_APPLY);
+
+        content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+        icon = gdu_presentable_get_icon (gdu_dialog_get_presentable (GDU_DIALOG (dialog)));
+
+        hbox = gtk_hbox_new (FALSE, 12);
+        gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0);
+
+        image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_DIALOG);
+        gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+        gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+
+        vbox = gtk_vbox_new (FALSE, 12);
+        gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
+
+        p = gdu_dialog_get_presentable (GDU_DIALOG (dialog));
+        d = gdu_presentable_get_device (p);
+        pool = gdu_presentable_get_pool (p);
+        drive_device = gdu_pool_get_by_object_path (pool, gdu_device_partition_get_slave (d));
+        drive = gdu_pool_get_drive_by_device (pool, drive_device);
+
+        drive_vpd_name = gdu_presentable_get_vpd_name (drive);
+        s = g_strdup_printf (_("Edit partition %d of %s"),
+                             gdu_device_partition_get_number (d),
+                             drive_vpd_name);
+        gtk_window_set_title (GTK_WINDOW (dialog), s);
+        g_free (s);
+
+        /* --- */
+
+        GtkWidget *table;
+        GtkWidget *entry;
+        GtkWidget *combo_box;
+        GtkWidget *check_button;
+        gint row;
+
+        table = gtk_table_new (2, 2, FALSE);
+        gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+        gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
+
+        row = 0;
+
+        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), _("Part_ition Label:"));
+        gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+                          GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+        entry = gtk_entry_new ();
+        gtk_table_attach (GTK_TABLE (table), entry, 1, 2, row, row + 1,
+                          GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+        dialog->priv->part_label_entry = entry;
+
+        row++;
+
+        /* --- */
+
+        /* partition type */
+        label = gtk_label_new (NULL);
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        /* Translators: 'Type' means partition type here */
+        gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), _("Ty_pe:"));
+        gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+                          GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+        combo_box = gdu_util_part_type_combo_box_create (NULL);
+        gtk_table_attach (GTK_TABLE (table), combo_box, 1, 2, row, row +1,
+                          GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+        gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo_box);
+        dialog->priv->part_type_combo_box = combo_box;
+
+        row++;
+
+        /* --- */
+
+        /* flag used by mbr, apm */
+        check_button = gtk_check_button_new_with_mnemonic (_("_Bootable"));
+        gtk_table_attach (GTK_TABLE (table), check_button, 0, 2, row, row +1,
+                          GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+        dialog->priv->part_flag_boot_check_button = check_button;
+
+        row++;
+
+        /* flag used by gpt */
+        check_button = gtk_check_button_new_with_mnemonic (_("Required / Firm_ware"));
+        gtk_table_attach (GTK_TABLE (table), check_button, 0, 2, row, row +1,
+                          GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+        dialog->priv->part_flag_required_check_button = check_button;
+
+        g_signal_connect (dialog->priv->part_type_combo_box,
+                          "changed",
+                          G_CALLBACK (part_type_combo_box_changed),
+                          dialog);
+        g_signal_connect (dialog->priv->part_label_entry,
+                          "changed",
+                          G_CALLBACK (part_label_entry_changed),
+                          dialog);
+        g_signal_connect (dialog->priv->part_flag_boot_check_button,
+                          "toggled",
+                          G_CALLBACK (part_flag_check_button_clicked),
+                          dialog);
+        g_signal_connect (dialog->priv->part_flag_required_check_button,
+                          "toggled",
+                          G_CALLBACK (part_flag_check_button_clicked),
+                          dialog);
+
+        /* control visibility of check buttons */
+        gtk_widget_set_no_show_all (dialog->priv->part_flag_boot_check_button, TRUE);
+        gtk_widget_set_no_show_all (dialog->priv->part_flag_required_check_button, TRUE);
+
+        g_object_unref (icon);
+        g_object_unref (d);
+        g_object_unref (drive_device);
+        g_object_unref (drive);
+        g_object_unref (pool);
+
+        g_free (drive_vpd_name);
+
+        update (dialog);
+
+        if (G_OBJECT_CLASS (gdu_edit_partition_dialog_parent_class)->constructed != NULL)
+                G_OBJECT_CLASS (gdu_edit_partition_dialog_parent_class)->constructed (object);
+}
+
+static void
+gdu_edit_partition_dialog_class_init (GduEditPartitionDialogClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        g_type_class_add_private (klass, sizeof (GduEditPartitionDialogPrivate));
+
+        object_class->get_property = gdu_edit_partition_dialog_get_property;
+        object_class->constructed  = gdu_edit_partition_dialog_constructed;
+        object_class->finalize     = gdu_edit_partition_dialog_finalize;
+
+        g_object_class_install_property (object_class,
+                                         PROP_PARTITION_LABEL,
+                                         g_param_spec_string ("partition-label",
+                                                              NULL,
+                                                              NULL,
+                                                              NULL,
+                                                              G_PARAM_READABLE));
+
+        g_object_class_install_property (object_class,
+                                         PROP_PARTITION_TYPE,
+                                         g_param_spec_string ("partition-type",
+                                                              NULL,
+                                                              NULL,
+                                                              NULL,
+                                                              G_PARAM_READABLE));
+
+
+        g_object_class_install_property (object_class,
+                                         PROP_PARTITION_FLAGS,
+                                         g_param_spec_boxed ("partition-flags",
+                                                             NULL,
+                                                             NULL,
+                                                             G_TYPE_STRV,
+                                                             G_PARAM_READABLE));
+
+}
+
+static void
+gdu_edit_partition_dialog_init (GduEditPartitionDialog *dialog)
+{
+        dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog, GDU_TYPE_EDIT_PARTITION_DIALOG, GduEditPartitionDialogPrivate);
+}
+
+GtkWidget *
+gdu_edit_partition_dialog_new (GtkWindow      *parent,
+                               GduPresentable *presentable)
+{
+        g_return_val_if_fail (GDU_IS_PRESENTABLE (presentable), NULL);
+        return GTK_WIDGET (g_object_new (GDU_TYPE_EDIT_PARTITION_DIALOG,
+                                         "transient-for", parent,
+                                         "presentable", presentable,
+                                         NULL));
+}
+
+gchar *
+gdu_edit_partition_dialog_get_partition_type  (GduEditPartitionDialog *dialog)
+{
+        g_return_val_if_fail (GDU_IS_EDIT_PARTITION_DIALOG (dialog), NULL);
+        return gdu_util_part_type_combo_box_get_selected (dialog->priv->part_type_combo_box);
+}
+
+gchar *
+gdu_edit_partition_dialog_get_partition_label (GduEditPartitionDialog *dialog)
+{
+        g_return_val_if_fail (GDU_IS_EDIT_PARTITION_DIALOG (dialog), NULL);
+        return g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->priv->part_label_entry)));
+}
+
+gchar **
+gdu_edit_partition_dialog_get_partition_flags (GduEditPartitionDialog *dialog)
+{
+        GPtrArray *p;
+
+        g_return_val_if_fail (GDU_IS_EDIT_PARTITION_DIALOG (dialog), NULL);
+
+        p = g_ptr_array_new ();
+        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->part_flag_boot_check_button)))
+                g_ptr_array_add (p, g_strdup ("boot"));
+        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->part_flag_required_check_button)))
+                g_ptr_array_add (p, g_strdup ("required"));
+        g_ptr_array_add (p, NULL);
+
+        return (gchar **) g_ptr_array_free (p, FALSE);
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/gdu-gtk/gdu-edit-partition-dialog.h b/src/gdu-gtk/gdu-edit-partition-dialog.h
new file mode 100644
index 0000000..3d3d5b2
--- /dev/null
+++ b/src/gdu-gtk/gdu-edit-partition-dialog.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* gdu-edit-partition-dialog.h
+ *
+ * Copyright (C) 2009 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_EDIT_PARTITION_DIALOG_H
+#define __GDU_EDIT_PARTITION_DIALOG_H
+
+#include <gdu-gtk/gdu-gtk-types.h>
+#include <gdu-gtk/gdu-dialog.h>
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_EDIT_PARTITION_DIALOG            gdu_edit_partition_dialog_get_type()
+#define GDU_EDIT_PARTITION_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDU_TYPE_EDIT_PARTITION_DIALOG, GduEditPartitionDialog))
+#define GDU_EDIT_PARTITION_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GDU_TYPE_EDIT_PARTITION_DIALOG, GduEditPartitionDialogClass))
+#define GDU_IS_EDIT_PARTITION_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDU_TYPE_EDIT_PARTITION_DIALOG))
+#define GDU_IS_EDIT_PARTITION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDU_TYPE_EDIT_PARTITION_DIALOG))
+#define GDU_EDIT_PARTITION_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GDU_TYPE_EDIT_PARTITION_DIALOG, GduEditPartitionDialogClass))
+
+typedef struct GduEditPartitionDialogClass   GduEditPartitionDialogClass;
+typedef struct GduEditPartitionDialogPrivate GduEditPartitionDialogPrivate;
+
+struct GduEditPartitionDialog
+{
+        GduDialog parent;
+
+        /*< private >*/
+        GduEditPartitionDialogPrivate *priv;
+};
+
+struct GduEditPartitionDialogClass
+{
+        GduDialogClass parent_class;
+};
+
+GType         gdu_edit_partition_dialog_get_type            (void) G_GNUC_CONST;
+GtkWidget    *gdu_edit_partition_dialog_new                 (GtkWindow      *parent,
+                                                             GduPresentable *volume);
+gchar        *gdu_edit_partition_dialog_get_partition_type  (GduEditPartitionDialog *dialog);
+gchar        *gdu_edit_partition_dialog_get_partition_label (GduEditPartitionDialog *dialog);
+gchar       **gdu_edit_partition_dialog_get_partition_flags (GduEditPartitionDialog *dialog);
+
+G_END_DECLS
+
+#endif /* __GDU_EDIT_PARTITION_DIALOG_H */
diff --git a/src/gdu-gtk/gdu-gtk-types.h b/src/gdu-gtk/gdu-gtk-types.h
index d7d7109..134d432 100644
--- a/src/gdu-gtk/gdu-gtk-types.h
+++ b/src/gdu-gtk/gdu-gtk-types.h
@@ -51,6 +51,7 @@ typedef struct GduErrorDialog              GduErrorDialog;
 typedef struct GduButtonElement            GduButtonElement;
 typedef struct GduButtonTable              GduButtonTable;
 typedef struct GduDialog                   GduDialog;
+typedef struct GduEditPartitionDialog      GduEditPartitionDialog;
 
 
 G_END_DECLS
diff --git a/src/gdu-gtk/gdu-gtk.h b/src/gdu-gtk/gdu-gtk.h
index ca38654..d670170 100644
--- a/src/gdu-gtk/gdu-gtk.h
+++ b/src/gdu-gtk/gdu-gtk.h
@@ -43,6 +43,7 @@
 #include <gdu-gtk/gdu-button-element.h>
 #include <gdu-gtk/gdu-button-table.h>
 #include <gdu-gtk/gdu-dialog.h>
+#include <gdu-gtk/gdu-edit-partition-dialog.h>
 #undef __GDU_GTK_INSIDE_GDU_GTK_H
 
 G_BEGIN_DECLS
diff --git a/src/palimpsest/gdu-section-volumes.c b/src/palimpsest/gdu-section-volumes.c
index 0be6473..d00fee5 100644
--- a/src/palimpsest/gdu-section-volumes.c
+++ b/src/palimpsest/gdu-section-volumes.c
@@ -187,6 +187,86 @@ on_mount_button_clicked (GduButtonElement *button_element,
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
+partition_modify_op_callback (GduDevice *device,
+                              GError    *error,
+                              gpointer   user_data)
+{
+        GduShell *shell = GDU_SHELL (user_data);
+
+        if (error != NULL) {
+                GtkWidget *dialog;
+                dialog = gdu_error_dialog_for_volume (GTK_WINDOW (gdu_shell_get_toplevel (shell)),
+                                                      device,
+                                                      _("Error modifying 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);
+        }
+        g_object_unref (shell);
+}
+
+static void
+on_partition_edit_button_clicked (GduButtonElement *button_element,
+                                  gpointer          user_data)
+{
+        GduSectionVolumes *section = GDU_SECTION_VOLUMES (user_data);
+        GduPresentable *v;
+        GduDevice *d;
+        GtkWindow *toplevel;
+        GtkWidget *dialog;
+        gint response;
+
+        v = NULL;
+
+        v = gdu_volume_grid_get_selected (GDU_VOLUME_GRID (section->priv->grid));
+        if (v == NULL)
+                goto out;
+
+        d = gdu_presentable_get_device (v);
+        if (d == NULL)
+                goto out;
+
+        toplevel = GTK_WINDOW (gdu_shell_get_toplevel (gdu_section_get_shell (GDU_SECTION (section))));
+        dialog = gdu_edit_partition_dialog_new (toplevel, v);
+        gtk_widget_show_all (dialog);
+        response = gtk_dialog_run (GTK_DIALOG (dialog));
+        if (response == GTK_RESPONSE_APPLY) {
+                gchar *partition_type;
+                gchar *partition_label;
+                gchar **partition_flags;
+
+                g_object_get (dialog,
+                              "partition-type", &partition_type,
+                              "partition-label", &partition_label,
+                              "partition-flags", &partition_flags,
+                              NULL);
+
+                gdu_device_op_partition_modify (d,
+                                                partition_type,
+                                                partition_label,
+                                                partition_flags,
+                                                partition_modify_op_callback,
+                                                g_object_ref (gdu_section_get_shell (GDU_SECTION (section))));
+
+                g_free (partition_type);
+                g_free (partition_label);
+                g_strfreev (partition_flags);
+        }
+        gtk_widget_destroy (dialog);
+
+ out:
+        if (d != NULL)
+                g_object_unref (d);
+        if (v != NULL)
+                g_object_unref (v);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
 gdu_section_volumes_update (GduSection *_section)
 {
         GduSectionVolumes *section = GDU_SECTION_VOLUMES (_section);
@@ -340,8 +420,20 @@ gdu_section_volumes_update (GduSection *_section)
                         g_free (s);
                         g_string_free (str, TRUE);
 
-                        show_partition_edit_button = TRUE;
                         show_partition_delete_button = TRUE;
+
+                        /* Don't show partition edit button for extended partitions */
+                        show_partition_edit_button = TRUE;
+                        if (g_strcmp0 (gdu_device_partition_get_scheme (d), "mbr") == 0) {
+                                gint partition_type;
+                                const gchar *partition_type_str;
+
+                                partition_type_str = gdu_device_partition_get_type (d);
+                                partition_type = strtol (partition_type_str, NULL, 0);
+                                if ((partition_type == 0x05 || partition_type == 0x0f || partition_type == 0x85)) {
+                                        show_partition_edit_button = FALSE;
+                                }
+                        }
                 } else {
                         gdu_details_element_set_text (section->priv->partition_element, "â??");
                 }
@@ -563,12 +655,10 @@ gdu_section_volumes_constructed (GObject *object)
         button_element = gdu_button_element_new (GTK_STOCK_EDIT,
                                                  _("Ed_it Partition"),
                                                  _("Change partition type and flags"));
-#if 0
         g_signal_connect (button_element,
                           "clicked",
                           G_CALLBACK (on_partition_edit_button_clicked),
                           section);
-#endif
         g_ptr_array_add (button_elements, button_element);
         section->priv->partition_edit_button = button_element;
 



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