[gnome-disk-utility] Disks: Add new --restore-disk-image option
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-disk-utility] Disks: Add new --restore-disk-image option
- Date: Wed, 22 May 2013 02:24:52 +0000 (UTC)
commit 55ceb75042cb22a041847278aa3aaec9d044b729
Author: David Zeuthen <zeuthen gmail com>
Date: Tue May 21 18:33:59 2013 -0700
Disks: Add new --restore-disk-image option
Signed-off-by: David Zeuthen <zeuthen gmail com>
data/ui/restore-disk-image-dialog.ui | 110 ++++++++++++++-
doc/man/gnome-disks.xml | 15 ++
src/disks/gduapplication.c | 8 +
src/disks/gdudevicetreemodel.c | 101 ++++++++++++--
src/disks/gdudevicetreemodel.h | 4 +-
src/disks/gduenums.h | 10 ++
src/disks/gdurestorediskimagedialog.c | 235 +++++++++++++++++++++++++++++----
src/disks/gdurestorediskimagedialog.h | 3 +-
src/disks/gduwindow.c | 8 +-
9 files changed, 446 insertions(+), 48 deletions(-)
---
diff --git a/data/ui/restore-disk-image-dialog.ui b/data/ui/restore-disk-image-dialog.ui
index 6ba5e95..8657f93 100644
--- a/data/ui/restore-disk-image-dialog.ui
+++ b/data/ui/restore-disk-image-dialog.ui
@@ -36,26 +36,26 @@
<property name="row_spacing">12</property>
<property name="column_spacing">12</property>
<child>
- <object class="GtkLabel" id="image-key-label">
+ <object class="GtkLabel" id="selectable-image-label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
<property name="label" translatable="yes">_Image to Restore</property>
<property name="use_underline">True</property>
- <property name="mnemonic_widget">image-fcbutton</property>
+ <property name="mnemonic_widget">selectable-image-fcbutton</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">0</property>
+ <property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
- <object class="GtkFileChooserButton" id="image-fcbutton">
+ <object class="GtkFileChooserButton" id="selectable-image-fcbutton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
@@ -64,7 +64,7 @@
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">0</property>
+ <property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
@@ -81,7 +81,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">1</property>
+ <property name="top_attach">3</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
@@ -97,7 +97,103 @@
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="selectable-destination-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Destination</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="selectable-destination-combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="image-key-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Image to Restore</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="image-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="selectable">True</property>
+ <property name="ellipsize">middle</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="image-size-key-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Image Size</property>
+ <property name="use_underline">True</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="image-size-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="selectable">True</property>
+ <property name="ellipsize">middle</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
diff --git a/doc/man/gnome-disks.xml b/doc/man/gnome-disks.xml
index 35f183d..ceda33c 100644
--- a/doc/man/gnome-disks.xml
+++ b/doc/man/gnome-disks.xml
@@ -70,6 +70,21 @@
</varlistentry>
<varlistentry>
+ <term>
+ <option>--restore-disk-image <replaceable>FILE</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ Shows the “Restore Disk Image” dialog for the file given
+ by <replaceable>FILE</replaceable> (for example,
+ <filename>/home/user/Downloads/SuperOS.iso</filename>) and
+ prompts the user to choose a disk to restore the image
+ unto.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--help</option></term>
<listitem>
<para>
diff --git a/src/disks/gduapplication.c b/src/disks/gduapplication.c
index 1334d28..612e969 100644
--- a/src/disks/gduapplication.c
+++ b/src/disks/gduapplication.c
@@ -18,6 +18,7 @@
#include "gduapplication.h"
#include "gduformatvolumedialog.h"
+#include "gdurestorediskimagedialog.h"
#include "gduwindow.h"
#include "gdulocaljob.h"
@@ -172,12 +173,14 @@ gdu_application_command_line (GApplication *_app,
gchar *opt_block_device = NULL, *error_message = NULL;
gboolean opt_help = FALSE;
gboolean opt_format = FALSE;
+ gchar *opt_restore_disk_image = NULL;
gint opt_xid = -1;
GOptionEntry opt_entries[] =
{
{"block-device", 0, 0, G_OPTION_ARG_STRING, &opt_block_device, N_("Select device"), NULL },
{"format-device", 0, 0, G_OPTION_ARG_NONE, &opt_format, N_("Format selected device"), NULL },
{"xid", 0, 0, G_OPTION_ARG_INT, &opt_xid, N_("Parent window XID for the format dialog"), NULL },
+ {"restore-disk-image", 0, 0, G_OPTION_ARG_FILENAME, &opt_restore_disk_image, N_("Restore disk image"),
NULL },
{"help", '?', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_help, N_("Show help options"), NULL },
{NULL}
};
@@ -254,6 +257,10 @@ gdu_application_command_line (GApplication *_app,
gdu_format_volume_dialog_show_for_xid (app->client, opt_xid, object_to_select);
}
+ if (opt_restore_disk_image != NULL)
+ {
+ gdu_restore_disk_image_dialog_show (app->window, NULL, opt_restore_disk_image);
+ }
ret = 0;
@@ -261,6 +268,7 @@ gdu_application_command_line (GApplication *_app,
g_option_context_free (context);
g_clear_object (&object_to_select);
g_free (opt_block_device);
+ g_free (opt_restore_disk_image);
g_strfreev (argv);
return ret;
}
diff --git a/src/disks/gdudevicetreemodel.c b/src/disks/gdudevicetreemodel.c
index 21e623a..a3e51b5 100644
--- a/src/disks/gdudevicetreemodel.c
+++ b/src/disks/gdudevicetreemodel.c
@@ -24,6 +24,8 @@ struct _GduDeviceTreeModel
GduApplication *application;
UDisksClient *client;
+ GduDeviceTreeModelFlags flags;
+
GList *current_drives;
GtkTreeIter drive_iter;
gboolean drive_iter_valid;
@@ -52,7 +54,8 @@ typedef struct
enum
{
PROP_0,
- PROP_APPLICATION
+ PROP_APPLICATION,
+ PROP_FLAGS
};
G_DEFINE_TYPE (GduDeviceTreeModel, gdu_device_tree_model, GTK_TYPE_TREE_STORE);
@@ -80,7 +83,8 @@ gdu_device_tree_model_finalize (GObject *object)
{
GduDeviceTreeModel *model = GDU_DEVICE_TREE_MODEL (object);
- g_source_remove (model->pefs_timeout_id);
+ if (model->pefs_timeout_id != 0)
+ g_source_remove (model->pefs_timeout_id);
if (model->spinner_timeout != 0)
g_source_remove (model->spinner_timeout);
@@ -95,7 +99,7 @@ gdu_device_tree_model_finalize (GObject *object)
g_list_foreach (model->current_mdraids, (GFunc) g_object_unref, NULL);
g_list_free (model->current_mdraids);
- g_object_unref (model->client);
+ g_object_unref (model->application);
G_OBJECT_CLASS (gdu_device_tree_model_parent_class)->finalize (object);
}
@@ -119,6 +123,10 @@ gdu_device_tree_model_get_property (GObject *object,
g_value_set_object (value, gdu_device_tree_model_get_application (model));
break;
+ case PROP_FLAGS:
+ g_value_set_flags (value, gdu_device_tree_model_get_flags (model));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -140,6 +148,10 @@ gdu_device_tree_model_set_property (GObject *object,
model->client = gdu_application_get_client (model->application);
break;
+ case PROP_FLAGS:
+ model->flags = g_value_get_flags (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -480,8 +492,22 @@ gdu_device_tree_model_constructed (GObject *object)
model);
coldplug (model);
- model->pefs_timeout_id = g_timeout_add_seconds (5, on_pefs_timeout, model);
- on_pefs_timeout (model);
+ if (model->flags & GDU_DEVICE_TREE_MODEL_FLAGS_UPDATE_POWER_STATE)
+ {
+ model->pefs_timeout_id = g_timeout_add_seconds (5, on_pefs_timeout, model);
+ on_pefs_timeout (model);
+ }
+
+ if (model->flags & GDU_DEVICE_TREE_MODEL_FLAGS_INCLUDE_NONE_ITEM)
+ {
+ gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
+ &model->drive_iter,
+ NULL, /* GtkTreeIter *parent */
+ 0,
+ GDU_DEVICE_TREE_MODEL_COLUMN_NAME, _("(None)"),
+ GDU_DEVICE_TREE_MODEL_COLUMN_SORT_KEY, "00_0select_device",
+ -1);
+ }
if (G_OBJECT_CLASS (gdu_device_tree_model_parent_class)->constructed != NULL)
G_OBJECT_CLASS (gdu_device_tree_model_parent_class)->constructed (object);
@@ -511,11 +537,27 @@ gdu_device_tree_model_class_init (GduDeviceTreeModelClass *klass)
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GduDeviceTreeModel:flags:
+ *
+ * The #GduApplication used by the #GduDeviceTreeModel instance.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_FLAGS,
+ g_param_spec_flags ("flags", NULL, NULL,
+ GDU_TYPE_DEVICE_TREE_MODEL_FLAGS,
+ GDU_DEVICE_TREE_MODEL_FLAGS_NONE,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
}
/**
* gdu_device_tree_model_new:
* @application: A #GduApplication.
+ * @flags: Flags from #GduDeviceTreeModelFlags.
*
* Creates a new #GduDeviceTreeModel for viewing the devices belonging to
* @application.
@@ -523,10 +565,12 @@ gdu_device_tree_model_class_init (GduDeviceTreeModelClass *klass)
* Returns: A #GduDeviceTreeModel. Free with g_object_unref().
*/
GduDeviceTreeModel *
-gdu_device_tree_model_new (GduApplication *application)
+gdu_device_tree_model_new (GduApplication *application,
+ GduDeviceTreeModelFlags flags)
{
return GDU_DEVICE_TREE_MODEL (g_object_new (GDU_TYPE_DEVICE_TREE_MODEL,
"application", application,
+ "flags", flags,
NULL));
}
@@ -546,6 +590,21 @@ gdu_device_tree_model_get_application (GduDeviceTreeModel *model)
return model->application;
}
+/**
+ * gdu_device_tree_model_get_flags:
+ * @model: A #GduDeviceTreeModel.
+ *
+ * Gets the #GduDeviceTreeModelFlags used by @model.
+ *
+ * Returns: The flags that @model was constructed with.
+ */
+GduDeviceTreeModelFlags
+gdu_device_tree_model_get_flags (GduDeviceTreeModel *model)
+{
+ g_return_val_if_fail (GDU_IS_DEVICE_TREE_MODEL (model), GDU_DEVICE_TREE_MODEL_FLAGS_NONE);
+ return model->flags;
+}
+
/* ---------------------------------------------------------------------------------------------------- */
static GtkTreeIter *
@@ -553,6 +612,9 @@ get_drive_header_iter (GduDeviceTreeModel *model)
{
gchar *s;
+ if (model->flags & GDU_DEVICE_TREE_MODEL_FLAGS_FLAT)
+ return NULL;
+
if (model->drive_iter_valid)
goto out;
@@ -626,6 +688,9 @@ get_mdraid_header_iter (GduDeviceTreeModel *model)
{
gchar *s;
+ if (model->flags & GDU_DEVICE_TREE_MODEL_FLAGS_FLAT)
+ return NULL;
+
if (model->mdraid_iter_valid)
goto out;
@@ -897,6 +962,7 @@ update_drive (GduDeviceTreeModel *model,
UDisksObjectInfo *info = NULL;
UDisksBlock *block = NULL;
gchar *s = NULL;
+ gchar *included_device_name = NULL;
gboolean warning = FALSE;
gboolean jobs_running = FALSE;
GtkTreeIter iter;
@@ -923,6 +989,9 @@ update_drive (GduDeviceTreeModel *model,
g_free (s);
}
+ if (model->flags & GDU_DEVICE_TREE_MODEL_FLAGS_INCLUDE_DEVICE_NAME)
+ included_device_name = g_strdup_printf (" (%s)", udisks_block_get_preferred_device (block));
+
info = udisks_client_get_object_info (model->client, object);
if (warning)
{
@@ -930,16 +999,18 @@ update_drive (GduDeviceTreeModel *model,
* of hard-coding the color
*/
s = g_strdup_printf ("<span foreground=\"#ff0000\">%s</span>\n"
- "<small><span foreground=\"#ff0000\">%s</span></small>",
+ "<small><span foreground=\"#ff0000\">%s%s</span></small>",
udisks_object_info_get_description (info),
- udisks_object_info_get_name (info));
+ udisks_object_info_get_name (info),
+ included_device_name != NULL ? included_device_name : "");
}
else
{
s = g_strdup_printf ("%s\n"
- "<small>%s</small>",
+ "<small>%s%s</small>",
udisks_object_info_get_description (info),
- udisks_object_info_get_name (info));
+ udisks_object_info_get_name (info),
+ included_device_name != NULL ? included_device_name : "");
}
jobs_running = drive_has_jobs (model, drive);
@@ -966,7 +1037,7 @@ update_drive (GduDeviceTreeModel *model,
-1);
/* update spinner, if jobs are running */
- if (jobs_running)
+ if (jobs_running && (model->flags & GDU_DEVICE_TREE_MODEL_FLAGS_UPDATE_PULSE))
{
if (model->spinner_timeout == 0)
{
@@ -978,6 +1049,7 @@ update_drive (GduDeviceTreeModel *model,
g_clear_object (&block);
g_clear_object (&info);
g_free (s);
+ g_free (included_device_name);
return jobs_running;
}
@@ -1170,7 +1242,7 @@ update_mdraid (GduDeviceTreeModel *model,
-1);
/* update spinner, if jobs are running */
- if (jobs_running)
+ if (jobs_running && (model->flags & GDU_DEVICE_TREE_MODEL_FLAGS_UPDATE_PULSE))
{
if (model->spinner_timeout == 0)
{
@@ -1261,6 +1333,9 @@ get_block_header_iter (GduDeviceTreeModel *model)
{
gchar *s;
+ if (model->flags & GDU_DEVICE_TREE_MODEL_FLAGS_FLAT)
+ return NULL;
+
if (model->block_iter_valid)
goto out;
@@ -1402,7 +1477,7 @@ update_block (GduDeviceTreeModel *model,
-1);
/* update spinner, if jobs are running */
- if (jobs_running)
+ if (jobs_running && (model->flags & GDU_DEVICE_TREE_MODEL_FLAGS_UPDATE_PULSE))
{
if (model->spinner_timeout == 0)
{
diff --git a/src/disks/gdudevicetreemodel.h b/src/disks/gdudevicetreemodel.h
index 021b567..079ae98 100644
--- a/src/disks/gdudevicetreemodel.h
+++ b/src/disks/gdudevicetreemodel.h
@@ -38,8 +38,10 @@ enum
};
GType gdu_device_tree_model_get_type (void) G_GNUC_CONST;
-GduDeviceTreeModel *gdu_device_tree_model_new (GduApplication *application);
+GduDeviceTreeModel *gdu_device_tree_model_new (GduApplication *application,
+ GduDeviceTreeModelFlags flags);
GduApplication *gdu_device_tree_model_get_application (GduDeviceTreeModel *model);
+GduDeviceTreeModelFlags gdu_device_tree_model_get_flags (GduDeviceTreeModel *model);
gboolean gdu_device_tree_model_get_iter_for_object (GduDeviceTreeModel *model,
UDisksObject *object,
GtkTreeIter *iter);
diff --git a/src/disks/gduenums.h b/src/disks/gduenums.h
index 1dcbeda..b520be8 100644
--- a/src/disks/gduenums.h
+++ b/src/disks/gduenums.h
@@ -30,6 +30,16 @@ typedef enum
GDU_POWER_STATE_FLAGS_FAILED = (1<<2)
} GduPowerStateFlags;
+typedef enum
+{
+ GDU_DEVICE_TREE_MODEL_FLAGS_NONE = 0,
+ GDU_DEVICE_TREE_MODEL_FLAGS_FLAT = (1<<0),
+ GDU_DEVICE_TREE_MODEL_FLAGS_UPDATE_POWER_STATE = (1<<1),
+ GDU_DEVICE_TREE_MODEL_FLAGS_UPDATE_PULSE = (1<<2),
+ GDU_DEVICE_TREE_MODEL_FLAGS_INCLUDE_DEVICE_NAME = (1<<3),
+ GDU_DEVICE_TREE_MODEL_FLAGS_INCLUDE_NONE_ITEM = (1<<4),
+} GduDeviceTreeModelFlags;
+
G_END_DECLS
#endif /* __GDU_ENUMS_H__ */
diff --git a/src/disks/gdurestorediskimagedialog.c b/src/disks/gdurestorediskimagedialog.c
index abfc4f5..181cbf0 100644
--- a/src/disks/gdurestorediskimagedialog.c
+++ b/src/disks/gdurestorediskimagedialog.c
@@ -25,6 +25,7 @@
#include "gduvolumegrid.h"
#include "gduestimator.h"
#include "gdulocaljob.h"
+#include "gdudevicetreemodel.h"
/* ---------------------------------------------------------------------------------------------------- */
@@ -34,6 +35,9 @@ typedef struct
GduWindow *window;
UDisksObject *object;
+ gchar *disk_image_filename;
+ gboolean switch_to_object;
+
UDisksBlock *block;
UDisksDrive *drive;
@@ -47,10 +51,17 @@ typedef struct
GtkWidget *error_label;
GtkWidget *image_key_label;
- GtkWidget *image_fcbutton;
+ GtkWidget *image_label;
+ GtkWidget *selectable_image_label;
+ GtkWidget *selectable_image_fcbutton;
+
+ GtkWidget *image_size_key_label;
+ GtkWidget *image_size_label;
GtkWidget *destination_key_label;
GtkWidget *destination_label;
+ GtkWidget *selectable_destination_label;
+ GtkWidget *selectable_destination_combobox;
GtkWidget *start_copying_button;
GtkWidget *cancel_button;
@@ -91,9 +102,17 @@ static const struct {
{G_STRUCT_OFFSET (DialogData, infobar_vbox), "infobar-vbox"},
{G_STRUCT_OFFSET (DialogData, image_key_label), "image-key-label"},
- {G_STRUCT_OFFSET (DialogData, image_fcbutton), "image-fcbutton"},
+ {G_STRUCT_OFFSET (DialogData, image_label), "image-label"},
+ {G_STRUCT_OFFSET (DialogData, selectable_image_label), "selectable-image-label"},
+ {G_STRUCT_OFFSET (DialogData, selectable_image_fcbutton), "selectable-image-fcbutton"},
+
+ {G_STRUCT_OFFSET (DialogData, image_size_key_label), "image-size-key-label"},
+ {G_STRUCT_OFFSET (DialogData, image_size_label), "image-size-label"},
+
{G_STRUCT_OFFSET (DialogData, destination_key_label), "destination-key-label"},
{G_STRUCT_OFFSET (DialogData, destination_label), "destination-label"},
+ {G_STRUCT_OFFSET (DialogData, selectable_destination_label), "selectable-destination-label"},
+ {G_STRUCT_OFFSET (DialogData, selectable_destination_combobox), "selectable-destination-combobox"},
{G_STRUCT_OFFSET (DialogData, start_copying_button), "start-copying-button"},
{G_STRUCT_OFFSET (DialogData, cancel_button), "cancel-button"},
@@ -158,9 +177,10 @@ dialog_data_unref (DialogData *data)
g_object_unref (data->warning_infobar);
g_object_unref (data->error_infobar);
g_object_unref (data->window);
- g_object_unref (data->object);
- g_object_unref (data->block);
+ g_clear_object (&data->object);
+ g_clear_object (&data->block);
g_clear_object (&data->drive);
+ g_free (data->disk_image_filename);
if (data->builder != NULL)
g_object_unref (data->builder);
g_free (data->buffer);
@@ -213,6 +233,7 @@ restore_disk_image_update (DialogData *data)
gboolean can_proceed = FALSE;
gchar *restore_warning = NULL;
gchar *restore_error = NULL;
+ gchar *image_size_str = NULL;
GFile *restore_file = NULL;
if (data->dialog == NULL)
@@ -223,7 +244,11 @@ restore_disk_image_update (DialogData *data)
goto out;
/* Check if we have a file */
- restore_file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (data->image_fcbutton));
+ if (data->disk_image_filename != NULL)
+ restore_file = g_file_new_for_commandline_arg (data->disk_image_filename);
+ else
+ restore_file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (data->selectable_image_fcbutton));
+
if (restore_file != NULL)
{
GFileInfo *info;
@@ -237,6 +262,8 @@ restore_disk_image_update (DialogData *data)
size = g_file_info_get_size (info);
g_object_unref (info);
+ image_size_str = udisks_client_get_size_for_display (gdu_window_get_client (data->window), size,
FALSE, TRUE);
+
if (data->block_size > 0)
{
if (size == 0)
@@ -289,9 +316,12 @@ restore_disk_image_update (DialogData *data)
gtk_widget_hide (data->error_infobar);
}
+ gtk_label_set_text (GTK_LABEL (data->image_size_label), image_size_str != NULL ? image_size_str : "—");
+
g_free (restore_warning);
g_free (restore_error);
g_clear_object (&restore_file);
+ g_free (image_size_str);
gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK, can_proceed);
@@ -327,16 +357,167 @@ on_notify (GObject *object,
/* ---------------------------------------------------------------------------------------------------- */
static void
+destination_combobox_sensitive_cb (GtkCellLayout *cell_layout,
+ GtkCellRenderer *renderer,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ /* DialogData *data = user_data; */
+ gboolean sensitive = FALSE;
+ UDisksBlock *block = NULL;
+
+ gtk_tree_model_get (model, iter,
+ GDU_DEVICE_TREE_MODEL_COLUMN_BLOCK, &block,
+ -1);
+
+ if (block == NULL)
+ sensitive = TRUE;
+
+ if (block != NULL &&
+ udisks_block_get_size (block) > 0 &&
+ !udisks_block_get_read_only (block))
+ sensitive = TRUE;
+
+ gtk_cell_renderer_set_sensitive (renderer, sensitive);
+
+ g_clear_object (&block);
+}
+
+static void
+set_destination_object (DialogData *data,
+ UDisksObject *object)
+{
+ if (data->object != object)
+ {
+ g_clear_object (&data->object);
+ g_clear_object (&data->block);
+ g_clear_object (&data->drive);
+ data->block_size = 0;
+ if (object != NULL)
+ {
+ data->object = g_object_ref (object);
+ data->block = udisks_object_get_block (data->object);
+ g_assert (data->block != NULL);
+ data->drive = udisks_client_get_drive_for_block (gdu_window_get_client (data->window),
data->block);
+ /* TODO: use a method call for this so it works on e.g. floppy drives where e.g. we don't know the
size */
+ data->block_size = udisks_block_get_size (data->block);
+ }
+ }
+}
+
+static void
+on_destination_combobox_notify_active (GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ DialogData *data = user_data;
+ UDisksObject *object = NULL;
+ GtkTreeIter iter;
+ GtkComboBox *combobox;
+
+ combobox = GTK_COMBO_BOX (data->selectable_destination_combobox);
+ if (gtk_combo_box_get_active_iter (combobox, &iter))
+ {
+ UDisksBlock *block = NULL;
+ gtk_tree_model_get (gtk_combo_box_get_model (combobox),
+ &iter,
+ GDU_DEVICE_TREE_MODEL_COLUMN_BLOCK, &block,
+ -1);
+ if (block != NULL)
+ object = (UDisksObject *) g_dbus_interface_dup_object (G_DBUS_INTERFACE (block));
+ g_clear_object (&block);
+ }
+ set_destination_object (data, object);
+ restore_disk_image_update (data);
+ g_clear_object (&object);
+}
+
+static void
+populate_destination_combobox (DialogData *data)
+{
+ GduDeviceTreeModel *model;
+ GtkComboBox *combobox;
+ GtkCellRenderer *renderer;
+
+ combobox = GTK_COMBO_BOX (data->selectable_destination_combobox);
+ model = gdu_device_tree_model_new (gdu_window_get_application (data->window),
+ GDU_DEVICE_TREE_MODEL_FLAGS_FLAT |
+ GDU_DEVICE_TREE_MODEL_FLAGS_INCLUDE_DEVICE_NAME |
+ GDU_DEVICE_TREE_MODEL_FLAGS_INCLUDE_NONE_ITEM);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
+ GDU_DEVICE_TREE_MODEL_COLUMN_SORT_KEY,
+ GTK_SORT_ASCENDING);
+ gtk_combo_box_set_model (combobox, GTK_TREE_MODEL (model));
+ g_object_unref (model);
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (G_OBJECT (renderer),
+ "stock-size", GTK_ICON_SIZE_DND,
+ NULL);
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer,
+ "gicon", GDU_DEVICE_TREE_MODEL_COLUMN_ICON,
+ NULL);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combobox), renderer,
+ destination_combobox_sensitive_cb, data, NULL);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer,
+ "markup", GDU_DEVICE_TREE_MODEL_COLUMN_NAME,
+ NULL);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combobox), renderer,
+ destination_combobox_sensitive_cb, data, NULL);
+
+ g_signal_connect (combobox, "notify::active", G_CALLBACK (on_destination_combobox_notify_active), data);
+
+ /* Select (None) item */
+ gtk_combo_box_set_active (combobox, 0);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
restore_disk_image_populate (DialogData *data)
{
- UDisksObjectInfo *info;
+ gdu_utils_configure_file_chooser_for_disk_images (GTK_FILE_CHOOSER (data->selectable_image_fcbutton),
TRUE);
+
+ /* Image: Show label if image is known, otherwise show a filechooser button */
+ if (data->disk_image_filename != NULL)
+ {
+ gchar *s;
+ s = gdu_utils_unfuse_path (data->disk_image_filename);
+ gtk_label_set_text (GTK_LABEL (data->image_label), s);
+ g_free (s);
+
+ gtk_widget_hide (data->selectable_image_label);
+ gtk_widget_hide (data->selectable_image_fcbutton);
+ }
+ else
+ {
+ gtk_widget_hide (data->image_key_label);
+ gtk_widget_hide (data->image_label);
+ }
- gdu_utils_configure_file_chooser_for_disk_images (GTK_FILE_CHOOSER (data->image_fcbutton), TRUE);
+ /* Destination: Show label if device is known, otherwise show a combobox */
+ if (data->object != NULL)
+ {
+ UDisksObjectInfo *info;
+ info = udisks_client_get_object_info (gdu_window_get_client (data->window), data->object);
+ gtk_label_set_text (GTK_LABEL (data->destination_label), udisks_object_info_get_one_liner (info));
+ g_clear_object (&info);
- /* Destination label */
- info = udisks_client_get_object_info (gdu_window_get_client (data->window), data->object);
- gtk_label_set_text (GTK_LABEL (data->destination_label), udisks_object_info_get_one_liner (info));
- g_clear_object (&info);
+ gtk_widget_hide (data->selectable_destination_label);
+ gtk_widget_hide (data->selectable_destination_combobox);
+ }
+ else
+ {
+ gtk_widget_hide (data->destination_key_label);
+ gtk_widget_hide (data->destination_label);
+
+ populate_destination_combobox (data);
+ }
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -712,7 +893,11 @@ start_copying (DialogData *data)
GError *error;
error = NULL;
- file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (data->image_fcbutton));
+ if (data->disk_image_filename != NULL)
+ file = g_file_new_for_commandline_arg (data->disk_image_filename);
+ else
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (data->selectable_image_fcbutton));
+
data->file_input_stream = g_file_read (file,
NULL,
&error);
@@ -761,6 +946,9 @@ start_copying (DialogData *data)
dialog_data_hide (data);
+ if (data->switch_to_object)
+ gdu_window_select_object (data->window, data->object);
+
g_thread_new ("copy-disk-image-thread",
copy_thread_func,
dialog_data_ref (data));
@@ -815,7 +1003,7 @@ on_dialog_response (GtkDialog *dialog,
}
/* now that we know the user picked a folder, update file chooser settings */
- gdu_utils_file_chooser_for_disk_images_update_settings (GTK_FILE_CHOOSER (data->image_fcbutton));
+ gdu_utils_file_chooser_for_disk_images_update_settings (GTK_FILE_CHOOSER
(data->selectable_image_fcbutton));
/* ensure the device is unused (e.g. unmounted) before copying data to it... */
gdu_window_ensure_unused (data->window,
@@ -836,7 +1024,8 @@ on_dialog_response (GtkDialog *dialog,
void
gdu_restore_disk_image_dialog_show (GduWindow *window,
- UDisksObject *object)
+ UDisksObject *object,
+ const gchar *disk_image_filename)
{
guint n;
DialogData *data;
@@ -845,15 +1034,12 @@ gdu_restore_disk_image_dialog_show (GduWindow *window,
data->ref_count = 1;
g_mutex_init (&data->copy_lock);
data->window = g_object_ref (window);
- data->object = g_object_ref (object);
- data->block = udisks_object_get_block (object);
- g_assert (data->block != NULL);
- data->drive = udisks_client_get_drive_for_block (gdu_window_get_client (window), data->block);
+ set_destination_object (data, object);
+ if (object == NULL)
+ data->switch_to_object = TRUE;
+ data->disk_image_filename = g_strdup (disk_image_filename);
data->cancellable = g_cancellable_new ();
- /* TODO: use a method call for this so it works on e.g. floppy drives where e.g. we don't know the size */
- data->block_size = udisks_block_get_size (data->block);
-
data->dialog = GTK_WIDGET (gdu_application_new_widget (gdu_window_get_application (data->window),
"restore-disk-image-dialog.ui",
"restore-disk-image-dialog",
@@ -863,7 +1049,7 @@ gdu_restore_disk_image_dialog_show (GduWindow *window,
gpointer *p = (gpointer *) ((char *) data + widget_mapping[n].offset);
*p = gtk_builder_get_object (data->builder, widget_mapping[n].name);
}
- g_signal_connect (data->image_fcbutton, "file-set", G_CALLBACK (on_file_set), data);
+ g_signal_connect (data->selectable_image_fcbutton, "file-set", G_CALLBACK (on_file_set), data);
data->warning_infobar = gdu_utils_create_info_bar (GTK_MESSAGE_INFO, "", &data->warning_label);
gtk_box_pack_start (GTK_BOX (data->infobar_vbox), data->warning_infobar, TRUE, TRUE, 0);
@@ -881,7 +1067,7 @@ gdu_restore_disk_image_dialog_show (GduWindow *window,
/* unfortunately, GtkFileChooserButton:file-set is not emitted when the user
* unselects a file but we can work around that.. (TODO: file bug against gtk+)
*/
- g_signal_connect (data->image_fcbutton, "notify",
+ g_signal_connect (data->selectable_image_fcbutton, "notify",
G_CALLBACK (on_notify), data);
data->response_signal_handler_id = g_signal_connect (data->dialog,
@@ -891,6 +1077,9 @@ gdu_restore_disk_image_dialog_show (GduWindow *window,
gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (window));
gtk_window_present (GTK_WINDOW (data->dialog));
+
+ gtk_widget_realize (data->selectable_destination_combobox);
+ gtk_widget_grab_focus (data->selectable_destination_combobox);
}
/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/disks/gdurestorediskimagedialog.h b/src/disks/gdurestorediskimagedialog.h
index 496084c..261bc0e 100644
--- a/src/disks/gdurestorediskimagedialog.h
+++ b/src/disks/gdurestorediskimagedialog.h
@@ -16,7 +16,8 @@
G_BEGIN_DECLS
void gdu_restore_disk_image_dialog_show (GduWindow *window,
- UDisksObject *object);
+ UDisksObject *object,
+ const gchar *disk_image_filename);
G_END_DECLS
diff --git a/src/disks/gduwindow.c b/src/disks/gduwindow.c
index 17a1c26..e5218ff 100644
--- a/src/disks/gduwindow.c
+++ b/src/disks/gduwindow.c
@@ -1310,7 +1310,9 @@ gdu_window_constructed (GObject *object)
//gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
- window->model = gdu_device_tree_model_new (window->application);
+ window->model = gdu_device_tree_model_new (window->application,
+ GDU_DEVICE_TREE_MODEL_FLAGS_UPDATE_POWER_STATE |
+ GDU_DEVICE_TREE_MODEL_FLAGS_UPDATE_PULSE);
gtk_tree_view_set_model (GTK_TREE_VIEW (window->device_tree_treeview), GTK_TREE_MODEL (window->model));
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (window->model),
@@ -3774,7 +3776,7 @@ on_generic_drive_menu_item_restore_disk_image (GtkMenuItem *menu_item,
object = gdu_volume_grid_get_block_object (GDU_VOLUME_GRID (window->volume_grid));
g_assert (object != NULL);
- gdu_restore_disk_image_dialog_show (window, object);
+ gdu_restore_disk_image_dialog_show (window, object, NULL);
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -3816,7 +3818,7 @@ on_generic_menu_item_restore_volume_image (GtkMenuItem *menu_item,
object = gdu_volume_grid_get_selected_device (GDU_VOLUME_GRID (window->volume_grid));
g_assert (object != NULL);
- gdu_restore_disk_image_dialog_show (window, object);
+ gdu_restore_disk_image_dialog_show (window, object, NULL);
}
/* ---------------------------------------------------------------------------------------------------- */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]