summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@redhat.com>2009-03-03 16:17:33 +0100
committerTomas Bzatek <tbzatek@redhat.com>2009-03-03 16:17:33 +0100
commit8e6bf7cf7d13c8734a5c469b2a3f96b974b34127 (patch)
tree35b2324798e139b01d3655d0e3be55144d2f324b
parent6feeb5f362ae79bc75f5f304db118eab36fdf155 (diff)
downloadnautilus-gdu-8e6bf7cf7d13c8734a5c469b2a3f96b974b34127.tar.gz
nautilus-gdu-8e6bf7cf7d13c8734a5c469b2a3f96b974b34127.tar.xz
nautilus-gdu-8e6bf7cf7d13c8734a5c469b2a3f96b974b34127.zip
Handle partition creation
- works on zeroed devices - works when partition table exists but no partition is selected - detects optical media and floppy disks and skips partition creation - volume chooser in standalone mode now lists only parent devices from toplevel removable ones
-rw-r--r--TODO7
-rw-r--r--src/format-window-operation.c470
-rw-r--r--src/format-window-operation.h20
-rw-r--r--src/format-window.c52
-rw-r--r--src/format-window.h15
-rw-r--r--src/gdu-utils.c128
6 files changed, 535 insertions, 157 deletions
diff --git a/TODO b/TODO
index d3a3c0a..233f2db 100644
--- a/TODO
+++ b/TODO
@@ -27,7 +27,7 @@ DONE, NEEDS_TESTING - monitor device/presentable events like eject, umount etc.
- show custom icon if user has set it in Nautilus
- is firmware needed for some devices?
- different partition tables?
-- what to do if device is blank (zeroed, no MBR)?
+DONE - what to do if device is blank (zeroed, no MBR)?
DONE - handle read only device - gdu_device_is_read_only() - test with DVD-RAM media
- stay consistent with volume labels in Nautilus and gdu (requires gvfs-devicekit port)
- localization (transifex? -- ask hughsie)
@@ -50,4 +50,7 @@ Bugs:
- libgdu should return always valid presentable names
NO - should the presentable instance from the pool::presentable-{added,changed,removed} signals be unreffed?
- complete CD-RW medium is not marked as readonly -- are we gonna have burning backend in DK-disks?
-
+ - would be great to have gdu_pool_get_toplevel_presentables()
+ - gdu_presentable_get_toplevel() always returns valid presentable even if it's already toplevel (i.e. /dev/md0), never returns NULL
+ - gdu_device_drive_get_media_compatibility() returns const char* pointers - check and document properly
+ - BUG !! gdu_device_op_partition_create() and gdu_device_op_partition_table_create() should spawn their finish callbacks only after device is ready (and pool up-to-date) so we can start another operation right away
diff --git a/src/format-window-operation.c b/src/format-window-operation.c
index d27af1a..eec5c45 100644
--- a/src/format-window-operation.c
+++ b/src/format-window-operation.c
@@ -35,6 +35,9 @@
#include "format-window-operation.h"
+
+#define DEVICE_SETTLE_TIMEOUT 3000
+
/* ---------------------------------------------------------------------------------------------------- */
/* TODO: this is quite dangerous, but needed */
@@ -63,6 +66,30 @@ mbr_part_is_linux_type (const char *part_type)
strcasecmp (part_type, "0xfd") == 0);
}
+
+/* Look whether the device needs to be partitioned */
+/* - generally we don't want to have partitions on optical drives and floppy disks */
+static gboolean
+device_needs_partition_table (GduDevice *device)
+{
+ char **media_compat;
+ gboolean needs = TRUE; /* default to TRUE */
+
+ media_compat = gdu_device_drive_get_media_compatibility (device);
+ for (; *media_compat; media_compat++) {
+ g_print (" compat '%s'\n", *media_compat);
+ /* http://hal.freedesktop.org/docs/DeviceKit-disks/Device.html#Device:drive-media-compatibility */
+ if (strstr (*media_compat, "optical") == *media_compat ||
+ strstr (*media_compat, "floppy") == *media_compat) {
+ needs = FALSE;
+ break;
+ }
+ }
+// g_strfreev (media_compat); /* so, is this const then? */
+ g_print ("device_needs_partition_table = %d\n", needs);
+ return needs;
+}
+
/* ---------------------------------------------------------------------------------------------------- */
static gboolean
@@ -72,11 +99,46 @@ job_progress_pulse_timeout_handler (gpointer user_data)
g_return_val_if_fail (data != NULL, TRUE);
+ g_print ("job_progress_pulse_timeout_handler\n");
+
gtk_progress_bar_pulse (GTK_PROGRESS_BAR (data->priv->progress_bar));
return TRUE;
}
static void
+do_progress_bar_update (FormatProcessData *data, const char *label, double percentage, gboolean active)
+{
+ if (active) {
+ gtk_progress_bar_set_text (GTK_PROGRESS_BAR (data->priv->progress_bar), label);
+
+ if (percentage < 0) {
+ gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (data->priv->progress_bar), 2.0 / 50);
+ gtk_progress_bar_pulse (GTK_PROGRESS_BAR (data->priv->progress_bar));
+ if (data->job_progress_pulse_timer_id == 0) {
+ g_print ("activating progress bounce...\n");
+ data->job_progress_pulse_timer_id = g_timeout_add (
+ 1000 / 50,
+ job_progress_pulse_timeout_handler,
+ data);
+ }
+ } else {
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (data->priv->progress_bar),
+ percentage / 100.0);
+ if (data->job_progress_pulse_timer_id > 0) {
+ g_source_remove (data->job_progress_pulse_timer_id);
+ data->job_progress_pulse_timer_id = 0;
+ }
+ }
+ }
+ else {
+ if (data->job_progress_pulse_timer_id > 0) {
+ g_source_remove (data->job_progress_pulse_timer_id);
+ data->job_progress_pulse_timer_id = 0;
+ }
+ }
+}
+
+static void
presentable_job_changed (GduPresentable *presentable, gpointer user_data)
{
FormatProcessData *data = user_data;
@@ -85,6 +147,8 @@ presentable_job_changed (GduPresentable *presentable, gpointer user_data)
char *task_description;
double percentage;
+ g_print ("presentable_job_changed\n");
+
g_return_if_fail (data != NULL);
if (data->device != NULL && gdu_device_job_in_progress (data->device)) {
@@ -95,36 +159,16 @@ presentable_job_changed (GduPresentable *presentable, gpointer user_data)
(task_description && strlen (task_description) > 0) ? task_description : job_description,
gdu_device_job_get_cur_task (data->device) + 1,
gdu_device_job_get_num_tasks (data->device));
- gtk_progress_bar_set_text (GTK_PROGRESS_BAR (data->priv->progress_bar), s);
- g_free (s);
percentage = gdu_device_job_get_cur_task_percentage (data->device);
- if (percentage < 0) {
- gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (data->priv->progress_bar), 2.0 / 50);
- gtk_progress_bar_pulse (GTK_PROGRESS_BAR (data->priv->progress_bar));
- if (data->job_progress_pulse_timer_id == 0) {
- data->job_progress_pulse_timer_id = g_timeout_add (
- 1000 / 50,
- job_progress_pulse_timeout_handler,
- data);
- }
- } else {
- gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (data->priv->progress_bar),
- percentage / 100.0);
- if (data->job_progress_pulse_timer_id > 0) {
- g_source_remove (data->job_progress_pulse_timer_id);
- data->job_progress_pulse_timer_id = 0;
- }
- }
+ do_progress_bar_update (data, s, percentage, TRUE);
+ g_free (s);
g_free (job_description);
g_free (task_description);
} else {
- if (data->job_progress_pulse_timer_id > 0) {
- g_source_remove (data->job_progress_pulse_timer_id);
- data->job_progress_pulse_timer_id = 0;
- }
+ do_progress_bar_update (data, NULL, -1, FALSE);
}
}
@@ -137,6 +181,10 @@ static void format_auth_end_callback (PolKitGnomeAction *action, gboolean gained
static void format_action_callback (GtkAction *action, gpointer user_data);
static void part_modify_auth_end_callback (PolKitGnomeAction *action, gboolean gained_privilege, gpointer user_data);
static void part_modify_action_callback (GtkAction *action, gpointer user_data);
+static void part_table_new_auth_end_callback (PolKitGnomeAction *action, gboolean gained_privilege, gpointer user_data);
+static void part_table_new_action_callback (GtkAction *action, gpointer user_data);
+static void part_new_auth_end_callback (PolKitGnomeAction *action, gboolean gained_privilege, gpointer user_data);
+static void part_new_action_callback (GtkAction *action, gpointer user_data);
void
update_ui_progress (FormatDialogPrivate *priv,
@@ -155,32 +203,63 @@ update_ui_progress (FormatDialogPrivate *priv,
gtk_button_set_label (GTK_BUTTON (priv->close_button), GTK_STOCK_STOP);
gtk_widget_show_all (priv->progress_bar_box);
if (data) {
- data->job_handler_id = g_signal_connect (priv->presentable, "job-changed", G_CALLBACK (presentable_job_changed), data);
- data->pk_unmount_auth_end_handler_id = g_signal_connect (priv->unmount_action, "auth-end", G_CALLBACK (unmount_auth_end_callback), data);
- data->pk_unmount_action_handler_id = g_signal_connect (priv->unmount_action, "activate", G_CALLBACK (unmount_action_callback), data);
- data->pk_format_auth_end_handler_id = g_signal_connect (priv->format_action, "auth-end", G_CALLBACK (format_auth_end_callback), data);
- data->pk_format_action_handler_id = g_signal_connect (priv->format_action, "activate", G_CALLBACK (format_action_callback), data);
- data->pk_part_modify_auth_end_handler_id = g_signal_connect (priv->part_modify_action, "auth-end", G_CALLBACK (part_modify_auth_end_callback), data);
- data->pk_part_modify_action_handler_id = g_signal_connect (priv->part_modify_action, "activate", G_CALLBACK (part_modify_action_callback), data);
+ g_signal_connect (data->presentable, "job-changed", G_CALLBACK (presentable_job_changed), data);
+
+ /* set up PolicyKit actions */
+ data->pk_unmount_action = polkit_action_new ();
+ polkit_action_set_action_id (data->pk_unmount_action, "org.freedesktop.devicekit.disks.filesystem-unmount-others");
+ data->unmount_action = polkit_gnome_action_new_default ("unmount", data->pk_unmount_action, NULL, NULL);
+ g_signal_connect (data->unmount_action, "auth-end", G_CALLBACK (unmount_auth_end_callback), data);
+ g_signal_connect (data->unmount_action, "activate", G_CALLBACK (unmount_action_callback), data);
+
+ data->pk_format_action = polkit_action_new ();
+ polkit_action_set_action_id (data->pk_format_action, "org.freedesktop.devicekit.disks.change");
+ data->format_action = polkit_gnome_action_new_default ("format", data->pk_format_action, NULL, NULL);
+ g_signal_connect (data->format_action, "auth-end", G_CALLBACK (format_auth_end_callback), data);
+ g_signal_connect (data->format_action, "activate", G_CALLBACK (format_action_callback), data);
+
+ data->pk_part_modify_action = polkit_action_new ();
+ /* action_id is the same as for format, but sometimes authentication is one shot */
+ polkit_action_set_action_id (data->pk_part_modify_action, "org.freedesktop.devicekit.disks.change");
+ data->part_modify_action = polkit_gnome_action_new_default ("part_modify", data->pk_part_modify_action, NULL, NULL);
+ g_signal_connect (data->part_modify_action, "auth-end", G_CALLBACK (part_modify_auth_end_callback), data);
+ g_signal_connect (data->part_modify_action, "activate", G_CALLBACK (part_modify_action_callback), data);
+
+ data->pk_part_table_new_action = polkit_action_new ();
+ polkit_action_set_action_id (data->pk_part_table_new_action, "org.freedesktop.devicekit.disks.change");
+ data->part_table_new_action = polkit_gnome_action_new_default ("part_table_new", data->pk_part_table_new_action, NULL, NULL);
+ g_signal_connect (data->part_table_new_action, "auth-end", G_CALLBACK (part_table_new_auth_end_callback), data);
+ g_signal_connect (data->part_table_new_action, "activate", G_CALLBACK (part_table_new_action_callback), data);
+
+ data->pk_part_new_action = polkit_action_new ();
+ polkit_action_set_action_id (data->pk_part_new_action, "org.freedesktop.devicekit.disks.change");
+ data->part_new_action = polkit_gnome_action_new_default ("part_new", data->pk_part_new_action, NULL, NULL);
+ g_signal_connect (data->part_new_action, "auth-end", G_CALLBACK (part_new_auth_end_callback), data);
+ g_signal_connect (data->part_new_action, "activate", G_CALLBACK (part_new_action_callback), data);
}
}
else
{
if (data) {
- if (data->job_handler_id)
- g_signal_handler_disconnect (priv->presentable, data->job_handler_id);
- if (data->pk_unmount_auth_end_handler_id)
- g_signal_handler_disconnect (priv->unmount_action, data->pk_unmount_auth_end_handler_id);
- if (data->pk_unmount_action_handler_id)
- g_signal_handler_disconnect (priv->unmount_action, data->pk_unmount_action_handler_id);
- if (data->pk_format_auth_end_handler_id)
- g_signal_handler_disconnect (priv->format_action, data->pk_format_auth_end_handler_id);
- if (data->pk_format_action_handler_id)
- g_signal_handler_disconnect (priv->format_action, data->pk_format_action_handler_id);
- if (data->pk_part_modify_auth_end_handler_id)
- g_signal_handler_disconnect (priv->part_modify_action, data->pk_part_modify_auth_end_handler_id);
- if (data->pk_part_modify_action_handler_id)
- g_signal_handler_disconnect (priv->part_modify_action, data->pk_part_modify_action_handler_id);
+ g_signal_handlers_disconnect_matched (data->unmount_action, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, data);
+ g_signal_handlers_disconnect_matched (data->format_action, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, data);
+ g_signal_handlers_disconnect_matched (data->part_modify_action, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, data);
+ g_signal_handlers_disconnect_matched (data->part_table_new_action, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, data);
+ g_signal_handlers_disconnect_matched (data->part_new_action, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, data);
+
+ /* destroy PolicyKit actions */
+ polkit_action_unref (data->pk_unmount_action);
+ g_object_unref (data->unmount_action);
+ polkit_action_unref (data->pk_format_action);
+ g_object_unref (data->format_action);
+ polkit_action_unref (data->pk_part_modify_action);
+ g_object_unref (data->part_modify_action);
+ polkit_action_unref (data->pk_part_table_new_action);
+ g_object_unref (data->part_table_new_action);
+ polkit_action_unref (data->pk_part_new_action);
+ g_object_unref (data->part_new_action);
+
+ g_signal_handlers_disconnect_matched (data->presentable, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, data);
if (data->job_progress_pulse_timer_id > 0) {
g_source_remove (data->job_progress_pulse_timer_id);
data->job_progress_pulse_timer_id = 0;
@@ -197,6 +276,8 @@ free_format_action_data (FormatProcessData *data)
{
if (data) {
update_ui_progress (data->priv, data, FALSE);
+ if (data->presentable != NULL)
+ g_object_unref (data->presentable);
if (data->device != NULL)
g_object_unref (data->device);
if (data->encrypt_passphrase != NULL)
@@ -212,6 +293,51 @@ free_format_action_data (FormatProcessData *data)
}
/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+action_finished (FormatProcessData *data, char *new_device_path)
+{
+ g_return_if_fail (data != NULL);
+ GduDevice *new_device;
+ GduPresentable *new_presentable = NULL;
+
+ /* we don't want to destroy objects at this point, don't pass data */
+ update_ui_progress (data->priv, NULL, FALSE);
+
+ /* change to the new device */
+ if (new_device_path) {
+ new_device = gdu_pool_get_by_object_path (data->priv->pool, new_device_path);
+ if (new_device) {
+ g_object_unref (data->device);
+ data->device = new_device;
+ new_presentable = gdu_pool_get_volume_by_device (data->priv->pool, new_device);
+ if (new_presentable) {
+ /* switch to new presentable */
+ g_print ("setting new presentable...\n");
+ }
+ } else {
+ g_warning ("action_finished: cannot find device for the %s device path\n", new_device_path);
+ }
+ g_free (new_device_path);
+ }
+
+ /* Force refresh of the new presentable */
+ select_new_presentable (data->priv, new_presentable != NULL ? new_presentable : data->priv->presentable);
+ if (new_presentable)
+ g_object_unref (new_presentable);
+
+ /* TODO: show encryption info somewhere? */
+ if (data->encrypt_passphrase != NULL) {
+ /* now set the passphrase if requested */
+ if (data->save_in_keyring || data->save_in_keyring_session) {
+ gdu_util_save_secret (data->device,
+ data->encrypt_passphrase,
+ data->save_in_keyring_session);
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
static void
nautilus_gdu_show_error (GtkWidget *parent_window,
GduPresentable *presentable,
@@ -274,7 +400,7 @@ modify_partition_completed (GduDevice *device,
if (error != NULL) {
nautilus_gdu_show_error (GTK_WIDGET (data->priv->dialog),
- data->priv->presentable,
+ data->presentable,
error,
_("Error modifying partition"));
g_error_free (error);
@@ -284,6 +410,8 @@ modify_partition_completed (GduDevice *device,
/* -- don't refresh here, wait for the "changed" callback
update_ui (data->priv); */
}
+ /* save encryption info even if operation fails */
+ action_finished (data, NULL);
free_format_action_data (data);
}
@@ -299,13 +427,13 @@ part_modify_action_callback (GtkAction *action, gpointer user_data)
return;
/* DK is buggy, passing a label string causes the operation to fail */
- gdu_device_op_partition_modify (data->device, data->recommended_part_type, NULL /* data->fslabel */, NULL, modify_partition_completed, data);
+ gdu_device_op_partition_modify (data->device, data->recommended_part_type, NULL, NULL, modify_partition_completed, data);
}
static void
part_modify_auth_end_callback (PolKitGnomeAction *action,
- gboolean gained_privilege,
- gpointer user_data)
+ gboolean gained_privilege,
+ gpointer user_data)
{
FormatProcessData *data = user_data;
@@ -337,24 +465,13 @@ format_action_completed (GduDevice *device,
if (error != NULL) {
nautilus_gdu_show_error (GTK_WIDGET (data->priv->dialog),
- data->priv->presentable,
+ data->presentable,
error,
_("Error creating partition"));
g_error_free (error);
}
else
{
- /* formatting finished */
- /* TODO: show encryption info somewhere? */
- if (data->encrypt_passphrase != NULL) {
- /* now set the passphrase if requested */
- if (data->save_in_keyring || data->save_in_keyring_session) {
- gdu_util_save_secret (device,
- data->encrypt_passphrase,
- data->save_in_keyring_session);
- }
- }
-
scheme = gdu_device_partition_get_scheme (device);
// g_print ("format_action_completed: scheme = %s\n", scheme);
/* TODO: extend to other partition types once this feature is working in DK */
@@ -367,13 +484,13 @@ format_action_completed (GduDevice *device,
! (mbr_part_is_linux_type (part_type) && mbr_part_is_linux_type (data->recommended_part_type)))
{
g_print ("changing part type to %s, device = %s\n", data->recommended_part_type, gdu_device_get_device_file (device));
- gtk_action_activate (GTK_ACTION (data->priv->part_modify_action));
+ gtk_action_activate (GTK_ACTION (data->part_modify_action));
return; /* don't change the UI yet */
}
}
- /* -- don't refresh here, wait for the "changed" callback
- update_ui (data->priv); */
+ /* formatting finished */
+ action_finished (data, NULL);
}
free_format_action_data (data);
}
@@ -426,10 +543,10 @@ unmount_show_busy (gpointer user_data)
{
FormatProcessData *data = user_data;
- if (gdu_util_dialog_show_filesystem_busy (GTK_WIDGET (data->priv->dialog), data->priv->presentable)) {
+ if (gdu_util_dialog_show_filesystem_busy (GTK_WIDGET (data->priv->dialog), data->presentable)) {
/* user managed to kill all applications; try again */
if (! data->priv->job_cancelled) {
- gtk_action_activate (GTK_ACTION (data->priv->unmount_action));
+ gtk_action_activate (GTK_ACTION (data->unmount_action));
}
}
else {
@@ -460,7 +577,7 @@ unmount_action_completed (GduDevice *device,
else
{
nautilus_gdu_show_error (GTK_WIDGET (data->priv->dialog),
- data->priv->presentable,
+ data->presentable,
error,
_("Error unmounting device"));
free_format_action_data (data);
@@ -473,7 +590,7 @@ unmount_action_completed (GduDevice *device,
g_print (" formatting...\n");
if (data->priv->job_cancelled)
return;
- gtk_action_activate (GTK_ACTION (data->priv->format_action));
+ gtk_action_activate (GTK_ACTION (data->format_action));
}
}
@@ -510,6 +627,171 @@ unmount_auth_end_callback (PolKitGnomeAction *action,
}
}
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+part_table_new_timeout_handler (gpointer user_data)
+{
+ FormatProcessData *data = user_data;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+ g_print ("part_table_new_timeout_handler\n");
+
+ gtk_action_activate (GTK_ACTION (data->part_new_action));
+
+ return FALSE;
+}
+
+static void
+part_table_new_completed (GduDevice *device,
+ GError *error,
+ gpointer user_data)
+{
+ FormatProcessData *data = user_data;
+
+ /* BUG: callback shouldn't be spawned until all changes are reflected in pool */
+ g_return_if_fail (data != NULL);
+
+ g_print ("part_table_new_completed\n");
+ update_ui_controls (data->priv);
+
+ if (error != NULL) {
+ nautilus_gdu_show_error (GTK_WIDGET (data->priv->dialog),
+ data->presentable,
+ error,
+ _("Error creating new partition table"));
+ free_format_action_data (data);
+ g_error_free (error);
+ }
+ else
+ {
+ g_print (" creating partition...\n");
+ if (data->priv->job_cancelled)
+ return;
+ /* TODO: we should wait here for proper refresh */
+ g_timeout_add (DEVICE_SETTLE_TIMEOUT, part_table_new_timeout_handler, data);
+ do_progress_bar_update (data, _("Waiting for device to settle..."), -1, TRUE);
+// gtk_action_activate (GTK_ACTION (data->part_new_action));
+ }
+}
+
+static void
+part_table_new_action_callback (GtkAction *action, gpointer user_data)
+{
+ FormatProcessData *data = user_data;
+
+ g_return_if_fail (data != NULL);
+ g_print ("part_table_new_action_callback\n");
+
+ if (data->priv->job_cancelled)
+ return;
+
+ /* default to MBR */
+ data->scheme = "mbr";
+
+ gdu_device_op_partition_table_create (data->device, data->scheme, data->secure_erase, part_table_new_completed, data);
+}
+
+static void
+part_table_new_auth_end_callback (PolKitGnomeAction *action,
+ gboolean gained_privilege,
+ gpointer user_data)
+{
+ FormatProcessData *data = user_data;
+
+ g_return_if_fail (data != NULL);
+ g_print ("part_table_new_auth_end_callback\n");
+
+ if (! gained_privilege) {
+ /* cancel the whole operation */
+ free_format_action_data (data);
+ }
+ else {
+ /* positive reply should be handled by unmount_action_callback */
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+part_new_completed (GduDevice *device,
+ char *created_device_object_path,
+ GError *error,
+ gpointer user_data)
+{
+ FormatProcessData *data = user_data;
+
+ /* BUG: callback shouldn't be spawned until all changes are reflected in pool */
+ g_return_if_fail (data != NULL);
+
+ g_print ("part_new_completed, created_device_object_path = %s\n", error == NULL ? created_device_object_path : NULL);
+
+ if (error != NULL) {
+ nautilus_gdu_show_error (GTK_WIDGET (data->priv->dialog),
+ data->presentable,
+ error,
+ _("Error creating new partition"));
+ g_error_free (error);
+ }
+ else
+ {
+ /* formatting finished */
+ /* TODO: we should wait here for proper refresh */
+ action_finished (data, g_strdup (created_device_object_path));
+ }
+ free_format_action_data (data);
+}
+
+static void
+part_new_action_callback (GtkAction *action, gpointer user_data)
+{
+ FormatProcessData *data = user_data;
+ guint64 offset;
+ guint64 size;
+ char *type;
+
+ g_return_if_fail (data != NULL);
+ g_print ("part_new_action_callback, device = %s\n", gdu_device_get_device_file (data->device));
+
+ if (data->priv->job_cancelled)
+ return;
+
+ offset = gdu_presentable_get_offset (data->presentable);
+ size = gdu_presentable_get_size (data->presentable);
+
+ if (! data->scheme || strlen (data->scheme) == 0)
+ data->scheme = gdu_device_partition_table_get_scheme (data->device); /* we should have toplevel device here */
+ if (! data->scheme || strlen (data->scheme) == 0)
+ data->scheme = "mbr"; /* default to MBR */
+
+ type = gdu_util_get_default_part_type_for_scheme_and_fstype (data->scheme, data->fstype, size);
+
+ g_print ("creating new partition, offset = %lu, size = %lu, scheme = %s, type = %s\n", offset, size, data->scheme, type);
+
+ gdu_device_op_partition_create (data->device, offset, size, type, NULL, NULL,
+ data->fstype, data->fslabel, data->secure_erase, data->encrypt_passphrase, data->take_ownership,
+ part_new_completed, data);
+ g_free (type);
+}
+
+static void
+part_new_auth_end_callback (PolKitGnomeAction *action,
+ gboolean gained_privilege,
+ gpointer user_data)
+{
+ FormatProcessData *data = user_data;
+
+ g_return_if_fail (data != NULL);
+ g_print ("part_new_auth_end_callback\n");
+
+ if (! gained_privilege) {
+ /* cancel the whole operation */
+ free_format_action_data (data);
+ }
+ else {
+ /* positive reply should be handled by unmount_action_callback */
+ }
+}
/* ---------------------------------------------------------------------------------------------------- */
@@ -523,26 +805,24 @@ do_format (FormatDialogPrivate *priv)
char *primary;
char *secondary;
char *drive_name;
+ gboolean create_new_part_table = FALSE;
+ gboolean create_new_partition = FALSE;
GduKnownFilesystem *kfs;
priv->job_cancelled = FALSE;
data = g_new0 (FormatProcessData, 1);
data->priv = priv;
+ data->job_progress_pulse_timer_id = 0;
primary = NULL;
secondary = NULL;
toplevel_presentable = NULL;
toplevel_device = NULL;
drive_name = NULL;
- data->device = gdu_presentable_get_device (priv->presentable);
- if (data->device == NULL) {
- g_warning ("%s: device is not supposed to be NULL", __FUNCTION__);
- free_format_action_data (data);
- goto out;
- }
- toplevel_presentable = gdu_presentable_get_toplevel (priv->presentable);
+ data->presentable = g_object_ref (priv->presentable);
+ toplevel_presentable = gdu_presentable_get_toplevel (data->presentable);
if (toplevel_presentable == NULL) {
g_warning ("%s: no toplevel presentable", __FUNCTION__);
}
@@ -552,6 +832,33 @@ do_format (FormatDialogPrivate *priv)
free_format_action_data (data);
goto out;
}
+ data->device = gdu_presentable_get_device (data->presentable);
+
+ if (data->device == NULL && toplevel_device != NULL) {
+ /* no device, i.e. partition table exists but no partition */
+ data->device = g_object_ref (toplevel_device);
+ create_new_part_table = FALSE;
+ create_new_partition = TRUE;
+ g_print ("Partition table exists but has no partition for the selected device.\n");
+ } else
+ if (toplevel_device != NULL && ! gdu_device_is_partition_table (toplevel_device)) {
+ /* no partition table on the device, create partition table first. */
+ /* also empty (zeroed) device */
+ create_new_part_table = TRUE;
+ create_new_partition = TRUE;
+ g_print ("Device is known but doesn't have partition table, we need to create it first.\n");
+ } else
+ if (toplevel_device != NULL && data->device != NULL && toplevel_device == data->device && device_needs_partition_table (data->device)) {
+ /* device is toplevel, check if we need new partitions */
+ create_new_partition = TRUE;
+ g_print ("Device is known but requires partitioning, we'll create new one.\n");
+ }
+
+ if (data->device == NULL) {
+ g_warning ("%s: device is not supposed to be NULL", __FUNCTION__);
+ free_format_action_data (data);
+ goto out;
+ }
drive_name = gdu_presentable_get_name (toplevel_presentable);
data->fstype = gdu_util_fstype_combo_box_get_selected (priv->part_type_combo_box);
@@ -628,11 +935,20 @@ do_format (FormatDialogPrivate *priv)
}
}
- /* unmount the device before formatting */
+
+ if (create_new_part_table && device_needs_partition_table (data->device)) {
+ /* device is zeroed, create partition table first */
+ gtk_action_activate (GTK_ACTION (data->part_table_new_action));
+ } else
+ if (create_new_partition && device_needs_partition_table (data->device)) {
+ /* device has partition table but has no partition */
+ gtk_action_activate (GTK_ACTION (data->part_new_action));
+ } else
if (gdu_device_is_mounted (data->device)) {
- gtk_action_activate (GTK_ACTION (priv->unmount_action));
+ /* unmount the device before formatting */
+ gtk_action_activate (GTK_ACTION (data->unmount_action));
} else {
- gtk_action_activate (GTK_ACTION (priv->format_action));
+ gtk_action_activate (GTK_ACTION (data->format_action));
}
out:
diff --git a/src/format-window-operation.h b/src/format-window-operation.h
index d5b1dac..f05b806 100644
--- a/src/format-window-operation.h
+++ b/src/format-window-operation.h
@@ -39,18 +39,24 @@ typedef struct {
char *fslabel;
char *fstype;
GduDevice *device;
+ GduPresentable *presentable;
gboolean take_ownership;
char *secure_erase;
const char *recommended_part_type;
+ const char *scheme;
guint job_progress_pulse_timer_id;
- gulong job_handler_id;
- gulong pk_unmount_action_handler_id;
- gulong pk_unmount_auth_end_handler_id;
- gulong pk_format_action_handler_id;
- gulong pk_format_auth_end_handler_id;
- gulong pk_part_modify_action_handler_id;
- gulong pk_part_modify_auth_end_handler_id;
+
+ PolKitAction *pk_unmount_action;
+ PolKitGnomeAction *unmount_action;
+ PolKitAction *pk_format_action;
+ PolKitGnomeAction *format_action;
+ PolKitAction *pk_part_modify_action;
+ PolKitGnomeAction *part_modify_action;
+ PolKitAction *pk_part_table_new_action;
+ PolKitGnomeAction *part_table_new_action;
+ PolKitAction *pk_part_new_action;
+ PolKitGnomeAction *part_new_action;
} FormatProcessData;
diff --git a/src/format-window.c b/src/format-window.c
index 48ba203..17fc595 100644
--- a/src/format-window.c
+++ b/src/format-window.c
@@ -36,6 +36,8 @@
+/* ---------------------------------------------------------------------------------------------------- */
+static void set_new_presentable (FormatDialogPrivate *priv, GduPresentable *presentable);
/* ---------------------------------------------------------------------------------------------------- */
@@ -133,9 +135,10 @@ update_ui_controls (FormatDialogPrivate *priv)
gtk_widget_show_all (priv->no_media_warning);
/* controls sensitivity */
- sensitive = priv->presentable != NULL && GDU_IS_PRESENTABLE (priv->presentable) &&
- device != NULL && (! priv->job_running) &&
- (! gdu_device_is_read_only (device)) && (gdu_device_is_media_available (device));
+ sensitive = priv->presentable != NULL && GDU_IS_PRESENTABLE (priv->presentable) && (! priv->job_running);
+ if (device)
+ sensitive = sensitive && ! gdu_device_is_read_only (device) && gdu_device_is_media_available (device);
+
gtk_widget_set_sensitive (priv->controls_box, sensitive);
gtk_widget_set_sensitive (priv->partition_label, sensitive);
if (priv->volume_selector)
@@ -495,7 +498,6 @@ update_ui (FormatDialogPrivate *priv)
/* ---------------------------------------------------------------------------------------------------- */
-static void set_new_presentable (FormatDialogPrivate *priv, GduPresentable *presentable);
static void
nautilus_gdu_destroy (FormatDialogPrivate *priv)
@@ -510,14 +512,6 @@ nautilus_gdu_destroy (FormatDialogPrivate *priv)
set_new_presentable (priv, NULL);
g_signal_handlers_disconnect_matched (priv->pool, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, priv);
- /* destroy PolicyKit actions */
- polkit_action_unref (priv->pk_unmount_action);
- g_object_unref (priv->unmount_action);
- polkit_action_unref (priv->pk_format_action);
- g_object_unref (priv->format_action);
- polkit_action_unref (priv->pk_part_modify_action);
- g_object_unref (priv->part_modify_action);
-
/* destroy the dialog and internal struct */
gtk_widget_destroy (GTK_WIDGET (priv->dialog));
g_object_unref (priv->pool);
@@ -553,6 +547,19 @@ presentable_changed (GduPresentable *presentable, FormatDialogPrivate *priv)
update_ui (priv);
}
+/* we do ref presentable ourselves */
+void
+select_new_presentable (FormatDialogPrivate *priv, GduPresentable *presentable)
+{
+ if (priv->volume_selector) {
+ gdu_util_presentable_combo_box_rebuild (priv->volume_selector, priv->pool);
+ gdu_util_presentable_combo_box_select (priv->volume_selector, presentable);
+ }
+ /* force refresh when no standalone mode */
+ if (presentable != priv->presentable || ! priv->volume_selector)
+ set_new_presentable (priv, presentable);
+}
+
static void
set_new_presentable (FormatDialogPrivate *priv, GduPresentable *presentable)
{
@@ -583,8 +590,11 @@ pool_presentable_changed (GduPool *pool, GduPresentable *presentable, FormatDial
{
g_return_if_fail (priv != NULL);
g_return_if_fail (priv->volume_selector != NULL);
- g_warning ("Pool presentable changed event.\n");
- gdu_util_presentable_combo_box_rebuild (priv->volume_selector, pool);
+
+ if (! priv->job_running) {
+ g_warning ("Pool presentable changed event.\n");
+ gdu_util_presentable_combo_box_rebuild (priv->volume_selector, pool);
+ }
}
static void
@@ -615,6 +625,7 @@ cancel_operation (FormatDialogPrivate *priv)
g_return_if_fail (priv != NULL);
g_return_if_fail (priv->job_running == TRUE);
+ /* TODO: check for valid device */
g_return_if_fail (priv->presentable != NULL);
g_warning ("Cancelling...\n");
@@ -932,19 +943,6 @@ nautilus_gdu_spawn_dialog (GduPresentable *presentable,
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
- /* set up PolicyKit actions */
- priv->pk_unmount_action = polkit_action_new ();
- polkit_action_set_action_id (priv->pk_unmount_action, "org.freedesktop.devicekit.disks.filesystem-unmount-others");
- priv->unmount_action = polkit_gnome_action_new_default ("unmount", priv->pk_unmount_action, NULL, NULL);
- priv->pk_format_action = polkit_action_new ();
- polkit_action_set_action_id (priv->pk_format_action, "org.freedesktop.devicekit.disks.change");
- priv->format_action = polkit_gnome_action_new_default ("format", priv->pk_format_action, NULL, NULL);
- priv->pk_part_modify_action = polkit_action_new ();
- /* action_id is the same as for format, but sometimes authentication is one shot */
- polkit_action_set_action_id (priv->pk_part_modify_action, "org.freedesktop.devicekit.disks.change");
- priv->part_modify_action = polkit_gnome_action_new_default ("part_modify", priv->pk_part_modify_action, NULL, NULL);
-
-
// gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, FALSE);
g_signal_connect (priv->dialog, "delete-event",
diff --git a/src/format-window.h b/src/format-window.h
index 15ada27..94445a5 100644
--- a/src/format-window.h
+++ b/src/format-window.h
@@ -61,19 +61,12 @@ typedef struct {
gboolean job_running;
gboolean job_cancelled;
-
- PolKitAction *pk_unmount_action;
- PolKitGnomeAction *unmount_action;
- PolKitAction *pk_format_action;
- PolKitGnomeAction *format_action;
- PolKitAction *pk_part_modify_action;
- PolKitGnomeAction *part_modify_action;
} FormatDialogPrivate;
-/* . pass presentable=NULL and standalone_mode=TRUE to display volume selector */
-/* . we do ref presentable ourselves */
+/* pass presentable=NULL and standalone_mode=TRUE to display volume selector */
+/* we do ref presentable ourselves */
void nautilus_gdu_spawn_dialog (GduPresentable *presentable,
gboolean standalone_mode);
@@ -82,6 +75,10 @@ void nautilus_gdu_spawn_dialog (GduPresentable *presentable,
void update_ui_controls (FormatDialogPrivate *priv);
+/* we do ref presentable ourselves */
+void select_new_presentable (FormatDialogPrivate *priv,
+ GduPresentable *presentable);
+
G_END_DECLS
#endif
diff --git a/src/gdu-utils.c b/src/gdu-utils.c
index e85eee3..0d01aef 100644
--- a/src/gdu-utils.c
+++ b/src/gdu-utils.c
@@ -147,6 +147,66 @@ find_presentable_from_device_path (char *device_path)
/* ---------------------------------------------------------------------------------------------------- */
/* Volume selector widget */
+static void
+gdu_util_presentable_combo_box_add_item (GtkListStore *store, GduPresentable *presentable)
+{
+ char *name = NULL;
+ char *display_name = NULL;
+ GdkPixbuf *pixbuf = NULL;
+ GtkTreeIter iter;
+ GduDevice *device = NULL;
+ GduPresentable *toplevel_presentable = NULL;
+ GduDevice *toplevel_device = NULL;
+
+ device = gdu_presentable_get_device (presentable);
+ toplevel_presentable = gdu_presentable_get_toplevel (presentable);
+ if (toplevel_presentable)
+ toplevel_device = gdu_presentable_get_device (toplevel_presentable);
+
+ /* Make display name */
+ if (device) {
+ name = g_strdup (gdu_device_id_get_label (device));
+ if (name && strlen (name) > 0)
+ display_name = g_strdup (name);
+ g_free (name);
+ name = NULL;
+ }
+ if (! display_name) {
+ name = gdu_presentable_get_name (presentable);
+ if (name && strlen (name) > 0)
+ display_name = g_strdup_printf ("(%s)", name);
+ g_free (name);
+ name = NULL;
+ }
+ if (! display_name && device)
+ display_name = g_strdup_printf ("(%s)", gdu_device_get_device_file (device));
+
+ /* Get an icon */
+ pixbuf = gdu_util_get_pixbuf_for_presentable (presentable, GTK_ICON_SIZE_DIALOG);
+
+ if (device || toplevel_device) {
+ gtk_list_store_append (store, &iter);
+ /* gtk_list_store_set() refs objects itself */
+ gtk_list_store_set (store, &iter,
+ 0, presentable,
+ 1, display_name,
+ 2, device ? gdu_device_get_device_file (device) : gdu_device_get_device_file (toplevel_device),
+ 3, pixbuf,
+ -1);
+ }
+
+ g_free (display_name);
+ if (device)
+ g_object_unref (device);
+ if (toplevel_presentable)
+ g_object_unref (toplevel_presentable);
+ if (toplevel_device)
+ g_object_unref (toplevel_device);
+ if (name)
+ g_free (name);
+ if (pixbuf)
+ g_object_unref (pixbuf);
+}
static GtkListStore *
gdu_util_presentable_combo_box_create_store (GduPool *pool)
@@ -173,55 +233,53 @@ gdu_util_presentable_combo_box_create_store (GduPool *pool)
GduPresentable *toplevel_presentable;
GduDevice *toplevel_device = NULL;
GduDevice *device;
- GdkPixbuf *pixbuf = NULL;
GList *enclosed_presentables = NULL;
- char *name = NULL;
- char *display_name = NULL;
-
device = gdu_presentable_get_device (presentable);
toplevel_presentable = gdu_presentable_get_toplevel (presentable);
- if (device != NULL && toplevel_presentable != NULL) {
+ if (toplevel_presentable)
toplevel_device = gdu_presentable_get_device (toplevel_presentable);
- pixbuf = gdu_util_get_pixbuf_for_presentable (presentable, GTK_ICON_SIZE_DIALOG);
+ /* First eliminate all non-toplevel presentables */
+ if (/* device != NULL && */
+ toplevel_device != NULL &&
+ toplevel_presentable == presentable &&
+ gdu_device_is_removable (toplevel_device)
+ /* && ! gdu_device_is_system_internal (device) */) {
/* determine parent presentables (in case of toplevel drive) */
enclosed_presentables = gdu_pool_get_enclosed_presentables (pool, presentable);
- if (toplevel_device != NULL && gdu_device_is_removable (toplevel_device) && g_list_length (enclosed_presentables) == 0) {
- name = g_strdup (gdu_device_id_get_label (device));
- if (name && strlen (name) > 0)
- display_name = g_strdup (name);
- g_free (name);
- name = NULL;
- if (! display_name) {
- name = gdu_presentable_get_name (presentable);
- if (name && strlen (name) > 0)
- display_name = g_strdup_printf ("(%s)", name);
- g_free (name);
- name = NULL;
- }
- if (! display_name)
- display_name = g_strdup_printf ("(%s)", gdu_device_get_device_file (device));
-
- gtk_list_store_append (store, &iter);
- /* gtk_list_store_set() refs objects itself */
- gtk_list_store_set (store, &iter,
- 0, presentable,
- 1, display_name,
- 2, gdu_device_get_device_file (device),
- 3, pixbuf,
- -1);
- g_free (display_name);
- if (name)
- g_free (name);
+ g_print ("presentable %s [%s], enclosed_presentables = %d, toplevel_presentable = %p vs. %p, gdu_device_is_partition_table = %d, gdu_device_is_optical_disc = %d, gdu_device_drive_get_media = '%s'\n",
+ gdu_presentable_get_name (presentable), device ? gdu_device_get_device_file (device) : "no device.", g_list_length (enclosed_presentables), toplevel_presentable, presentable, gdu_device_is_partition_table (device), gdu_device_is_optical_disc (device), gdu_device_drive_get_media (device));
+#if 0
+ char **media_compat = gdu_device_drive_get_media_compatibility (device);
+ for (; *media_compat; media_compat++) {
+ g_print (" compat '%s'\n", *media_compat);
+ }
+#endif
+
+
+ GList *enclosed_presentables_l;
+ for (enclosed_presentables_l = enclosed_presentables; enclosed_presentables_l != NULL; enclosed_presentables_l = enclosed_presentables_l->next) {
+ GduPresentable *presentable_e = enclosed_presentables_l->data;
+ GduDevice *device_e = gdu_presentable_get_device (presentable_e);
+ g_print (" +--- %s, GDU_IS_DRIVE = %d, GDU_IS_VOLUME = %d, GDU_IS_VOLUME_HOLE = %d, device = %p [%s]\n",
+ gdu_presentable_get_name (presentable_e), GDU_IS_DRIVE (presentable_e), GDU_IS_VOLUME (presentable_e), GDU_IS_VOLUME_HOLE (presentable_e), device_e, device_e ? gdu_device_get_device_file (device_e) : "no device.");
+ gdu_util_presentable_combo_box_add_item (store, presentable_e);
+ if (device_e)
+ g_object_unref (device_e);
+ }
+
+#if 0
+ if (/* toplevel_device != NULL && gdu_device_is_removable (toplevel_device) && */ g_list_length (enclosed_presentables) == 0) {
+ gdu_util_presentable_combo_box_add_item (store, presentable);
}
+#endif
+
g_list_foreach (enclosed_presentables, (GFunc) g_object_unref, NULL);
g_list_free (enclosed_presentables);
}
- if (pixbuf)
- g_object_unref (pixbuf);
if (toplevel_presentable)
g_object_unref (toplevel_presentable);
if (device)