[seahorse/refactor: 11/33] Make the main key manager view reflect what's in the side pane.



commit 05c1e46d0c53be1cdb3d5ce1d9e39c5f477bc258
Author: Stef Walter <stefw collabora co uk>
Date:   Fri Sep 9 13:53:54 2011 +0200

    Make the main key manager view reflect what's in the side pane.

 src/seahorse-key-manager.c   |  296 +++++-------------------------------------
 src/seahorse-key-manager.xml |  111 ++---------------
 src/seahorse-sidebar.c       |  232 ++++++++++++++++++++-------------
 src/seahorse-sidebar.h       |    2 +
 4 files changed, 188 insertions(+), 453 deletions(-)
---
diff --git a/src/seahorse-key-manager.c b/src/seahorse-key-manager.c
index 926facb..5f057f3 100644
--- a/src/seahorse-key-manager.c
+++ b/src/seahorse-key-manager.c
@@ -57,25 +57,16 @@ void           on_keymanager_import_button              (GtkButton* button,
 
 enum {
 	PROP_0,
-	PROP_SOURCES,
 	PROP_SELECTED
 };
-typedef struct _TabInfo {
-	guint id;
-	gint page;
-	GtkTreeView* view;
-	SeahorseCollection *collection;
-	GtkWidget* widget;
-	SeahorseKeyManagerStore* store;
-} TabInfo;
 
 struct _SeahorseKeyManagerPrivate {
-	GcrCollection *sources;
-	GcrUnionCollection *collection;
-	GtkNotebook* notebook;
 	GtkActionGroup* view_actions;
 	GtkEntry* filter_entry;
-	TabInfo* tabs;
+
+	GtkTreeView* view;
+	GcrCollection *collection; /* owned by the sidebar */
+	SeahorseKeyManagerStore* store;
 
 	GSettings *settings;
 	gint sidebar_width;
@@ -87,102 +78,12 @@ enum  {
 	TARGETS_URIS
 };
 
-enum  {
-	TAB_PUBLIC = 0,
-	TAB_PRIVATE,
-	TAB_PASSWORD,
-	TAB_NUM_TABS
-} SeahorseKeyManagerTabs;
-
-static SeahorsePredicate pred_public = {
-	0,
-	SEAHORSE_USAGE_PUBLIC_KEY, 
-	0, 
-	0, 
-	NULL
-};
-
-static SeahorsePredicate pred_private = {
-	0,
-	SEAHORSE_USAGE_PRIVATE_KEY, 
-	0, 
-	0, 
-	NULL
-};
-
-static SeahorsePredicate pred_password = {
-	0, /* type filled in later */
-	0, 
-	0, 
-	0, 
-	NULL
-};
-
 G_DEFINE_TYPE (SeahorseKeyManager, seahorse_key_manager, SEAHORSE_TYPE_VIEWER);
 
 /* -----------------------------------------------------------------------------
  * INTERNAL 
  */
 
-static TabInfo* 
-get_tab_for_object (SeahorseKeyManager* self, SeahorseObject* obj) 
-{
-	gint i;
-	
-	g_return_val_if_fail (SEAHORSE_IS_KEY_MANAGER (self), NULL);
-	g_return_val_if_fail (SEAHORSE_IS_OBJECT (obj), NULL);
-	
-	for (i = 0; i < TAB_NUM_TABS; ++i) {
-		TabInfo* tab = &self->pv->tabs[i];
-		if (gcr_collection_contains (GCR_COLLECTION (tab->collection),
-		                             G_OBJECT (obj)))
-			return tab;
-	}
-	
-	return NULL;
-}
-
-static TabInfo* 
-get_tab_info (SeahorseKeyManager* self, gint page) 
-{
-	gint i;
-	
-	g_return_val_if_fail (SEAHORSE_IS_KEY_MANAGER (self), NULL);
-
-	if (page < 0) 
-		page = gtk_notebook_get_current_page (self->pv->notebook);
-	if (page < 0)
-		return NULL;
-
-	for (i = 0; i < TAB_NUM_TABS; ++i)
-	{
-		TabInfo* tab = &self->pv->tabs[i];
-		if (tab->page == page)
-			return tab;
-	}
-
-	return NULL;
-}
-
-static GtkTreeView* 
-get_current_view (SeahorseKeyManager* self) 
-{
-	TabInfo* tab;
-	g_return_val_if_fail (SEAHORSE_IS_KEY_MANAGER (self), NULL);
-	tab = get_tab_info (self, -1);
-	if (tab == NULL)
-		return NULL;
-	return tab->view;
-}
-
-static void 
-set_tab_current (SeahorseKeyManager* self, TabInfo* tab) 
-{
-	g_return_if_fail (SEAHORSE_IS_KEY_MANAGER (self));
-	gtk_notebook_set_current_page (self->pv->notebook, tab->page);
-	g_signal_emit_by_name (G_OBJECT (SEAHORSE_VIEW (self)), "selection-changed");
-}
-
 static gboolean 
 fire_selection_changed (gpointer user_data)
 {
@@ -196,16 +97,6 @@ fire_selection_changed (gpointer user_data)
 }
 
 static void 
-on_tab_changed (GtkNotebook* notebook, void* unused, guint page_num, SeahorseKeyManager* self) 
-{
-	g_return_if_fail (SEAHORSE_IS_KEY_MANAGER (self));
-	g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
-	gtk_entry_set_text (self->pv->filter_entry, "");
-
-	fire_selection_changed (self);
-}
-
-static void 
 on_view_selection_changed (GtkTreeSelection* selection, SeahorseKeyManager* self) 
 {
 	g_return_if_fail (SEAHORSE_IS_KEY_MANAGER (self));
@@ -271,42 +162,7 @@ on_keymanager_new_button (GtkButton* button, SeahorseKeyManager* self)
 	seahorse_generate_select_show (seahorse_viewer_get_window (SEAHORSE_VIEWER (self)));
 }
 
-static void 
-initialize_tab (SeahorseKeyManager* self, const char* tabwidget, guint tabid, const char* viewwidget, 
-                const SeahorsePredicate* pred)
-{
-	SeahorseCollection *collection;
-	GtkTreeSelection *selection;
-	GtkTreeView *view;
-	
-	g_assert (tabid < (int)TAB_NUM_TABS);
-	
-	self->pv->tabs[tabid].id = tabid;
-	self->pv->tabs[tabid].widget = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), tabwidget);
-	g_return_if_fail (self->pv->tabs[tabid].widget != NULL);
-	
-	self->pv->tabs[tabid].page = gtk_notebook_page_num (self->pv->notebook, self->pv->tabs[tabid].widget);
-	g_return_if_fail (self->pv->tabs[tabid].page >= 0);
-
-	collection = seahorse_collection_new_for_predicate (GCR_COLLECTION (self->pv->collection),
-	                                                    (SeahorsePredicate*)pred, NULL);
-	self->pv->tabs[tabid].collection = SEAHORSE_COLLECTION (collection);
-
-	/* Init key list & selection settings */
-	view = GTK_TREE_VIEW (seahorse_widget_get_widget (SEAHORSE_WIDGET (self), viewwidget));
-	self->pv->tabs[tabid].view = view;
-	g_return_if_fail (view != NULL);
-	
-	selection = gtk_tree_view_get_selection (view);
-	gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
-	g_signal_connect (selection, "changed", G_CALLBACK (on_view_selection_changed), self);
-	gtk_widget_realize (GTK_WIDGET (view));
-
-	/* Add new key store and associate it */
-	self->pv->tabs[tabid].store = seahorse_key_manager_store_new (GCR_COLLECTION (collection),
-	                                                              view, self->pv->settings);
-}
-
+#if REFACTOR_FIRST
 static gboolean 
 on_first_timer (SeahorseKeyManager* self) 
 {
@@ -326,6 +182,7 @@ on_first_timer (SeahorseKeyManager* self)
 	
 	return FALSE;
 }
