[seahorse/refactor: 37/37] Right clicking on the sidebar items for context menus.



commit d4b8510ad74b2b7a8b5e67a554f16eeff9000228
Author: Stef Walter <stefw collabora co uk>
Date:   Thu Oct 20 09:42:22 2011 +0200

    Right clicking on the sidebar items for context menus.

 gkr/seahorse-gkr-actions.c     |   63 +++++++++++--------
 libseahorse/seahorse-actions.c |    9 +++
 libseahorse/seahorse-actions.h |    2 +-
 libseahorse/seahorse-viewer.c  |   20 ++++--
 libseahorse/seahorse-viewer.h  |    4 +-
 src/seahorse-key-manager.c     |   14 ++++
 src/seahorse-key-manager.ui    |   13 +---
 src/seahorse-sidebar.c         |  134 +++++++++++++++++++++++++++++++++++++++-
 8 files changed, 208 insertions(+), 51 deletions(-)
---
diff --git a/gkr/seahorse-gkr-actions.c b/gkr/seahorse-gkr-actions.c
index 2479dba..bddf259 100644
--- a/gkr/seahorse-gkr-actions.c
+++ b/gkr/seahorse-gkr-actions.c
@@ -67,19 +67,24 @@ on_new_keyring (GtkAction *action,
 	seahorse_gkr_add_keyring_show (seahorse_action_get_window (action));
 }
 
+static void
+on_new_item (GtkAction *action,
+                 gpointer unused)
+{
+	seahorse_gkr_add_item_show (seahorse_action_get_window (action));
+}
 
 static const GtkActionEntry BACKEND_ACTIONS[] = {
-	{ "new-keyring", "folder", N_("New password keyring"), "",
+	{ "gkr-keyring-new", "folder", N_("New password keyring"), "",
 	  N_("Used to store application and network passwords"), G_CALLBACK (on_new_keyring) },
+	{ "gkr-item-new", "emblem-readonly", N_("New password..."), "",
+	  N_("Safely store a password or secret."), G_CALLBACK (on_new_item) },
 };
 
-static const gchar* BACKEND_UI = ""\
-"<ui>"\
-"	<popup name='PlacePopup'>"\
-"		<menuitem action='keyring-default'/>"\
-"		<menuitem action='keyring-lock'/>"\
-"		<menuitem action='keyring-unlock'/>"\
-"		<menuitem action='keyring-password'/>"\
+static const gchar* BACKEND_UI =
+"<ui>"
+"	<popup name='SeahorseGkrBackend'>"
+"		<menuitem action='gkr-keyring-new'/>"
 "	</popup>"\
 "</ui>";
 
@@ -89,6 +94,7 @@ seahorse_gkr_backend_actions_init (SeahorseGkrBackendActions *self)
 	GtkActionGroup *actions = GTK_ACTION_GROUP (self);
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
 	gtk_action_group_add_actions (actions, BACKEND_ACTIONS, G_N_ELEMENTS (BACKEND_ACTIONS), self);
+	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), BACKEND_UI);
 }
 
 static void
