[seahorse/refactor: 31/33] Save the set of selected place in settings



commit 1bb3e5d47134b46e14c199ffb00aab07fd12cf18
Author: Stef Walter <stefw collabora co uk>
Date:   Fri Oct 14 12:34:48 2011 +0200

    Save the set of selected place in settings
    
     * Each place has a uri, and remember the set of chosen uris
       even when the uri is no longer present.

 data/org.gnome.seahorse.manager.gschema.xml |    5 +
 gkr/seahorse-gkr-keyring.c                  |   12 +-
 libseahorse/seahorse-source.c               |    4 +
 libseahorse/seahorse-source.h               |   10 -
 pgp/seahorse-gpgme-keyring.c                |    7 +-
 pgp/seahorse-server-source.c                |    4 +-
 pkcs11/seahorse-pkcs11-backend.c            |    2 +
 pkcs11/seahorse-token.c                     |   20 ++-
 src/seahorse-key-manager.c                  |   38 +++--
 src/seahorse-sidebar.c                      |  300 ++++++++++++++++++++-------
 src/seahorse-sidebar.h                      |    5 +
 ssh/seahorse-ssh-source.c                   |   12 +-
 12 files changed, 308 insertions(+), 111 deletions(-)
---
diff --git a/data/org.gnome.seahorse.manager.gschema.xml b/data/org.gnome.seahorse.manager.gschema.xml
index b6fa3f8..efd3e2f 100644
--- a/data/org.gnome.seahorse.manager.gschema.xml
+++ b/data/org.gnome.seahorse.manager.gschema.xml
@@ -16,6 +16,11 @@
 			<summary>Width of the side pane</summary>
 			<description>The default width of the side pane.</description>
 		</key>
+		<key name="places-selected" type="as">
+			<default>["secret-service://login"]</default>
+			<summary>The places chosen</summary>
+			<description>The URIs of the places chosen in the sidebar.</description>
+		</key>
 
 		<!-- Unused, remove once stable -->
 