+#endif
 
 static void
 on_clear_clicked (GtkEntry* entry, GtkEntryIconPosition icon_pos, GdkEvent* event, gpointer user_data)
@@ -337,14 +194,12 @@ static void
 on_filter_changed (GtkEntry* entry, SeahorseKeyManager* self) 
 {
 	const gchar *text;
-	gint i;
 
 	g_return_if_fail (SEAHORSE_IS_KEY_MANAGER (self));
 	g_return_if_fail (GTK_IS_ENTRY (entry));
 
 	text = gtk_entry_get_text (entry);
-	for (i = 0; i < TAB_NUM_TABS; ++i)
-		g_object_set (self->pv->tabs[i].store, "filter", text, NULL);
+	g_object_set (self->pv->store, "filter", text, NULL);
 }
 
 #ifdef REFACTOR_IMPORT
@@ -682,71 +537,22 @@ static GList*
 seahorse_key_manager_get_selected_objects (SeahorseViewer* base) 
 {
 	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (base); 
-	TabInfo* tab = get_tab_info (self, -1);
-	if (tab == NULL)
-		return NULL;
-	return seahorse_key_manager_store_get_selected_objects (tab->view);
+	return seahorse_key_manager_store_get_selected_objects (self->pv->view);
 }
 
 static void 
 seahorse_key_manager_set_selected_objects (SeahorseViewer* base, GList* objects) 
 {
 	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (base);
-	GList** tab_lists;
-	GList *l;
-	gint i;
-	guint highest_matched;
-	TabInfo* highest_tab;
-
-	tab_lists = g_new0 (GList*, TAB_NUM_TABS + 1);
-	
-	/* Break objects into what's on each tab */
-	for (l = objects; l; l = g_list_next (l)) {
-		SeahorseObject* obj = SEAHORSE_OBJECT (l->data);
-		TabInfo* tab = get_tab_for_object (self, obj);
-		if (tab == NULL) 
-			continue;
+	seahorse_key_manager_store_set_selected_objects (self->pv->view, objects);
 
-		g_assert (tab->id < TAB_NUM_TABS);
-		tab_lists[tab->id] = g_list_prepend (tab_lists[tab->id], obj);
-	}
-	
-	highest_matched = 0;
-	highest_tab = NULL;
-	
-	for (i = 0; i < TAB_NUM_TABS; ++i) {
-		GList* list = tab_lists[i];
-		TabInfo* tab = &self->pv->tabs[i];
-
-		/* Save away the tab that had the most objects */
-		guint num = g_list_length (list);
-		if (num > highest_matched) {
-			highest_matched = num;
-			highest_tab = tab;
-		}
-		
-		/* Select the objects on that tab */
-		seahorse_key_manager_store_set_selected_objects (tab->view, list);
-		
-		/* Free the broken down list */
-		g_list_free (list);
-	}
-	
-	g_free (tab_lists);
-	
-	/* Change to the tab with the most objects */
-	if (highest_tab != NULL)
-		set_tab_current (self, highest_tab);
 }
 
 static SeahorseObject* 
 seahorse_key_manager_get_selected (SeahorseViewer* base) 
 {
 	SeahorseKeyManager* self = SEAHORSE_KEY_MANAGER (base);
-	TabInfo* tab = get_tab_info (self, -1);
-	if (tab == NULL)
-		return NULL;
-	return seahorse_key_manager_store_get_selected_object (tab->view);
+	return seahorse_key_manager_store_get_selected_object (self->pv->view);
 }
 
 static void 
