[gnome-disk-utility/udisks2-port] Add UI to set up and delete loop devices
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-disk-utility/udisks2-port] Add UI to set up and delete loop devices
- Date: Sat, 23 Jul 2011 17:16:03 +0000 (UTC)
commit c731598493845385301c9b73936b6b9c2f15d071
Author: David Zeuthen <davidz redhat com>
Date: Sat Jul 23 13:15:26 2011 -0400
Add UI to set up and delete loop devices
Signed-off-by: David Zeuthen <davidz redhat com>
configure.ac | 2 +-
data/ui/palimpsest.ui | 19 ++-
src/palimpsest/gdudevicetreemodel.c | 9 +
src/palimpsest/gdudevicetreemodel.h | 9 +-
src/palimpsest/gduwindow.c | 275 +++++++++++++++++++++++++++++++++--
5 files changed, 295 insertions(+), 19 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 4b62f93..c154826 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,7 +31,7 @@ GLIB2_REQUIRED=2.22
UDISKS2_REQUIRED=1.90
GTK3_REQUIRED=3.0.0
-PKG_CHECK_MODULES(GLIB2, [gio-2.0 >= $GLIB2_REQUIRED])
+PKG_CHECK_MODULES(GLIB2, [gio-unix-2.0 >= $GLIB2_REQUIRED])
PKG_CHECK_MODULES(UDISKS2, [udisks2 >= $UDISKS2_REQUIRED])
PKG_CHECK_MODULES(GTK3, [gtk+-3.0 >= $GTK3_REQUIRED])
diff --git a/data/ui/palimpsest.ui b/data/ui/palimpsest.ui
index 168db43..6687c4a 100644
--- a/data/ui/palimpsest.ui
+++ b/data/ui/palimpsest.ui
@@ -286,6 +286,18 @@
<action-widget response="-5">button2</action-widget>
</action-widgets>
</object>
+ <object class="GtkMenu" id="device-tree-popup-menu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem" id="dtpm-attach-disk-image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="label" translatable="yes">Attach Disk Image...</property>
+ </object>
+ </child>
+ </object>
<object class="GtkWindow" id="palimpsest-window">
<property name="can_focus">False</property>
<property name="border_width">12</property>
@@ -310,7 +322,6 @@
<object class="GtkTreeView" id="device-tree-treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="headers_visible">True</property>
<property name="headers_clickable">False</property>
<property name="show_expanders">False</property>
<property name="level_indentation">12</property>
@@ -332,9 +343,10 @@
<property name="can_focus">False</property>
<property name="icon_size">1</property>
<child>
- <object class="GtkToolButton" id="dtoolbutton1">
+ <object class="GtkToolButton" id="device-tree-add-button">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Add a new device</property>
<property name="use_action_appearance">False</property>
<property name="icon_name">list-add-symbolic</property>
</object>
@@ -344,9 +356,10 @@
</packing>
</child>
<child>
- <object class="GtkToolButton" id="dtoolbutton2">
+ <object class="GtkToolButton" id="device-tree-remove-button">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Remove device</property>
<property name="use_action_appearance">False</property>
<property name="icon_name">list-remove-symbolic</property>
</object>
diff --git a/src/palimpsest/gdudevicetreemodel.c b/src/palimpsest/gdudevicetreemodel.c
index 615ef3d..d475b56 100644
--- a/src/palimpsest/gdudevicetreemodel.c
+++ b/src/palimpsest/gdudevicetreemodel.c
@@ -225,6 +225,15 @@ find_iter_for_object (GduDeviceTreeModel *model,
return data.found;
}
+gboolean
+gdu_device_tree_model_get_iter_for_object (GduDeviceTreeModel *model,
+ UDisksObject *object,
+ GtkTreeIter *iter)
+{
+ return find_iter_for_object (model, object, iter);
+}
+
+
#if 0
static gboolean
find_iter_for_object_path (GduDeviceTreeModel *model,
diff --git a/src/palimpsest/gdudevicetreemodel.h b/src/palimpsest/gdudevicetreemodel.h
index 8dfd479..1396aad 100644
--- a/src/palimpsest/gdudevicetreemodel.h
+++ b/src/palimpsest/gdudevicetreemodel.h
@@ -43,9 +43,12 @@ enum
GDU_DEVICE_TREE_MODEL_N_COLUMNS
};
-GType gdu_device_tree_model_get_type (void) G_GNUC_CONST;
-GduDeviceTreeModel *gdu_device_tree_model_new (UDisksClient *client);
-UDisksClient *gdu_device_tree_model_get_client (GduDeviceTreeModel *model);
+GType gdu_device_tree_model_get_type (void) G_GNUC_CONST;
+GduDeviceTreeModel *gdu_device_tree_model_new (UDisksClient *client);
+UDisksClient *gdu_device_tree_model_get_client (GduDeviceTreeModel *model);
+gboolean gdu_device_tree_model_get_iter_for_object (GduDeviceTreeModel *model,
+ UDisksObject *object,
+ GtkTreeIter *iter);
G_END_DECLS
diff --git a/src/palimpsest/gduwindow.c b/src/palimpsest/gduwindow.c
index 0f67caf..8057fa5 100644
--- a/src/palimpsest/gduwindow.c
+++ b/src/palimpsest/gduwindow.c
@@ -24,7 +24,13 @@
#include <string.h>
#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
#include <glib/gi18n.h>
+#include <gio/gunixfdlist.h>
#include "gduapplication.h"
#include "gduwindow.h"
@@ -79,7 +85,7 @@ static gboolean on_activate_link (GtkLabel *label,
gpointer user_data);
static void setup_device_page (GduWindow *window, UDisksObject *object);
-static void update_device_page (GduWindow *window);
+static gboolean update_device_page (GduWindow *window);
static void teardown_device_page (GduWindow *window);
static void on_volume_grid_changed (GduVolumeGrid *grid,
@@ -197,31 +203,45 @@ on_row_inserted (GtkTreeModel *tree_model,
gtk_tree_view_expand_all (GTK_TREE_VIEW (gdu_window_get_widget (window, "device-tree-treeview")));
}
-static void select_details_page (GduWindow *window,
- UDisksObject *object,
- DetailsPage page);
+static gboolean select_details_page (GduWindow *window,
+ UDisksObject *object,
+ DetailsPage page);
static void
set_selected_object (GduWindow *window,
UDisksObject *object)
{
+ gboolean can_remove;
+ GtkTreeIter iter;
+
+ if (gdu_device_tree_model_get_iter_for_object (window->model, object, &iter))
+ {
+ GtkTreeSelection *tree_selection;
+ tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (gdu_window_get_widget (window, "device-tree-treeview")));
+ gtk_tree_selection_select_iter (tree_selection, &iter);
+ }
+
+ can_remove = FALSE;
if (object != NULL)
{
if (udisks_object_peek_drive (object) != NULL ||
udisks_object_peek_block_device (object) != NULL)
{
- select_details_page (window, object, DETAILS_PAGE_DEVICE);
+ can_remove = select_details_page (window, object, DETAILS_PAGE_DEVICE);
}
else
{
g_warning ("no page for object %s", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
- select_details_page (window, NULL, DETAILS_PAGE_NOT_IMPLEMENTED);
+ can_remove = select_details_page (window, NULL, DETAILS_PAGE_NOT_IMPLEMENTED);
}
}
else
{
- select_details_page (window, NULL, DETAILS_PAGE_NOT_SELECTED);
+ can_remove = select_details_page (window, NULL, DETAILS_PAGE_NOT_SELECTED);
}
+
+ gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (window->builder, "device-tree-remove-button")),
+ can_remove);
}
static void
@@ -249,6 +269,210 @@ on_tree_selection_changed (GtkTreeSelection *tree_selection,
}
}
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_device_tree_add_button_clicked (GtkToolButton *button,
+ gpointer user_data)
+{
+ GduWindow *window = GDU_WINDOW (user_data);
+ GtkMenu *menu;
+
+ menu = GTK_MENU (gtk_builder_get_object (window->builder, "device-tree-popup-menu"));
+ gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+loop_delete_cb (UDisksLoop *loop,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GduWindow *window = GDU_WINDOW (user_data);
+ GError *error;
+
+ error = NULL;
+ if (!udisks_loop_call_delete_finish (loop, res, &error))
+ {
+ gdu_window_show_error (window,
+ _("Error deleting loop device"),
+ error);
+ g_error_free (error);
+ }
+ g_object_unref (window);
+}
+
+static void
+on_device_tree_remove_button_clicked (GtkToolButton *button,
+ gpointer user_data)
+{
+ GduWindow *window = GDU_WINDOW (user_data);
+ UDisksLoop *loop;
+
+ loop = udisks_object_peek_loop (window->current_object);
+ if (loop != NULL)
+ {
+ GVariantBuilder options_builder;
+ g_variant_builder_init (&options_builder, G_VARIANT_TYPE_VARDICT);
+ udisks_loop_call_delete (loop,
+ g_variant_builder_end (&options_builder),
+ NULL, /* GCancellable */
+ (GAsyncReadyCallback) loop_delete_cb,
+ g_object_ref (window));
+ }
+ else
+ {
+ g_warning ("remove action not implemented for object");
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+ GduWindow *window;
+ gchar *filename;
+} LoopSetupData;
+
+static LoopSetupData *
+loop_setup_data_new (GduWindow *window,
+ const gchar *filename)
+{
+ LoopSetupData *data;
+ data = g_slice_new0 (LoopSetupData);
+ data->window = g_object_ref (window);
+ data->filename = g_strdup (filename);
+ return data;
+}
+
+static void
+loop_setup_data_free (LoopSetupData *data)
+{
+ g_object_unref (data->window);
+ g_free (data->filename);
+ g_slice_free (LoopSetupData, data);
+}
+
+static void
+loop_setup_cb (UDisksManager *manager,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ LoopSetupData *data = user_data;
+ gchar *out_loop_device_object_path;
+ GError *error;
+
+ error = NULL;
+ if (!udisks_manager_call_loop_setup_finish (manager, &out_loop_device_object_path, NULL, res, &error))
+ {
+ gdu_window_show_error (data->window,
+ _("Error attaching disk image"),
+ error);
+ g_error_free (error);
+ }
+ else
+ {
+ gchar *uri;
+ UDisksObject *object;
+
+ /* This is to make it appear in the file chooser's "Recently Used" list */
+ uri = g_strdup_printf ("file://%s", data->filename);
+ gtk_recent_manager_add_item (gtk_recent_manager_get_default (), uri);
+ g_free (uri);
+
+ object = UDISKS_OBJECT (g_dbus_object_manager_get_object (udisks_client_get_object_manager (data->window->client),
+ out_loop_device_object_path));
+ set_selected_object (data->window, object);
+ g_object_unref (object);
+ g_free (out_loop_device_object_path);
+ }
+
+ loop_setup_data_free (data);
+}
+
+static void
+on_dtpm_attach_disk_image_activated (GtkMenuItem *item,
+ gpointer user_data)
+{
+ GduWindow *window = GDU_WINDOW (user_data);
+ GtkWidget *dialog;
+ GtkFileFilter *filter;
+ gchar *filename;
+ gint fd;
+ GUnixFDList *fd_list;
+ GVariantBuilder options_builder;
+
+ filename = NULL;
+ fd = -1;
+
+ dialog = gtk_file_chooser_dialog_new (_("Select Disk Image to Attach"),
+ GTK_WINDOW (window),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ _("Attach"), GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_home_dir ());
+
+ /* TODO: define proper mime-types */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_set_name (filter, _("All Files"));
+ gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); /* adopts filter */
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_set_name (filter, _("Disk Images"));
+ gtk_file_filter_add_pattern (filter, "*.img");
+ gtk_file_filter_add_pattern (filter, "*.iso");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); /* adopts filter */
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+ /* Can't support non-local files because uid gets EPERM when doing fstat(2)
+ * an FD from the FUSE mount... it would be nice to support this, though
+ */
+ /* gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), FALSE); */
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT)
+ goto out;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ gtk_widget_hide (dialog);
+
+ fd = open (filename, O_RDWR);
+ if (fd == -1)
+ fd = open (filename, O_RDONLY);
+ if (fd == -1)
+ {
+ GError *error;
+ error = g_error_new (G_IO_ERROR,
+ g_io_error_from_errno (errno),
+ "%s", strerror (errno));
+ gdu_window_show_error (window,
+ _("Error attaching disk image"),
+ error);
+ g_error_free (error);
+ goto out;
+ }
+
+ g_variant_builder_init (&options_builder, G_VARIANT_TYPE_VARDICT);
+ /* TODO: add options to options_builder */
+
+ fd_list = g_unix_fd_list_new_from_array (&fd, 1); /* adopts the fd */
+ udisks_manager_call_loop_setup (udisks_client_get_manager (window->client),
+ g_variant_new_handle (0),
+ g_variant_builder_end (&options_builder),
+ fd_list,
+ NULL, /* GCancellable */
+ (GAsyncReadyCallback) loop_setup_cb,
+ loop_setup_data_new (window, filename));
+
+ out:
+ gtk_widget_destroy (dialog);
+ g_free (filename);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+
gboolean _gdu_application_get_running_from_source_tree (GduApplication *app);
static void
@@ -452,6 +676,20 @@ gdu_window_constructed (GObject *object)
gtk_widget_set_name (gdu_window_get_widget (window, "devtab-grid-toolbar"), "devtab-grid-toolbar");
gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
+ /* popup menu */
+ g_signal_connect (gtk_builder_get_object (window->builder, "device-tree-add-button"),
+ "clicked",
+ G_CALLBACK (on_device_tree_add_button_clicked),
+ window);
+ g_signal_connect (gtk_builder_get_object (window->builder, "device-tree-remove-button"),
+ "clicked",
+ G_CALLBACK (on_device_tree_remove_button_clicked),
+ window);
+ g_signal_connect (gtk_builder_get_object (window->builder, "dtpm-attach-disk-image"),
+ "activate",
+ G_CALLBACK (on_dtpm_attach_disk_image_activated),
+ window);
+
/* actions */
g_signal_connect (gtk_builder_get_object (window->builder, "devtab-action-generic"),
"activate",
@@ -775,10 +1013,11 @@ setup_details_page (GduWindow *window,
}
}
-static void
+static gboolean
update_details_page (GduWindow *window,
DetailsPage page)
{
+ gboolean can_remove;
//g_debug ("update for %s, page %d",
// object != NULL ? g_dbus_object_get_object_path (object) : "<none>",
// page);
@@ -792,17 +1031,20 @@ update_details_page (GduWindow *window,
break;
case DETAILS_PAGE_DEVICE:
- update_device_page (window);
+ can_remove = update_device_page (window);
break;
}
+
+ return can_remove;
}
-static void
+static gboolean
select_details_page (GduWindow *window,
UDisksObject *object,
DetailsPage page)
{
GtkNotebook *notebook;
+ gboolean can_remove;
notebook = GTK_NOTEBOOK (gdu_window_get_widget (window, "palimpsest-notebook"));
@@ -821,7 +1063,8 @@ select_details_page (GduWindow *window,
window->current_object,
window->current_page);
- update_details_page (window, window->current_page);
+ can_remove = update_details_page (window, window->current_page);
+ return can_remove;
}
static void
@@ -1345,7 +1588,7 @@ update_device_page_for_free_space (GduWindow *window,
"devtab-action-partition-create")), TRUE);
}
-static void
+static gboolean
update_device_page (GduWindow *window)
{
UDisksObject *object;
@@ -1355,6 +1598,9 @@ update_device_page (GduWindow *window)
guint64 size;
GList *children;
GList *l;
+ gboolean can_remove;
+
+ can_remove = FALSE;
/* first hide everything */
gtk_container_foreach (GTK_CONTAINER (gdu_window_get_widget (window, "devtab-drive-table")),
@@ -1377,6 +1623,9 @@ update_device_page (GduWindow *window)
type = gdu_volume_grid_get_selected_type (GDU_VOLUME_GRID (window->volume_grid));
size = gdu_volume_grid_get_selected_size (GDU_VOLUME_GRID (window->volume_grid));
+ if (udisks_object_peek_loop (object) != NULL)
+ can_remove = TRUE;
+
if (drive != NULL)
update_device_page_for_drive (window, object, drive);
@@ -1413,6 +1662,8 @@ update_device_page (GduWindow *window)
}
}
}
+
+ return can_remove;
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]