@@ -139,13 +145,6 @@ GType                      seahorse_gkr_keyring_actions_get_type               (
 G_DEFINE_TYPE (SeahorseGkrKeyringActions, seahorse_gkr_keyring_actions, SEAHORSE_TYPE_ACTIONS);
 
 static void
-on_gkr_add_item (GtkAction *action,
-                 gpointer unused)
-{
-	seahorse_gkr_add_item_show (seahorse_action_get_window (action));
-}
-
-static void
 on_keyring_unlock_done (GnomeKeyringResult result,
                         gpointer user_data)
 {
@@ -331,32 +330,42 @@ on_keyring_delete (GtkAction* action,
 
 
 static const GtkActionEntry KEYRING_ACTIONS[] = {
-	{ "keyring-lock", NULL, N_("_Lock"), "",
+	{ "gkr-keyring-lock", NULL, N_("_Lock"), "",
 	  N_("Lock the password storage keyring so a master password is required to unlock it."), G_CALLBACK (on_keyring_lock) },
-	{ "keyring-unlock", NULL, N_("_Unlock"), "",
+	{ "gkr-keyring-unlock", NULL, N_("_Unlock"), "",
 	  N_("Unlock the password storage keyring with a master password so it is available for use."), G_CALLBACK (on_keyring_unlock) },
-	{ "keyring-default", NULL, N_("_Set as default"), "",
+	{ "gkr-keyring-default", NULL, N_("_Set as default"), "",
 	  N_("Applications usually store new passwords in the default keyring."), G_CALLBACK (on_keyring_default) },
-	{ "keyring-password", NULL, N_("Change _Password"), "",
+	{ "gkr-keyring-password", NULL, N_("Change _Password"), "",
 	  N_("Change the unlock password of the password storage keyring"), G_CALLBACK (on_keyring_password) },
-	{ "properties", GTK_STOCK_PROPERTIES, NULL, NULL,
+	{ "gkr-keyring-properties", GTK_STOCK_PROPERTIES, NULL, NULL,
 	  N_("Properties of the keyring."), G_CALLBACK (on_keyring_properties) },
-	{ "delete", GTK_STOCK_DELETE, NULL, NULL,
+	{ "gkr-keyring-delete", GTK_STOCK_DELETE, NULL, NULL,
 	  N_("Delete the keyring."), G_CALLBACK (on_keyring_delete) },
-	{ "new-password", "emblem-readonly", N_("New password..."), "",
-	  N_("Safely store a password or secret."), G_CALLBACK (on_gkr_add_item) },
 };
 
+static const gchar* KEYRING_UI =
+"<ui>"
+"	<popup name='SeahorseGkrKeyring'>"
+"		<menuitem action='gkr-keyring-unlock'/>"
+"		<menuitem action='gkr-keyring-lock'/>"
+"		<menuitem action='gkr-keyring-default'/>"
+"		<menuitem action='gkr-keyring-password'/>"
+"		<menuitem action='gkr-keyring-delete'/>"
+"		<menuitem action='gkr-keyring-properties'/>"
+"	</popup>"\
+"</ui>";
+
 static void
 seahorse_gkr_keyring_actions_init (SeahorseGkrKeyringActions *self)
 {
 	GtkActionGroup *actions = GTK_ACTION_GROUP (self);
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
 	gtk_action_group_add_actions (actions, KEYRING_ACTIONS, G_N_ELEMENTS (KEYRING_ACTIONS), self);
-	self->action_lock = g_object_ref (gtk_action_group_get_action (actions, "keyring-lock"));
-	self->action_unlock = g_object_ref (gtk_action_group_get_action (actions, "keyring-unlock"));
-	self->action_default = g_object_ref (gtk_action_group_get_action (actions, "keyring-default"));
-	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), BACKEND_UI);
+	self->action_lock = g_object_ref (gtk_action_group_get_action (actions, "gkr-keyring-lock"));
+	self->action_unlock = g_object_ref (gtk_action_group_get_action (actions, "gkr-keyring-unlock"));
+	self->action_default = g_object_ref (gtk_action_group_get_action (actions, "gkr-keyring-default"));
+	seahorse_actions_register_definition (SEAHORSE_ACTIONS (self), KEYRING_UI);
 }
 
 static void
diff --git a/libseahorse/seahorse-actions.c b/libseahorse/seahorse-actions.c
index 31465c6..50abfd1 100644
--- a/libseahorse/seahorse-actions.c
+++ b/libseahorse/seahorse-actions.c
@@ -44,6 +44,15 @@ seahorse_actions_init (SeahorseActions *self)
 	                                         SeahorseActionsPrivate));
 }
 
+GtkActionGroup *
+seahorse_actions_new (const gchar *name)
+{
+	g_return_val_if_fail (name != NULL, NULL);
+	return g_object_new (SEAHORSE_TYPE_ACTIONS,
+	                     "name", name,
+	                     NULL);
+}
+
 static void
 seahorse_actions_class_init (SeahorseActionsClass *klass)
 {
diff --git a/libseahorse/seahorse-actions.h b/libseahorse/seahorse-actions.h
index 34b3f3a..c67c101 100644
--- a/libseahorse/seahorse-actions.h
+++ b/libseahorse/seahorse-actions.h
@@ -53,7 +53,7 @@ struct _SeahorseActionsClass {
 
 GType                 seahorse_actions_get_type                 (void);
 
-SeahorseViewer *      seahorse_actions_get_viewer               (SeahorseActions *self);
+GtkActionGroup *      seahorse_actions_new                      (const gchar *name);
 
 const gchar *         seahorse_actions_get_definition           (SeahorseActions *self);
 
diff --git a/libseahorse/seahorse-viewer.c b/libseahorse/seahorse-viewer.c
index c951bc2..79849b6 100644
--- a/libseahorse/seahorse-viewer.c
+++ b/libseahorse/seahorse-viewer.c
@@ -733,23 +733,29 @@ seahorse_viewer_include_actions (SeahorseViewer* self,
 
 void
 seahorse_viewer_show_context_menu (SeahorseViewer* self,
-                                   const gchar *which,
+                                   const gchar *name,
                                    guint button,
                                    guint time)
 {
-	GtkMenu* menu;
+	GtkWidget *menu;
+	gchar *path;
 
 	g_return_if_fail (SEAHORSE_IS_VIEWER (self));
-	g_return_if_fail (which != NULL);
+	g_return_if_fail (name != NULL);
 
-	menu = GTK_MENU (gtk_ui_manager_get_widget (self->pv->ui_manager, which));
+	path = g_strdup_printf ("/%s", name);
+	menu = gtk_ui_manager_get_widget (self->pv->ui_manager, path);
+	g_free (path);
+
+	if (menu == NULL)
+		return;
 	if (!GTK_IS_MENU (menu)) {
-		g_warning ("couldn't find menu '%s' in UI", which);
+		g_warning ("the object /%s isn't a menu", name);
 		return;
 	}
 
-	gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, time);
-	gtk_widget_show (GTK_WIDGET (menu));
+	gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, button, time);
+	gtk_widget_show (menu);
 }
 
 void
diff --git a/libseahorse/seahorse-viewer.h b/libseahorse/seahorse-viewer.h
index 5ced3c6..4a6508b 100644
--- a/libseahorse/seahorse-viewer.h
+++ b/libseahorse/seahorse-viewer.h
@@ -26,9 +26,7 @@
 
 #include "seahorse-widget.h"
 
-#define SEAHORSE_VIEWER_MENU_BACKEND  "/BackendPopup"
-#define SEAHORSE_VIEWER_MENU_OBJECT   "/ObjectPopup"
-#define SEAHORSE_VIEWER_MENU_PLACE    "/PlacePopup"
+#define SEAHORSE_VIEWER_MENU_OBJECT   "ObjectPopup"
 
 #define SEAHORSE_TYPE_VIEWER               (seahorse_viewer_get_type ())
 #define SEAHORSE_VIEWER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_VIEWER, SeahorseViewer))
diff --git a/src/seahorse-key-manager.c b/src/seahorse-key-manager.c
index b6d8324..c7cc1ba 100644
--- a/src/seahorse-key-manager.c
+++ b/src/seahorse-key-manager.c
@@ -489,6 +489,19 @@ on_sidebar_panes_size_allocate (GtkWidget *widget,
 	}
 }
 
+static void
+on_sidebar_popup_menu (SeahorseSidebar *sidebar,
+                       GcrCollection *collection,
+                       gpointer user_data)
+{
+	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (user_data);
+	const gchar *name;
+
+	name = G_OBJECT_TYPE_NAME (collection);
+	seahorse_viewer_show_context_menu (SEAHORSE_VIEWER (self), name,
+	                                   0, gtk_get_current_event_time ());
+}
+
 static GcrCollection *
 setup_sidebar (SeahorseKeyManager *self)
 {
@@ -526,6 +539,7 @@ setup_sidebar (SeahorseKeyManager *self)
 	panes = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "sidebar-panes");
 	gtk_paned_set_position (GTK_PANED (panes), self->pv->sidebar_width);
 	g_signal_connect (self->pv->sidebar, "size_allocate", G_CALLBACK (on_sidebar_panes_size_allocate), self);
+	g_signal_connect (self->pv->sidebar, "context-menu", G_CALLBACK (on_sidebar_popup_menu), self);
 
 	return seahorse_sidebar_get_collection (self->pv->sidebar);
 }
diff --git a/src/seahorse-key-manager.ui b/src/seahorse-key-manager.ui
index ba582de..b5815e9 100644
--- a/src/seahorse-key-manager.ui
+++ b/src/seahorse-key-manager.ui
@@ -30,24 +30,15 @@
 		</menu>
 
 	</menubar>
-  
+
 	<toolbar name="MainToolbar">
 		<toolitem action="properties-object"/>
 	</toolbar>
-	
+
 	<popup name="ObjectPopup">
 		<menuitem action="properties-object"/>
 		<separator/>
 		<menuitem action="edit-delete"/>
 		<separator/>
 	</popup>
-
-	<popup name="PlacePopup">
-		<menuitem action="properties-object"/>
-	</popup>
-
-	<popup name="BackendPopup">
-		<menuitem action="properties-object"/>
-	</popup>
-
 </ui>
diff --git a/src/seahorse-sidebar.c b/src/seahorse-sidebar.c
index a59b52a..bfe0465 100644
--- a/src/seahorse-sidebar.c
+++ b/src/seahorse-sidebar.c
@@ -23,6 +23,8 @@
 
 #include "seahorse-sidebar.h"
 
+#include "seahorse-backend.h"
+#include "seahorse-place.h"
 #include "seahorse-registry.h"
 
 #include "gkr/seahorse-gkr.h"
@@ -92,6 +94,13 @@ static GType column_types[] = {
 	G_TYPE_STRING,
 };
 
+enum {
+	CONTEXT_MENU,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
 G_DEFINE_TYPE (SeahorseSidebar, seahorse_sidebar, GTK_TYPE_SCROLLED_WINDOW);
 
 static void
@@ -747,6 +756,66 @@ on_checked_toggled  (GtkCellRendererToggle *renderer,
 }
 
 static void
+on_tree_view_popup_menu (GtkWidget *widget,
+                         gpointer user_data)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
+	GtkTreeModel *model = GTK_TREE_MODEL (self->store);
+	GcrCollection *collection;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+
+	gtk_tree_view_get_cursor (self->tree_view, &path, NULL);
+	if (path == NULL)
+		return;
+
+	if (!gtk_tree_model_get_iter (model, &iter, path))
+		g_return_if_reached ();
+	gtk_tree_path_free (path);
+
+	gtk_tree_model_get (model, &iter,
+	                    SIDEBAR_COLLECTION, &collection,
+	                    -1);
+
+	g_signal_emit (self, signals[CONTEXT_MENU], 0, collection);
+
+	g_clear_object (&collection);
+}
+
+static gboolean
+on_tree_view_button_press_event (GtkWidget *widget,
+                                 GdkEventButton *event,
+                                 gpointer user_data)
+{
+	SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
+	GtkTreeModel *model = GTK_TREE_MODEL (self->store);
+	GcrCollection *collection;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+
+	if (event->button != 3 || event->type != GDK_BUTTON_PRESS)
+		return FALSE;
+
+	if (!gtk_tree_view_get_path_at_pos (self->tree_view, event->x, event->y,
+	                                    &path, NULL, NULL, NULL))
+		return FALSE;
+
+	gtk_tree_view_set_cursor (self->tree_view, path, NULL, FALSE);
+	if (!gtk_tree_model_get_iter (model, &iter, path))
+		g_return_val_if_reached (FALSE);
+	gtk_tree_path_free (path);
+
+	gtk_tree_model_get (model, &iter,
+	                    SIDEBAR_COLLECTION, &collection,
+	                    -1);
+
+	g_signal_emit (self, signals[CONTEXT_MENU], 0, collection);
+
+	g_clear_object (&collection);
+	return TRUE;
+}
+
+static void
 seahorse_sidebar_constructed (GObject *obj)
 {
 	SeahorseSidebar *self = SEAHORSE_SIDEBAR (obj);
@@ -847,6 +916,8 @@ seahorse_sidebar_constructed (GObject *obj)
 	gtk_tree_view_set_tooltip_column (tree_view, SIDEBAR_TOOLTIP);
 	gtk_tree_view_set_search_column (tree_view, SIDEBAR_LABEL);
 	gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (self->store));
+	g_signal_connect (tree_view, "popup-menu", G_CALLBACK (on_tree_view_popup_menu), self);
+	g_signal_connect (tree_view, "button-press-event", G_CALLBACK (on_tree_view_button_press_event), self);
 
 	gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (tree_view));
 	gtk_widget_show (GTK_WIDGET (tree_view));
@@ -968,6 +1039,10 @@ seahorse_sidebar_class_init (SeahorseSidebarClass *klass)
 	g_object_class_install_property (gobject_class, PROP_SELECTED_URIS,
 	        g_param_spec_boxed ("selected-uris", "Selected URIs", "URIs selected by the user",
 	                            G_TYPE_STRV, G_PARAM_READWRITE));
+
+	signals[CONTEXT_MENU] = g_signal_new ("context-menu", SEAHORSE_TYPE_SIDEBAR,
+	                                      G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL,
+	                                      G_TYPE_NONE, 1, GCR_TYPE_COLLECTION);
 }
 
 SeahorseSidebar *
@@ -1042,14 +1117,47 @@ seahorse_sidebar_set_selected_uris (SeahorseSidebar *self,
 GList *
 seahorse_sidebar_get_selected_places (SeahorseSidebar *self)
 {
+	GcrCollection *collection;
+	GtkTreePath *path;
+	RowType row_type;
+	GtkTreeIter iter;
+	GList *places;
+
 	g_return_val_if_fail (SEAHORSE_IS_SIDEBAR (self), NULL);
-	return gcr_union_collection_elements (self->objects);
+
+	places = gcr_union_collection_elements (self->objects);
+
+	gtk_tree_view_get_cursor (self->tree_view, &path, NULL);
+	if (path != NULL) {
+		if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (self->store), &iter, path))
+			g_return_val_if_reached (NULL);
+		gtk_tree_model_get (GTK_TREE_MODEL (self->store), &iter,
+		                    SIDEBAR_ROW_TYPE, &row_type,
+		                    SIDEBAR_COLLECTION, &collection,
+		                    -1);
+
+		if (collection != NULL) {
+			if (row_type == TYPE_PLACE) {
+				places = g_list_remove (places, collection);
+				places = g_list_prepend (places, collection);
+			}
+			g_object_unref (collection);
+		}
+
+		gtk_tree_path_free (path);
+	}
+
+	return places;
 }
 
 GList *
 seahorse_sidebar_get_backends (SeahorseSidebar *self)
 {
 	GList *backends = NULL;
+	GcrCollection *collection;
+	GtkTreePath *path;
+	RowType row_type;
+	GtkTreeIter iter;
 	guint i;
 
 	g_return_val_if_fail (SEAHORSE_IS_SIDEBAR (self), NULL);
@@ -1057,5 +1165,27 @@ seahorse_sidebar_get_backends (SeahorseSidebar *self)
 	for (i = 0; i < self->backends->len; i++)
 		backends = g_list_prepend (backends, self->backends->pdata[i]);
 
-	return g_list_reverse (backends);
+	backends = g_list_reverse (backends);
+
+	gtk_tree_view_get_cursor (self->tree_view, &path, NULL);
+	if (path != NULL) {
+		if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (self->store), &iter, path))
+			g_return_val_if_reached (NULL);
+		gtk_tree_model_get (GTK_TREE_MODEL (self->store), &iter,
+		                    SIDEBAR_ROW_TYPE, &row_type,
+		                    SIDEBAR_COLLECTION, &collection,
+		                    -1);
+
+		if (collection != NULL) {
+			if (row_type == TYPE_BACKEND) {
+				backends = g_list_remove (backends, collection);
+				backends = g_list_prepend (backends, collection);
+			}
+			g_object_unref (collection);
+		}
+
+		gtk_tree_path_free (path);
+	}
+
+	return backends;
 }



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