@@ -789,7 +595,7 @@ on_sidebar_panes_size_allocate (GtkWidget *widget,
 	}
 }
 
-static void
+static GcrCollection *
 setup_sidebar (SeahorseKeyManager *self)
 {
 	SeahorseSidebar *sidebar;
@@ -804,6 +610,8 @@ setup_sidebar (SeahorseKeyManager *self)
 	widget = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "sidebar-panes");
 	gtk_paned_set_position (GTK_PANED (widget), self->pv->sidebar_width);
 	g_signal_connect (sidebar, "size_allocate", G_CALLBACK (on_sidebar_panes_size_allocate), self);
+
+	return seahorse_sidebar_get_collection (sidebar);
 }
 
 static void
@@ -813,15 +621,13 @@ seahorse_key_manager_constructed (GObject *object)
 	GtkActionGroup* actions;
 	GtkToggleAction* action;
 	GtkTargetList* targets;
+	GtkTreeSelection *selection;
 	GtkWidget* widget;
 
 	G_OBJECT_CLASS (seahorse_key_manager_parent_class)->constructed (object);
 
-	setup_sidebar (self);
-
-	self->pv->tabs = g_new0 (TabInfo, TAB_NUM_TABS);
+	self->pv->collection = setup_sidebar (self);
 
-	self->pv->notebook = GTK_NOTEBOOK (seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "notebook"));
 	gtk_window_set_title (seahorse_viewer_get_window (SEAHORSE_VIEWER (self)), _("Passwords and Keys"));
 	
 	actions = gtk_action_group_new ("general");
@@ -855,10 +661,7 @@ seahorse_key_manager_constructed (GObject *object)
 
 	g_signal_connect_object (seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "new-button"), 
 	                         "clicked", G_CALLBACK (on_keymanager_new_button), self, 0);
-	
-	/* The notebook */
-	g_signal_connect_object (self->pv->notebook, "switch-page", G_CALLBACK (on_tab_changed), self, G_CONNECT_AFTER);
-	
+
 	/* Flush all updates */
 	seahorse_viewer_ensure_updated (SEAHORSE_VIEWER (self));
 	
@@ -925,17 +728,24 @@ seahorse_key_manager_constructed (GObject *object)
 	/* For the filtering */
 	g_signal_connect_object (GTK_EDITABLE (self->pv->filter_entry), "changed", 
 	                         G_CALLBACK (on_filter_changed), self, 0);
-	
-	/* Initialize the tabs, and associate them up */
-	initialize_tab (self, "pub-key-tab", TAB_PUBLIC, "pub-key-list", &pred_public);
-	initialize_tab (self, "sec-key-tab", TAB_PRIVATE, "sec-key-list", &pred_private);
-	pred_password.type = SEAHORSE_TYPE_GKR_KEYRING;
-	initialize_tab (self, "password-tab", TAB_PASSWORD, "password-list", &pred_password);
-	
+
+
+	/* Init key list & selection settings */
+	self->pv->view = GTK_TREE_VIEW (seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "key-list"));
+	g_return_if_fail (self->pv->view != NULL);
+
+	selection = gtk_tree_view_get_selection (self->pv->view);
+	gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+	g_signal_connect (selection, "changed", G_CALLBACK (on_view_selection_changed), self);
+	gtk_widget_realize (GTK_WIDGET (self->pv->view));
+
+	/* Add new key store and associate it */
+	self->pv->store = seahorse_key_manager_store_new (self->pv->collection,
+	                                                  self->pv->view,
+	                                                  self->pv->settings);
+
 	/* Set focus to the current key list */
-	widget = GTK_WIDGET (get_current_view (self));
 	gtk_widget_grab_focus (widget);