diff --git a/gkr/seahorse-gkr-keyring.c b/gkr/seahorse-gkr-keyring.c
index 8a83ba4..5caab44 100644
--- a/gkr/seahorse-gkr-keyring.c
+++ b/gkr/seahorse-gkr-keyring.c
@@ -39,7 +39,8 @@ enum {
 	PROP_DESCRIPTION,
 	PROP_KEYRING_NAME,
 	PROP_KEYRING_INFO,
-	PROP_IS_DEFAULT
+	PROP_IS_DEFAULT,
+	PROP_URI,
 };
 
 struct _SeahorseGkrKeyringPrivate {
@@ -410,7 +411,8 @@ seahorse_gkr_keyring_get_property (GObject *obj, guint prop_id, GValue *value,
                            GParamSpec *pspec)
 {
 	SeahorseGkrKeyring *self = SEAHORSE_GKR_KEYRING (obj);
-	
+	gchar *text;
+
 	switch (prop_id) {
 	case PROP_DESCRIPTION:
 		g_value_set_string (value, seahorse_gkr_keyring_get_description (self));
@@ -424,6 +426,10 @@ seahorse_gkr_keyring_get_property (GObject *obj, guint prop_id, GValue *value,
 	case PROP_IS_DEFAULT:
 		g_value_set_boolean (value, seahorse_gkr_keyring_get_is_default (self));
 		break;
+	case PROP_URI:
+		text = g_strdup_printf ("secret-service://%s", self->pv->keyring_name);
+		g_value_take_string (value, text);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -444,6 +450,8 @@ seahorse_gkr_keyring_class_init (SeahorseGkrKeyringClass *klass)
 
 	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
 
+	g_object_class_override_property (gobject_class, PROP_URI, "uri");
+
 	g_object_class_install_property (gobject_class, PROP_KEYRING_NAME,
 	           g_param_spec_string ("keyring-name", "Gnome Keyring Name", "Name of keyring.", 
 	                                "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
diff --git a/libseahorse/seahorse-source.c b/libseahorse/seahorse-source.c
index 28b6603..dfd562e 100644
--- a/libseahorse/seahorse-source.c
+++ b/libseahorse/seahorse-source.c
@@ -64,6 +64,10 @@ seahorse_source_default_init (SeahorseSourceIface *iface)
 		                                "", G_PARAM_READABLE));
 
 		g_object_interface_install_property (iface,
+		           g_param_spec_string ("uri", "URI", "URI for the source",
+		                                "", G_PARAM_READABLE));
+
+		g_object_interface_install_property (iface,
 		           g_param_spec_object ("icon", "Icon", "Icon for this source",
 		                                G_TYPE_ICON, G_PARAM_READABLE));
 
diff --git a/libseahorse/seahorse-source.h b/libseahorse/seahorse-source.h
index 162b895..2f717c6 100644
--- a/libseahorse/seahorse-source.h
+++ b/libseahorse/seahorse-source.h
@@ -21,19 +21,9 @@
  */
  
 /**
- * SeahorseSource: Base class for other sources. 
- * 
  * - A generic interface for accessing sources.
  * - Eventually more functionality will be merged from seahorse-op.* into 
  *   this class and derived classes. 
- * 
- * Properties base classes must implement:
- *  ktype: (GQuark) The ktype (ie: SEAHORSE_PGP) of objects originating from this 
- *         object source.
- *  location: (SeahorseLocation) The location of objects that come from this 
- *         source. (ie: SEAHORSE_LOCATION_LOCAL, SEAHORSE_LOCATION_REMOTE)
- *  uri: (gchar*) Only for remote object sources. The full URI of the keyserver 
- *         being used.
  */
 
 
diff --git a/pgp/seahorse-gpgme-keyring.c b/pgp/seahorse-gpgme-keyring.c
index ce4de65..f63dc50 100644
--- a/pgp/seahorse-gpgme-keyring.c
+++ b/pgp/seahorse-gpgme-keyring.c
@@ -52,7 +52,8 @@ enum {
 	PROP_0,
 	PROP_LABEL,
 	PROP_DESCRIPTION,
-	PROP_ICON
+	PROP_ICON,
+	PROP_URI
 };
 
 /* Amount of keys to load in a batch */
@@ -965,6 +966,9 @@ seahorse_gpgme_keyring_get_property (GObject *obj,
 	case PROP_ICON:
 		g_value_take_object (value, g_themed_icon_new (GCR_ICON_HOME_DIRECTORY));
 		break;
+	case PROP_URI:
+		g_value_set_string (value, "gnupg://");
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -1031,6 +1035,7 @@ seahorse_gpgme_keyring_class_init (SeahorseGpgmeKeyringClass *klass)
 
 	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
 	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
+	g_object_class_override_property (gobject_class, PROP_URI, "uri");
 	g_object_class_override_property (gobject_class, PROP_ICON, "icon");
 }
 
diff --git a/pgp/seahorse-server-source.c b/pgp/seahorse-server-source.c
index 91161b0..387c10c 100644
--- a/pgp/seahorse-server-source.c
+++ b/pgp/seahorse-server-source.c
@@ -106,7 +106,7 @@ seahorse_server_source_class_init (SeahorseServerSourceClass *klass)
     g_object_class_install_property (gobject_class, PROP_URI,
             g_param_spec_string ("uri", "Key Server URI",
                                  "Key Server full URI", "",
-                                 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
+                                 G_PARAM_READWRITE));
 }
 
 /**
@@ -167,7 +167,7 @@ seahorse_server_set_property (GObject *object, guint prop_id,
         g_return_if_fail (ssrc->priv->server && ssrc->priv->server[0]);
         break;
     case PROP_URI:
-        g_assert (ssrc->priv->uri == NULL);
+        g_free (ssrc->priv->uri);
         ssrc->priv->uri = g_strdup (g_value_get_string (value));
         g_return_if_fail (ssrc->priv->uri && ssrc->priv->uri[0]);
         break;
diff --git a/pkcs11/seahorse-pkcs11-backend.c b/pkcs11/seahorse-pkcs11-backend.c
index 1f87d9d..93c84c9 100644
--- a/pkcs11/seahorse-pkcs11-backend.c
+++ b/pkcs11/seahorse-pkcs11-backend.c
@@ -142,6 +142,8 @@ on_initialized_registered (GObject *unused,
 		slots = gck_module_get_slots (m->data, TRUE);
 		for (s = slots; s; s = g_list_next (s)) {
 			token = gck_slot_get_token_info (s->data);
+			if (token == NULL)
+				continue;
 			if (is_token_usable (self, s->data, token)) {
 				source = SEAHORSE_SOURCE (seahorse_token_new (s->data));
 				self->slots = g_list_append (self->slots, source);
diff --git a/pkcs11/seahorse-token.c b/pkcs11/seahorse-token.c
index cb5fd12..6b015d2 100644
--- a/pkcs11/seahorse-token.c
+++ b/pkcs11/seahorse-token.c
@@ -44,11 +44,13 @@ enum {
 	PROP_DESCRIPTION,
 	PROP_ICON,
 	PROP_SLOT,
-	PROP_FLAGS
+	PROP_FLAGS,
+	PROP_URI,
 };
 
 struct _SeahorseTokenPrivate {
 	GckSlot *slot;
+	gchar *uri;
 	GHashTable *objects;
 };
 
@@ -216,9 +218,17 @@ static void
 seahorse_token_constructed (GObject *obj)
 {
 	SeahorseToken *self = SEAHORSE_TOKEN (obj);
+	GckUriData *data;
 
 	G_OBJECT_CLASS (seahorse_token_parent_class)->constructed (obj);
 
+	g_return_if_fail (self->pv->slot != NULL);
+
+	data = gck_uri_data_new ();
+	data->token_info = gck_slot_get_token_info (self->pv->slot);
+	self->pv->uri = gck_uri_build (data, GCK_URI_FOR_TOKEN);
+	gck_uri_data_free (data);
+
 	seahorse_token_refresh_async (self, NULL, NULL, NULL);
 }
 
@@ -262,6 +272,12 @@ seahorse_token_get_property (GObject *object,
 	case PROP_FLAGS:
 		g_value_set_uint (value, 0);
 		break;
+	case PROP_URI:
+		g_value_set_string (value, self->pv->uri);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
 	}
 }
 
@@ -303,6 +319,7 @@ seahorse_token_finalize (GObject *obj)
 
 	g_hash_table_destroy (self->pv->objects);
 	g_assert (self->pv->slot == NULL);
+	g_free (self->pv->uri);
 
 	G_OBJECT_CLASS (seahorse_token_parent_class)->finalize (obj);
 }
@@ -322,6 +339,7 @@ seahorse_token_class_init (SeahorseTokenClass *klass)
 
 	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
 	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
+	g_object_class_override_property (gobject_class, PROP_URI, "uri");
 	g_object_class_override_property (gobject_class, PROP_ICON, "icon");
 
 	g_object_class_install_property (gobject_class, PROP_SLOT,
diff --git a/src/seahorse-key-manager.c b/src/seahorse-key-manager.c
index 1aae0fe..e7261d0 100644
--- a/src/seahorse-key-manager.c
+++ b/src/seahorse-key-manager.c
@@ -497,12 +497,12 @@ on_sidebar_panes_size_allocate (GtkWidget *widget,
 {
 	SeahorseKeyManager *self = SEAHORSE_KEY_MANAGER (user_data);
 
-	if (self->pv->sidebar_width_sig != 0) {
-		g_source_remove (self->pv->sidebar_width_sig);
-		self->pv->sidebar_width_sig = 0;
-	}
-
 	if (allocation->width != self->pv->sidebar_width && allocation->width > 1) {
+		if (self->pv->sidebar_width_sig != 0) {
+			g_source_remove (self->pv->sidebar_width_sig);
+			self->pv->sidebar_width_sig = 0;
+		}
+
 		self->pv->sidebar_width = allocation->width;
 		self->pv->sidebar_width_sig = g_idle_add (on_idle_save_sidebar_width, self);
 	}
@@ -521,22 +521,32 @@ setup_sidebar (SeahorseKeyManager *self)
 	gtk_container_add (GTK_CONTAINER (area), GTK_WIDGET (sidebar));
 	gtk_widget_show (GTK_WIDGET (sidebar));
 
-	self->pv->sidebar_width = g_settings_get_int (self->pv->settings, "sidebar-width");
-	panes = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "sidebar-panes");
-	gtk_paned_set_position (GTK_PANED (panes), self->pv->sidebar_width);
-	g_signal_connect (sidebar, "size_allocate", G_CALLBACK (on_sidebar_panes_size_allocate), self);
-
 	actions = gtk_action_group_new ("sidebar");
 	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
 	gtk_action_group_add_toggle_actions (actions, SIDEBAR_ACTIONS,
 	                                     G_N_ELEMENTS (SIDEBAR_ACTIONS), self);
 	action = gtk_action_group_get_action (actions, "view-places");
-	g_object_bind_property (action, "active", area, "visible", G_BINDING_DEFAULT);
-	g_object_bind_property (action, "active", sidebar, "combined", G_BINDING_INVERT_BOOLEAN);
-	g_settings_bind (self->pv->settings, "sidebar-visible", action, "active", G_SETTINGS_BIND_DEFAULT);
+	g_object_bind_property (action, "active",
+	                        area, "visible",
+	                        G_BINDING_DEFAULT);
+	g_object_bind_property (action, "active",
+	                        sidebar, "combined",
+	                        G_BINDING_INVERT_BOOLEAN);
+	g_settings_bind (self->pv->settings, "sidebar-visible",
+	                 action, "active",
+	                 G_SETTINGS_BIND_DEFAULT);
 	seahorse_viewer_include_actions (SEAHORSE_VIEWER (self), actions);
 	g_object_unref (actions);
 
+	g_settings_bind (self->pv->settings, "places-selected",
+	                 sidebar, "selected-uris",
+	                 G_SETTINGS_BIND_DEFAULT);
+
+	self->pv->sidebar_width = g_settings_get_int (self->pv->settings, "sidebar-width");
+	panes = seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "sidebar-panes");
+	gtk_paned_set_position (GTK_PANED (panes), self->pv->sidebar_width);
+	g_signal_connect (sidebar, "size_allocate", G_CALLBACK (on_sidebar_panes_size_allocate), self);
+
 	return seahorse_sidebar_get_collection (sidebar);
 }
 
@@ -570,7 +580,7 @@ seahorse_key_manager_constructed (GObject *object)
 	seahorse_viewer_include_actions (SEAHORSE_VIEWER (self), self->pv->view_actions);
 
 	/* Notify us when settings change */
-	g_signal_connect_object (self->pv->settings, "changed",
+	g_signal_connect_object (self->pv->settings, "changed::item-filter",
 	                         G_CALLBACK (on_item_filter_changed), action, 0);
 
 	/* close event */
diff --git a/src/seahorse-sidebar.c b/src/seahorse-sidebar.c
index 30e87a6..ab42602 100644
--- a/src/seahorse-sidebar.c
+++ b/src/seahorse-sidebar.c
@@ -32,12 +32,6 @@
 
 #include <glib/gi18n.h>
 
-typedef enum {
-	SEAHORSE_SIDEBAR_MODE_COMBINED,
-	SEAHORSE_SIDEBAR_MODE_CHECKED,
-	SEAHORSE_SIDEBAR_MODE_SELECTED
-} SeahorseSidebarMode;
-
 struct _SeahorseSidebar {
 	GtkScrolledWindow parent;
 
@@ -45,10 +39,16 @@ struct _SeahorseSidebar {
 
 	GtkListStore *store;
 	GPtrArray *backends;
-	SeahorseSidebarMode mode;
-	GHashTable *checked;
 	GcrUnionCollection *objects;
+
+	/* The selection */
+	GHashTable *checked;
 	GcrCollection *selected;
+	gboolean combined;
+	gboolean updating;
+
+	/* A set of chosen uris, used with settings */
+	GHashTable *chosen;
 
 	guint update_places_sig;
 };
@@ -60,7 +60,8 @@ struct _SeahorseSidebarClass {
 enum {
 	PROP_0,
 	PROP_COLLECTION,
-	PROP_COMBINED
+	PROP_COMBINED,
+	PROP_SELECTED_URIS
 };
 
 typedef enum {
@@ -76,6 +77,7 @@ enum {
 	SIDEBAR_EDITABLE,
 	SIDEBAR_CATEGORY,
 	SIDEBAR_COLLECTION,
+	SIDEBAR_URI,
 	SIDEBAR_N_COLUMNS
 };
 
@@ -87,6 +89,7 @@ static GType column_types[] = {
 	G_TYPE_BOOLEAN,
 	G_TYPE_STRING,
 	0 /* later */,
+	G_TYPE_STRING,
 };
 
 G_DEFINE_TYPE (SeahorseSidebar, seahorse_sidebar, GTK_TYPE_SCROLLED_WINDOW);
@@ -102,11 +105,11 @@ seahorse_sidebar_init (SeahorseSidebar *self)
 	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 ());
-	self->mode = SEAHORSE_SIDEBAR_MODE_SELECTED;
+	self->chosen = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 }
 
 static void
-next_or_append_row (SeahorseSidebar *self,
+next_or_append_row (GtkListStore *store,
                     GtkTreeIter *iter,
                     const gchar *category,
                     GcrCollection *collection)
@@ -128,18 +131,18 @@ next_or_append_row (SeahorseSidebar *self,
 	/* A marker that tells us the iter is not yet valid */
 	if (iter->stamp == GPOINTER_TO_INT (iter) && iter->user_data3 == iter &&
 	    iter->user_data2 == iter && iter->user_data == iter) {
-		if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->store), iter))
-			gtk_list_store_append (self->store, iter);
+		if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), iter))
+			gtk_list_store_append (store, iter);
 		return;
 	}
 
-	if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (self->store), iter)) {
-		gtk_list_store_append (self->store, iter);
+	if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (store), iter)) {
+		gtk_list_store_append (store, iter);
 		return;
 	}
 
 	for (;;) {
-		gtk_tree_model_get (GTK_TREE_MODEL (self->store), iter,
+		gtk_tree_model_get (GTK_TREE_MODEL (store), iter,
 		                    SIDEBAR_CATEGORY, &row_category,
 		                    SIDEBAR_COLLECTION, &row_collection,
 		                    -1);
@@ -152,9 +155,8 @@ next_or_append_row (SeahorseSidebar *self,
 		if (found)
 			return;
 
-		g_hash_table_remove (self->checked, row_collection);
-		if (!gtk_list_store_remove (self->store, iter)) {
-			gtk_list_store_append (self->store, iter);
+		if (!gtk_list_store_remove (store, iter)) {
+			gtk_list_store_append (store, iter);
 			return;
 		}
 	}
@@ -171,6 +173,7 @@ update_backend (SeahorseSidebar *self,
 	gchar *tooltip;
 	gchar *label;
 	GIcon *icon = NULL;
+	gchar *uri;
 
 	collections = gcr_collection_get_objects (backend);
 
@@ -184,7 +187,7 @@ update_backend (SeahorseSidebar *self,
 	              "description", &tooltip,
 	              NULL);
 
-	next_or_append_row (self, iter, category, GCR_COLLECTION (backend));
+	next_or_append_row (self->store, iter, category, GCR_COLLECTION (backend));
 	gtk_list_store_set (self->store, iter,
 	                    SIDEBAR_ROW_TYPE, TYPE_BACKEND,
 	                    SIDEBAR_CATEGORY, category,
@@ -198,18 +201,18 @@ update_backend (SeahorseSidebar *self,
 	g_free (tooltip);
 
 	for (l = collections; l != NULL; l = g_list_next (l)) {
-
 		label = tooltip = NULL;
 		g_object_get (l->data,
 		              "label", &label,
 		              "description", &tooltip,
 		              "icon", &icon,
+		              "uri", &uri,
 		              NULL);
 
 		spec = g_object_class_find_property (G_OBJECT_GET_CLASS (l->data), "label");
 		g_return_if_fail (spec != NULL);
 
-		next_or_append_row (self, iter, category, l->data);
+		next_or_append_row (self->store, iter, category, l->data);
 		gtk_list_store_set (self->store, iter,
 		                    SIDEBAR_ROW_TYPE, TYPE_PLACE,
 		                    SIDEBAR_CATEGORY, category,
@@ -218,11 +221,13 @@ update_backend (SeahorseSidebar *self,
 		                    SIDEBAR_ICON, icon,
 		                    SIDEBAR_EDITABLE, (spec->flags & G_PARAM_WRITABLE) ? TRUE : FALSE,
 		                    SIDEBAR_COLLECTION, l->data,
+		                    SIDEBAR_URI, uri,
 		                    -1);
 
 		g_clear_object (&icon);
 		g_free (label);
 		g_free (tooltip);
+		g_free (uri);
 	}
 
 	g_free (category);
@@ -230,31 +235,50 @@ update_backend (SeahorseSidebar *self,
 }
 
 static void
-update_objects_in_collection (SeahorseSidebar *self)
+update_objects_in_collection (SeahorseSidebar *self,
+                              gboolean update_chosen)
 {
 	GList *collections;
 	gboolean include;
 	gboolean have;
+	gboolean changed = FALSE;
+	gchar *uri;
 	GList *l;
 	guint i;
 
+	/* Updating collection is blocked */
+	if (self->updating)
+		return;
+
 	for (i = 0; i < self->backends->len; i++) {
 		collections = gcr_collection_get_objects (self->backends->pdata[i]);
 		for (l = collections; l != NULL; l = g_list_next (l)) {
-			switch (self->mode) {
-			case SEAHORSE_SIDEBAR_MODE_COMBINED:
-				include = TRUE;
-				break;
-			case SEAHORSE_SIDEBAR_MODE_CHECKED:
+
+			/* Checked collections are chosen*/
+			if (g_hash_table_size (self->checked) > 0)
 				include = (g_hash_table_lookup (self->checked, l->data) != NULL);
-				break;
-			case SEAHORSE_SIDEBAR_MODE_SELECTED:
+
+			/* Just selected one is chosen */
+			else
 				include = (l->data == self->selected);
-				break;
-			default:
-				g_assert_not_reached ();
+
+			if (update_chosen) {
+				g_object_get (l->data, "uri", &uri, NULL);
+				have = g_hash_table_lookup (self->chosen, uri) != NULL;
+				if (include && !have) {
+					g_hash_table_insert (self->chosen, g_strdup (uri), "");
+					changed = TRUE;
+				} else if (!include && have) {
+					g_hash_table_remove (self->chosen, uri);
+					changed = TRUE;
+				}
+				g_free (uri);
 			}
 
+			/* Combined overrides and shows all objects */
+			if (self->combined)
+				include = TRUE;
+
 			have = gcr_union_collection_have (self->objects, l->data);
 			if (include && !have)
 				gcr_union_collection_add (self->objects, l->data);
@@ -263,6 +287,9 @@ update_objects_in_collection (SeahorseSidebar *self)
 		}
 		g_list_free (collections);
 	}
+
+	if (update_chosen && changed)
+		g_object_notify (G_OBJECT (self), "selected-uris");
 }
 
 static void
@@ -281,8 +308,8 @@ update_objects_for_selection (SeahorseSidebar *self,
 	if (selected != self->selected) {
 		g_clear_object (&self->selected);
 		self->selected = selected ? g_object_ref (selected) : NULL;
-		if (self->mode == SEAHORSE_SIDEBAR_MODE_SELECTED)
-			update_objects_in_collection (self);
+		if (g_hash_table_size (self->checked) == 0)
+			update_objects_in_collection (self, TRUE);
 	}
 
 	g_clear_object (&selected);
@@ -293,11 +320,7 @@ update_objects_for_checked (SeahorseSidebar *self,
                             GcrCollection *place)
 {
 	g_hash_table_insert (self->checked, place, place);
-
-	if (self->mode == SEAHORSE_SIDEBAR_MODE_SELECTED)
-		self->mode = SEAHORSE_SIDEBAR_MODE_CHECKED;
-	if (self->mode != SEAHORSE_SIDEBAR_MODE_COMBINED)
-		update_objects_in_collection (self);
+	update_objects_in_collection (self, TRUE);
 }
 
 static void
@@ -306,33 +329,121 @@ update_objects_for_unchecked (SeahorseSidebar *self,
 {
 	if (!g_hash_table_remove (self->checked, place))
 		g_assert_not_reached ();
+	update_objects_in_collection (self, TRUE);
+}
 
-	if (self->mode == SEAHORSE_SIDEBAR_MODE_CHECKED &&
-	    g_hash_table_size (self->checked) == 0)
-		self->mode = SEAHORSE_SIDEBAR_MODE_SELECTED;
-	if (self->mode != SEAHORSE_SIDEBAR_MODE_COMBINED)
-		update_objects_in_collection (self);
+static void
+update_objects_for_combine (SeahorseSidebar *self,
+                            gboolean combine)
+{
+	if (self->combined != combine) {
+		self->combined = combine;
+		update_objects_in_collection (self, FALSE);
+	}
 }
 
 static void
-update_objects_for_combine (SeahorseSidebar *self)
+invalidate_all_rows (GtkTreeModel *model)
 {
-	if (self->mode != SEAHORSE_SIDEBAR_MODE_COMBINED) {
-		self->mode = SEAHORSE_SIDEBAR_MODE_COMBINED;
-		update_objects_in_collection (self);
+	GtkTreeIter iter;
+	GtkTreePath *path;
+
+	if (gtk_tree_model_get_iter_first (model, &iter)) {
+		do {
+			path = gtk_tree_model_get_path (model, &iter);
+			gtk_tree_model_row_changed (model, path, &iter);
+			gtk_tree_path_free (path);
+		} while (gtk_tree_model_iter_next (model, &iter));
 	}
 }
 
 static void
-update_objects_for_uncombine (SeahorseSidebar *self)
+update_objects_for_chosen (SeahorseSidebar *self,
+                           GHashTable *chosen)
 {
-	if (self->mode == SEAHORSE_SIDEBAR_MODE_COMBINED) {
-		if (g_hash_table_size (self->checked) > 0)
-			self->mode = SEAHORSE_SIDEBAR_MODE_CHECKED;
-		else
-			self->mode = SEAHORSE_SIDEBAR_MODE_SELECTED;
-		update_objects_in_collection (self);
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+	GcrCollection *collection;
+	gboolean checked;
+	gchar *uri;
+	gint count = 0;
+	gboolean changed = FALSE;
+	GcrCollection *selected = NULL;
+	GtkTreeIter select_iter;
+	GtkTreeSelection *selection;
+
+	self->updating = TRUE;
+
+	/* Update the display */
+	model = GTK_TREE_MODEL (self->store);
+	if (gtk_tree_model_get_iter_first (model, &iter)) {
+		do {
+			gtk_tree_model_get (model, &iter,
+					    SIDEBAR_COLLECTION, &collection,
+					    SIDEBAR_URI, &uri,
+					    -1);
+
+			if (collection && uri) {
+				checked = g_hash_table_size (self->checked) > 0;
+
+				/* Chosen */
+				if (g_hash_table_lookup (chosen, uri)) {
+					if (!checked) {
+						/* First one update selection */
+						if (count == 0) {
+							g_clear_object (&selected);
+							selected = collection;
+							collection = NULL;
+							select_iter = iter;
+							changed = TRUE;
+
+						/* Second one, change to checked if necessary */
+						} else if (count == 1) {
+							g_assert (selected != NULL);
+							g_hash_table_insert (self->checked,
+							                     selected,
+							                     selected);
+							g_clear_object (&selected);
+							checked = TRUE;
+							changed = TRUE;
+						}
+					}
+
+					if (checked) {
+						g_hash_table_insert (self->checked,
+						                     collection,
+						                     collection);
+						changed = TRUE;
+					}
+
+					count++;
+
+				/* Not chosen */
+				} else {
+					if (!checked)
+						changed = TRUE;
+					if (g_hash_table_remove (self->checked, collection))
+						changed = TRUE;
+				}
+			}
+
+			g_clear_object (&collection);
+			g_free (uri);
+		} while (gtk_tree_model_iter_next (model, &iter));
 	}
+
+	if (selected) {
+		selection = gtk_tree_view_get_selection (self->tree_view);
+		gtk_tree_selection_select_iter (selection, &select_iter);
+		g_object_unref (selected);
+	}
+
+	self->updating = FALSE;
+
+	if (changed)
+		invalidate_all_rows (model);
+
+	update_objects_in_collection (self, FALSE);
 }
 
 static void
@@ -349,7 +460,7 @@ update_places (SeahorseSidebar *self)
 		update_backend (self, GCR_COLLECTION (self->backends->pdata[i]), &iter);
 
 	/* Update selection */
-	update_objects_in_collection (self);
+	update_objects_for_chosen (self, self->chosen);
 }
 
 static gboolean
@@ -457,7 +568,8 @@ on_cell_renderer_check (GtkTreeViewColumn *column,
 		active = g_hash_table_lookup (self->checked, collection) != NULL;
 		visible = TRUE;
 	} else {
-		visible = (collection == self->selected);
+		visible = (gtk_widget_is_focus (GTK_WIDGET (self->tree_view)) &&
+		           collection == self->selected);
 	}
 
 	/* self->mnemonics_visible */
@@ -470,21 +582,6 @@ on_cell_renderer_check (GtkTreeViewColumn *column,
 	g_clear_object (&collection);
 }
 
-static void
-invalidate_all_rows (GtkTreeModel *model)
-{
-	GtkTreeIter iter;
-	GtkTreePath *path;
-
-	if (gtk_tree_model_get_iter_first (model, &iter)) {
-		do {
-			path = gtk_tree_model_get_path (model, &iter);
-			gtk_tree_model_row_changed (model, path, &iter);
-			gtk_tree_path_free (path);
-		} while (gtk_tree_model_iter_next (model, &iter));
-	}
-}
-
 static gboolean
 on_tree_selection_validate (GtkTreeSelection *selection,
                             GtkTreeModel *model,
@@ -779,6 +876,9 @@ seahorse_sidebar_get_property (GObject *obj,
 	case PROP_COMBINED:
 		g_value_set_boolean (value, seahorse_sidebar_get_combined (self));
 		break;
+	case PROP_SELECTED_URIS:
+		g_value_take_boxed (value, seahorse_sidebar_get_selected_uris (self));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -797,6 +897,9 @@ seahorse_sidebar_set_property (GObject *obj,
 	case PROP_COMBINED:
 		seahorse_sidebar_set_combined (self, g_value_get_boolean (value));
 		break;
+	case PROP_SELECTED_URIS:
+		seahorse_sidebar_set_selected_uris (self, g_value_get_boxed (value));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -831,6 +934,7 @@ seahorse_sidebar_finalize (GObject *obj)
 
 	g_clear_object (&self->selected);
 	g_hash_table_destroy (self->checked);
+	g_hash_table_destroy (self->chosen);
 	g_object_unref (self->objects);
 
 	if (self->update_places_sig)
@@ -860,6 +964,10 @@ seahorse_sidebar_class_init (SeahorseSidebarClass *klass)
 	g_object_class_install_property (gobject_class, PROP_COMBINED,
 	        g_param_spec_boolean ("combined", "Combined", "Collection shows all objects combined",
 	                              FALSE, G_PARAM_READWRITE));
+
+	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));
 }
 
 SeahorseSidebar *
@@ -880,7 +988,7 @@ gboolean
 seahorse_sidebar_get_combined (SeahorseSidebar *self)
 {
 	g_return_val_if_fail (SEAHORSE_IS_SIDEBAR (self), FALSE);
-	return self->mode == SEAHORSE_SIDEBAR_MODE_COMBINED;
+	return self->combined;
 }
 
 void
@@ -888,9 +996,45 @@ seahorse_sidebar_set_combined (SeahorseSidebar *self,
                                gboolean combined)
 {
 	g_return_if_fail (SEAHORSE_IS_SIDEBAR (self));
-	if (combined)
-		update_objects_for_combine (self);
-	else
-		update_objects_for_uncombine (self);
+	update_objects_for_combine (self, combined);
 	g_object_notify (G_OBJECT (self), "combined");
 }
+
+gchar **
+seahorse_sidebar_get_selected_uris (SeahorseSidebar *self)
+{
+	GHashTableIter iter;
+	GPtrArray *results;
+	gchar *uri;
+
+	g_return_val_if_fail (SEAHORSE_IS_SIDEBAR (self), NULL);
+
+	results = g_ptr_array_new ();
+	g_hash_table_iter_init (&iter, self->chosen);
+	while (g_hash_table_iter_next (&iter, (gpointer *)&uri, NULL))
+		g_ptr_array_add (results, g_strdup (uri));
+	g_ptr_array_add (results, NULL);
+
+	return (gchar **)g_ptr_array_free (results, FALSE);
+}
+
+void
+seahorse_sidebar_set_selected_uris (SeahorseSidebar *self,
+                                    const gchar **value)
+{
+	GHashTable *chosen;
+	gint i;
+
+	g_return_if_fail (SEAHORSE_IS_SIDEBAR (self));
+
+	/* For quick lookups */
+	chosen = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	for (i = 0; value != NULL && value[i] != NULL; i++)
+		g_hash_table_insert (chosen, g_strdup (value[i]), "");
+
+	update_objects_for_chosen (self, chosen);
+	g_hash_table_destroy (self->chosen);
+	self->chosen = chosen;
+
+	g_object_notify (G_OBJECT (self), "selected-uris");
+}
diff --git a/src/seahorse-sidebar.h b/src/seahorse-sidebar.h
index 48b57ef..fb59f36 100644
--- a/src/seahorse-sidebar.h
+++ b/src/seahorse-sidebar.h
@@ -47,4 +47,9 @@ void                         seahorse_sidebar_set_combined       (SeahorseSideba
 
 GcrCollection *              seahorse_sidebar_get_collection     (SeahorseSidebar *self);
 
+gchar **                     seahorse_sidebar_get_selected_uris  (SeahorseSidebar *self);
+
+void                         seahorse_sidebar_set_selected_uris  (SeahorseSidebar *self,
+                                                                  const gchar **value);
+
 #endif /* __SEAHORSE_SIDEBAR_H__ */
diff --git a/ssh/seahorse-ssh-source.c b/ssh/seahorse-ssh-source.c
index b08f5e7..0f283d9 100644
--- a/ssh/seahorse-ssh-source.c
+++ b/ssh/seahorse-ssh-source.c
@@ -49,7 +49,8 @@ enum {
 	PROP_LABEL,
 	PROP_DESCRIPTION,
 	PROP_ICON,
-	PROP_BASE_DIRECTORY
+	PROP_BASE_DIRECTORY,
+	PROP_URI
 };
 
 struct _SeahorseSSHSourcePrivate {
@@ -230,7 +231,7 @@ seahorse_ssh_source_get_property (GObject *obj,
 		g_value_set_string (value, _("OpenSSH directory"));
 		break;
 	case PROP_DESCRIPTION:
-		text = g_strdup_printf (_("OpenSSH: %s"), "~/.ssh/");
+		text = g_strdup_printf (_("OpenSSH: %s"), self->priv->ssh_homedir);
 		g_value_take_string (value, text);
 		break;
 	case PROP_ICON:
@@ -239,6 +240,10 @@ seahorse_ssh_source_get_property (GObject *obj,
 	case PROP_BASE_DIRECTORY:
 		g_value_set_string (value, self->priv->ssh_homedir);
 		break;
+	case PROP_URI:
+		g_value_take_string (value, g_strdup_printf ("openssh://%s",
+		                                             self->priv->ssh_homedir));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -295,7 +300,7 @@ seahorse_ssh_source_init (SeahorseSSHSource *ssrc)
 	ssrc->priv->scheduled_refresh = 0;
 	ssrc->priv->monitor_handle = NULL;
 
-	ssrc->priv->ssh_homedir = g_strdup_printf ("%s/.ssh/", g_get_home_dir ());
+	ssrc->priv->ssh_homedir = g_strdup_printf ("%s/.ssh", g_get_home_dir ());
 
 	/* Make the .ssh directory if it doesn't exist */
 	if (!g_file_test (ssrc->priv->ssh_homedir, G_FILE_TEST_EXISTS)) {
@@ -329,6 +334,7 @@ seahorse_ssh_source_class_init (SeahorseSSHSourceClass *klass)
 
     g_object_class_override_property (gobject_class, PROP_LABEL, "label");
     g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
+    g_object_class_override_property (gobject_class, PROP_URI, "uri");
     g_object_class_override_property (gobject_class, PROP_ICON, "icon");
 
     g_object_class_install_property (gobject_class, PROP_BASE_DIRECTORY,



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