-
 	g_signal_emit_by_name (self, "selection-changed");
 
 	/* To avoid flicker */
@@ -954,8 +764,10 @@ seahorse_key_manager_constructed (GObject *object)
 	                         G_CALLBACK (on_target_drag_data_received), self, 0);
 #endif
 
+#ifdef REFACTOR_FIRST
 	/* To show first time dialog */
 	g_timeout_add_seconds (1, (GSourceFunc)on_first_timer, self);
+#endif
 }
 
 static void
@@ -963,14 +775,12 @@ seahorse_key_manager_init (SeahorseKeyManager *self)
 {
 	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_KEY_MANAGER, SeahorseKeyManagerPrivate);
 	self->pv->settings = g_settings_new ("org.gnome.seahorse.manager");
-	self->pv->collection = GCR_UNION_COLLECTION (gcr_union_collection_new ());
 }
 
 static void
 seahorse_key_manager_finalize (GObject *obj)
 {
 	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (obj);
-	gint i;
 
 	if (self->pv->sidebar_width_sig != 0) {
 		g_source_remove (self->pv->sidebar_width_sig);
@@ -982,19 +792,8 @@ seahorse_key_manager_finalize (GObject *obj)
 	self->pv->view_actions = NULL;
 	
 	self->pv->filter_entry = NULL;
-	
-	if (self->pv->tabs) {
-		for (i = 0; i < TAB_NUM_TABS; ++i) {
-			g_clear_object (&self->pv->tabs[i].store);
-			g_clear_object (&self->pv->tabs[i].collection);
-		}
-		g_free (self->pv->tabs);
-		self->pv->tabs = NULL;
-	}
 
 	g_clear_object (&self->pv->settings);
-	g_object_unref (self->pv->collection);
-	g_clear_object (&self->pv->sources);
 
 	G_OBJECT_CLASS (seahorse_key_manager_parent_class)->finalize (obj);
 }
@@ -1004,17 +803,8 @@ seahorse_key_manager_set_property (GObject *obj, guint prop_id, const GValue *va
                            GParamSpec *pspec)
 {
 	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (obj);
-	GList *collections, *l;
 
 	switch (prop_id) {
-	case PROP_SOURCES:
-		g_return_if_fail (self->pv->sources == NULL);
-		self->pv->sources = g_value_dup_object (value);
-		collections = gcr_collection_get_objects (self->pv->sources);
-		for (l = collections; l != NULL; l = g_list_next (l))
-			gcr_union_collection_add (self->pv->collection, l->data);
-		g_list_free (collections);
-		break;
 	case PROP_SELECTED:
 		seahorse_viewer_set_selected (SEAHORSE_VIEWER (self), g_value_get_object (value));
 		break;
@@ -1031,9 +821,6 @@ seahorse_key_manager_get_property (GObject *obj, guint prop_id, GValue *value,
 	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (obj);
 
 	switch (prop_id) {
-	case PROP_SOURCES:
-		g_value_set_object (value, self->pv->sources);
-		break;
 	case PROP_SELECTED:
 		g_value_set_object (value, seahorse_viewer_get_selected (SEAHORSE_VIEWER (self)));
 		break;
@@ -1061,10 +848,6 @@ seahorse_key_manager_class_init (SeahorseKeyManagerClass *klass)
 	SEAHORSE_VIEWER_CLASS (klass)->get_selected = seahorse_key_manager_get_selected;
 	SEAHORSE_VIEWER_CLASS (klass)->set_selected = seahorse_key_manager_set_selected;
 
-	g_object_class_install_property (gobject_class, PROP_SOURCES,
-	               g_param_spec_object ("sources", "Sources" , "Collection of Sources",
-	                                    GCR_TYPE_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
 	g_object_class_override_property (gobject_class, PROP_SELECTED, "selected");
 }
 
@@ -1077,22 +860,11 @@ SeahorseWidget *
 seahorse_key_manager_show (void)
 {
 	SeahorseKeyManager *self;
-	GcrUnionCollection *sources;
-	GList *backends, *l;
-
-	sources = GCR_UNION_COLLECTION (gcr_union_collection_new ());
-
-	backends = seahorse_registry_object_instances (NULL, "backend", NULL);
-	for (l = backends; l != NULL; l = g_list_next (l))
-		gcr_union_collection_take (sources, GCR_COLLECTION (l->data));
-	g_list_free (backends);
 
 	self = g_object_new (SEAHORSE_TYPE_KEY_MANAGER,
 	                     "name", "key-manager",
-	                     "sources", sources,
 	                     NULL);
 
-	g_object_unref (sources);
 	g_object_ref_sink (self);
 
 	return SEAHORSE_WIDGET (self);
diff --git a/src/seahorse-key-manager.xml b/src/seahorse-key-manager.xml
index 77285f8..c495028 100644
--- a/src/seahorse-key-manager.xml
+++ b/src/seahorse-key-manager.xml
@@ -61,116 +61,23 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkNotebook" id="notebook">
+                  <object class="GtkScrolledWindow" id="key-list-scroll-area">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="border_width">3</property>
                     <child>
-                      <object class="GtkScrolledWindow" id="password-tab">
+                      <object class="GtkTreeView" id="key-list">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="border_width">3</property>
-                        <child>
-                          <object class="GtkTreeView" id="password-list">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="border_width">12</property>
-                            <property name="rules_hint">True</property>
-                            <signal name="button-press-event" handler="on_keymanager_key_list_button_pressed" swapped="no"/>
-                            <signal name="row-activated" handler="on_keymanager_row_activated" swapped="no"/>
-                            <signal name="popup-menu" handler="on_keymanager_key_list_popup_menu" swapped="no"/>
-                            <child internal-child="selection">
-                              <object class="GtkTreeSelection" id="treeview-selection"/>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                    <child type="tab">
-                      <object class="GtkLabel" id="label29">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xpad">3</property>
-                        <property name="label" translatable="yes">_Passwords</property>
-                        <property name="use_underline">True</property>
-                      </object>
-                      <packing>
-                        <property name="tab_fill">False</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkScrolledWindow" id="sec-key-tab">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="border_width">3</property>
-                        <child>
-                          <object class="GtkTreeView" id="sec-key-list">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="border_width">12</property>
-                            <property name="rules_hint">True</property>
-                            <signal name="button-press-event" handler="on_keymanager_key_list_button_pressed" swapped="no"/>
-                            <signal name="row-activated" handler="on_keymanager_row_activated" swapped="no"/>
-                            <signal name="popup-menu" handler="on_keymanager_key_list_popup_menu" swapped="no"/>
-                            <child internal-child="selection">
-                              <object class="GtkTreeSelection" id="treeview-selection1"/>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                    <child type="tab">
-                      <object class="GtkLabel" id="label26">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xpad">3</property>
-                        <property name="label" translatable="yes">My _Personal Keys</property>
-                        <property name="use_underline">True</property>
-                      </object>
-                      <packing>
-                        <property name="position">1</property>
-                        <property name="tab_fill">False</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkScrolledWindow" id="pub-key-tab">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="border_width">3</property>
-                        <child>
-                          <object class="GtkTreeView" id="pub-key-list">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="border_width">12</property>
-                            <property name="rules_hint">True</property>
-                            <signal name="button-press-event" handler="on_keymanager_key_list_button_pressed" swapped="no"/>
-                            <signal name="row-activated" handler="on_keymanager_row_activated" swapped="no"/>
-                            <signal name="popup-menu" handler="on_keymanager_key_list_popup_menu" swapped="no"/>
-                            <child internal-child="selection">
-                              <object class="GtkTreeSelection" id="treeview-selection2"/>
-                            </child>
-                          </object>
+                        <property name="border_width">12</property>
+                        <property name="rules_hint">True</property>
+                        <signal name="button-press-event" handler="on_keymanager_key_list_button_pressed" swapped="no"/>
+                        <signal name="row-activated" handler="on_keymanager_row_activated" swapped="no"/>
+                        <signal name="popup-menu" handler="on_keymanager_key_list_popup_menu" swapped="no"/>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection" id="treeview-selection"/>
                         </child>
                       </object>
-                      <packing>
-                        <property name="position">2</property>
-                      </packing>
-                    </child>
-                    <child type="tab">
-                      <object class="GtkLabel" id="label28">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xpad">3</property>
-                        <property name="label" translatable="yes">Other _Keys</property>
-                        <property name="use_underline">True</property>
-                      </object>
-                      <packing>
-                        <property name="position">2</property>
-                        <property name="tab_fill">False</property>
-                      </packing>
                     </child>
                   </object>
                   <packing>
diff --git a/src/seahorse-sidebar.c b/src/seahorse-sidebar.c
index f4e7960..19cddf0 100644
--- a/src/seahorse-sidebar.c
+++ b/src/seahorse-sidebar.c
@@ -39,11 +39,11 @@ struct _SeahorseSidebar {
 
 	GtkListStore *store;
 	GPtrArray *backends;
+	GHashTable *checked;
+	GcrUnionCollection *objects;
+	GcrCollection *selected;
 
 	guint update_places_sig;
-
-	gint checks_checked;
-	GtkTreePath *selected_path;
 };
 
 struct _SeahorseSidebarClass {
@@ -52,12 +52,13 @@ struct _SeahorseSidebarClass {
 
 enum {
 	PROP_0,
+	PROP_COLLECTION
 };
 
 typedef enum {
-	PLACES_HEADING,
-	PLACES_COLLECTION,
-} PlaceType;
+	TYPE_BACKEND,
+	TYPE_PLACE,
+} RowType;
 
 enum {
 	SIDEBAR_ROW_TYPE,
@@ -67,7 +68,6 @@ enum {
 	SIDEBAR_EDITABLE,
 	SIDEBAR_CATEGORY,
 	SIDEBAR_COLLECTION,
-	SIDEBAR_CHECKED,
 	SIDEBAR_N_COLUMNS
 };
 
@@ -79,7 +79,6 @@ static GType column_types[] = {
 	G_TYPE_BOOLEAN,
 	G_TYPE_STRING,
 	0 /* later */,
-	G_TYPE_BOOLEAN,
 };
 
 G_DEFINE_TYPE (SeahorseSidebar, seahorse_sidebar, GTK_TYPE_SCROLLED_WINDOW);
@@ -93,7 +92,8 @@ seahorse_sidebar_init (SeahorseSidebar *self)
 	self->store = gtk_list_store_newv (SIDEBAR_N_COLUMNS, column_types);
 
 	self->backends = g_ptr_array_new_with_free_func (g_object_unref);
-
+	self->checked = g_hash_table_new (g_direct_hash, g_direct_equal);
+	self->objects = GCR_UNION_COLLECTION (gcr_union_collection_new ());
 }
 
 static void
@@ -176,7 +176,7 @@ update_backend (SeahorseSidebar *self,
 
 	next_or_append_row (self->store, iter, category, GCR_COLLECTION (backend));
 	gtk_list_store_set (self->store, iter,
-	                    SIDEBAR_ROW_TYPE, PLACES_HEADING,
+	                    SIDEBAR_ROW_TYPE, TYPE_BACKEND,
 	                    SIDEBAR_CATEGORY, category,
 	                    SIDEBAR_LABEL, label,
 	                    SIDEBAR_TOOLTIP, tooltip,
@@ -201,7 +201,7 @@ update_backend (SeahorseSidebar *self,
 
 		next_or_append_row (self->store, iter, category, l->data);
 		gtk_list_store_set (self->store, iter,
-		                    SIDEBAR_ROW_TYPE, PLACES_COLLECTION,
+		                    SIDEBAR_ROW_TYPE, TYPE_PLACE,
 		                    SIDEBAR_CATEGORY, category,
 		                    SIDEBAR_LABEL, label,
 		                    SIDEBAR_TOOLTIP, tooltip,
@@ -220,11 +220,80 @@ update_backend (SeahorseSidebar *self,
 }
 
 static void
+update_objects_for_selection (SeahorseSidebar *self,
+                              GtkTreeSelection *selection)
+{
+	GcrCollection *selected = NULL;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	if (gtk_tree_selection_get_selected (selection, &model, &iter))
+		gtk_tree_model_get (model, &iter,
+		                    SIDEBAR_COLLECTION, &selected,
+		                    -1);
+
+	if (selected != self->selected) {
+		if (self->selected && g_hash_table_size (self->checked) == 0)
+			gcr_union_collection_remove (self->objects, self->selected);
+
+		g_clear_object (&self->selected);
+		self->selected = selected ? g_object_ref (selected) : NULL;
+
+		if (self->selected && g_hash_table_size (self->checked) == 0)
+			gcr_union_collection_add (self->objects, self->selected);
+	}
+
+	g_clear_object (&selected);
+}
+
+static void
+update_objects_for_checked (SeahorseSidebar *self,
+                            GcrCollection *place)
+{
+	g_hash_table_insert (self->checked, place, place);
+
+	/* The first check ... */
+	if (g_hash_table_size (self->checked) == 1) {
+
+		/* ... but the currently checked one was selected so leave same */
+		if (self->selected == place)
+			return;
+
+		/* ... something else was selected, so update */
+		else if (self->selected)
+			gcr_union_collection_remove (self->objects, self->selected);
+	}
+
+	gcr_union_collection_add (self->objects, place);
+}
+
+static void
+update_objects_for_unchecked (SeahorseSidebar *self,
+                              GcrCollection *place)
+{
+	if (!g_hash_table_remove (self->checked, place))
+		g_assert_not_reached ();
+
+	/* No more checks ... */
+	if (g_hash_table_size (self->checked) == 0) {
+
+		/* ... but the currently unchecked one is selected so leave same ... */
+		if (self->selected == place)
+			return;
+
+		/* ... something else is selected, so update */
+		else if (self->selected)
+			gcr_union_collection_add (self->objects, self->selected);
+	}
+
+	gcr_union_collection_remove (self->objects, place);
+}
+
+static void
 update_places (SeahorseSidebar *self)
 {
 	GtkTreeSelection *selection;
 	GtkTreeIter iter;
-	GtkTreeModel *model;
 	guint i;
 
 	/* A marker that tells us the iter is not yet valid */
@@ -235,11 +304,8 @@ update_places (SeahorseSidebar *self)
 		update_backend (self, GCR_COLLECTION (self->backends->pdata[i]), &iter);
 
 	/* Update selection */
-	gtk_tree_path_free (self->selected_path);
-	self->selected_path = NULL;
 	selection = gtk_tree_view_get_selection (self->tree_view);
-	if (gtk_tree_selection_get_selected (selection, &model, &iter))
-		self->selected_path = gtk_tree_model_get_path (model, &iter);
+	update_objects_for_selection (self, selection);
 }
 
 static gboolean
@@ -267,12 +333,12 @@ on_cell_renderer_heading_visible (GtkTreeViewColumn *column,
                                   GtkTreeIter *iter,
                                   gpointer user_data)
 {
-	PlaceType type;
+	RowType type;
 	gtk_tree_model_get (model, iter,
 	                    SIDEBAR_ROW_TYPE, &type,
 	                    -1);
 	g_object_set (cell,
-	              "visible", (type == PLACES_HEADING),
+	              "visible", (type == TYPE_BACKEND),
 	              NULL);
 }
 
@@ -283,12 +349,12 @@ on_padding_cell_renderer (GtkTreeViewColumn *column,
                           GtkTreeIter *iter,
                           gpointer user_data)
 {
-	PlaceType type;
+	RowType type;
 	gtk_tree_model_get (model, iter,
 	                    SIDEBAR_ROW_TYPE, &type,
 	                    -1);
 
-	if (type == PLACES_HEADING) {
+	if (type == TYPE_BACKEND) {
 		g_object_set (cell,
 		              "visible", FALSE,
 		              "xpad", 0,
@@ -310,12 +376,12 @@ on_cell_renderer_heading_not_visible (GtkTreeViewColumn *column,
                                       GtkTreeIter *iter,
                                       gpointer user_data)
 {
-	PlaceType type;
+	RowType type;
 	gtk_tree_model_get (model, iter,
 	                    SIDEBAR_ROW_TYPE, &type,
 	                    -1);
 	g_object_set (cell,
-	              "visible", (type != PLACES_HEADING),
+	              "visible", (type != TYPE_BACKEND),
 	              NULL);
 }
 
@@ -327,29 +393,27 @@ on_cell_renderer_check (GtkTreeViewColumn *column,
                         gpointer user_data)
 {
 	SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
-	PlaceType type;
+	GcrCollection *collection;
+	RowType type;
 	gboolean active;
 	gboolean inconsistent;
 	gboolean visible;
-	GtkTreePath *only;
 
 	gtk_tree_model_get (model, iter,
 	                    SIDEBAR_ROW_TYPE, &type,
-	                    SIDEBAR_CHECKED, &active,
+	                    SIDEBAR_COLLECTION, &collection,
 	                    -1);
 
+	active = FALSE;
 	inconsistent = FALSE;
 
-	if (type == PLACES_HEADING) {
+	if (type == TYPE_BACKEND) {
 		visible = FALSE;
-	} else if (self->checks_checked > 0) {
+	} else if (collection != NULL && g_hash_table_size (self->checked) > 0) {
+		active = g_hash_table_lookup (self->checked, collection) != NULL;
 		visible = TRUE;
-	} else if (self->selected_path != NULL) {
-		only = gtk_tree_model_get_path (model, iter);
-		visible = gtk_tree_path_compare (only, self->selected_path) == 0;
-		gtk_tree_path_free (only);
 	} else {
-		visible = FALSE;
+		visible = (collection == self->selected);
 	}
 
 	/* self->mnemonics_visible */
@@ -358,6 +422,8 @@ on_cell_renderer_check (GtkTreeViewColumn *column,
 	              "active", active,
 	              "inconsistent", inconsistent,
 	              NULL);
+
+	g_clear_object (&collection);
 }
 
 static void
@@ -383,13 +449,13 @@ on_tree_selection_validate (GtkTreeSelection *selection,
                             gpointer user_data)
 {
 	GtkTreeIter iter;
-	PlaceType row_type;
+	RowType row_type;
 
 	gtk_tree_model_get_iter (model, &iter, path);
 	gtk_tree_model_get (model, &iter,
 	                    SIDEBAR_ROW_TYPE, &row_type,
 	                    -1);
-	if (row_type == PLACES_HEADING)
+	if (row_type == TYPE_BACKEND)
 		return FALSE;
 
 	return TRUE;
@@ -400,16 +466,8 @@ on_tree_selection_changed (GtkTreeSelection *selection,
                            gpointer user_data)
 {
 	SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-
-	gtk_tree_path_free (self->selected_path);
-	self->selected_path = NULL;
-
-	if (gtk_tree_selection_get_selected (selection, &model, &iter))
-		self->selected_path = gtk_tree_model_get_path (model, &iter);
-
-	invalidate_all_rows (model);
+	update_objects_for_selection (self, selection);
+	invalidate_all_rows (GTK_TREE_MODEL (self->store));
 }
 
 static void
@@ -508,31 +566,43 @@ load_backends (SeahorseSidebar *self)
 
 static void
 on_checked_toggled  (GtkCellRendererToggle *renderer,
-                     gchar *path,
+                     gchar *path_string,
                      gpointer user_data)
 {
 	SeahorseSidebar *self = SEAHORSE_SIDEBAR (user_data);
+	GcrCollection *collection;
+	GtkTreeModel *model;
 	GtkTreeIter iter;
+	GtkTreePath *path;
 	gboolean checked;
+	gboolean have;
 
-	if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (self->store), &iter, path))
-		g_return_if_reached ();
+	model = GTK_TREE_MODEL (self->store);
+	path = gtk_tree_path_new_from_string (path_string);
+	gtk_tree_model_get_iter (model, &iter, path);
 
 	checked = !gtk_cell_renderer_toggle_get_active (renderer);
-	gtk_list_store_set (self->store, &iter,
-	                    SIDEBAR_CHECKED, checked,
+	gtk_tree_model_get (model, &iter,
+	                    SIDEBAR_COLLECTION, &collection,
 	                    -1);
+	have = g_hash_table_lookup (self->checked, collection) != NULL;
 
-	if (checked) {
-		self->checks_checked++;
-		if (self->checks_checked == 1)
-			invalidate_all_rows (GTK_TREE_MODEL (self->store));
-	} else {
-		g_assert (self->checks_checked > 0);
-		self->checks_checked--;
-		if (self->checks_checked == 0)
-			invalidate_all_rows (GTK_TREE_MODEL (self->store));
+	if (checked && !have) {
+		update_objects_for_checked (self, collection);
+		if (g_hash_table_size (self->checked) == 1)
+			invalidate_all_rows (model);
+		else
+			gtk_tree_model_row_changed (model, path, &iter);
+	} else if (!checked && have) {
+		update_objects_for_unchecked (self, collection);
+		if (g_hash_table_size (self->checked) == 0)
+			invalidate_all_rows (model);
+		else
+			gtk_tree_model_row_changed (model, path, &iter);
 	}
+
+	g_object_unref (collection);
+	gtk_tree_path_free (path);
 }
 
 static void
@@ -649,8 +719,6 @@ seahorse_sidebar_constructed (GObject *obj)
 	load_backends (self);
 }
 
-#if 0
-
 static void
 seahorse_sidebar_get_property (GObject *obj,
                                guint prop_id,
@@ -660,8 +728,8 @@ seahorse_sidebar_get_property (GObject *obj,
 	SeahorseSidebar *self = SEAHORSE_SIDEBAR (obj);
 
 	switch (prop_id) {
-	case PROP_PLACES:
-		g_value_set_object (value, self->places);
+	case PROP_COLLECTION:
+		g_value_set_object (value, seahorse_sidebar_get_collection (self));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
@@ -670,26 +738,6 @@ seahorse_sidebar_get_property (GObject *obj,
 }
 
 static void
-seahorse_sidebar_set_property (GObject *obj,
-                               guint prop_id,
-                               const GValue *value,
-                               GParamSpec *pspec)
-{
-	SeahorseSidebar *self = SEAHORSE_SIDEBAR (obj);
-
-	switch (prop_id) {
-	case PROP_PLACES:
-		self->places = g_value_dup_object (value);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
-		break;
-	}
-}
-
-#endif
-
-static void
 seahorse_sidebar_dispose (GObject *obj)
 {
 	SeahorseSidebar *self = SEAHORSE_SIDEBAR (obj);
@@ -715,7 +763,9 @@ seahorse_sidebar_finalize (GObject *obj)
 {
 	SeahorseSidebar *self = SEAHORSE_SIDEBAR (obj);
 
-	gtk_tree_path_free (self->selected_path);
+	g_clear_object (&self->selected);
+	g_hash_table_destroy (self->checked);
+	g_object_unref (self->objects);
 
 	if (self->update_places_sig)
 		g_source_remove (self->update_places_sig);
@@ -734,14 +784,11 @@ seahorse_sidebar_class_init (SeahorseSidebarClass *klass)
 	gobject_class->constructed = seahorse_sidebar_constructed;
 	gobject_class->dispose = seahorse_sidebar_dispose;
 	gobject_class->finalize = seahorse_sidebar_finalize;
-#if 0
-	gobject_class->set_property = seahorse_sidebar_set_property;
 	gobject_class->get_property = seahorse_sidebar_get_property;
 
-	g_object_class_install_property (gobject_class, PROP_PLACES,
-	        g_param_spec_object ("places", "Places", "Places for Items",
-	                             GCR_TYPE_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-#endif
+	g_object_class_install_property (gobject_class, PROP_COLLECTION,
+	        g_param_spec_object ("collection", "Collection", "Collection of objects sidebar represents",
+	                             GCR_TYPE_COLLECTION, G_PARAM_READABLE));
 }
 
 SeahorseSidebar *
@@ -750,3 +797,10 @@ seahorse_sidebar_new (void)
 	return g_object_new (SEAHORSE_TYPE_SIDEBAR,
 	                     NULL);
 }
+
+GcrCollection *
+seahorse_sidebar_get_collection (SeahorseSidebar *self)
+{
+	g_return_val_if_fail (SEAHORSE_IS_SIDEBAR (self), NULL);
+	return GCR_COLLECTION (self->objects);
+}
diff --git a/src/seahorse-sidebar.h b/src/seahorse-sidebar.h
index e167e30..1bf994e 100644
--- a/src/seahorse-sidebar.h
+++ b/src/seahorse-sidebar.h
@@ -40,4 +40,6 @@ GType                        seahorse_sidebar_get_type           (void);
 
 SeahorseSidebar *            seahorse_sidebar_new                (void);
 
+GcrCollection *              seahorse_sidebar_get_collection     (SeahorseSidebar *self);
+
 #endif /* __SEAHORSE_SIDEBAR_H__ */



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