static void
seahorse_keyserver_results_set_property (GObject *obj, guint prop_id, const GValue *value, 
                           GParamSpec *pspec)
{
	SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (obj);
	const gchar* str;
	
	switch (prop_id) {
	case PROP_SEARCH:
		/* Many key servers ignore spaces at the beginning and end, so we do too */
		str = g_value_get_string (value);
		if (!str)
			str = "";
		self->pv->search_string = g_strstrip (g_utf8_casefold (str, -1));
		break;
		
	case PROP_SELECTED:
		seahorse_viewer_set_selected (SEAHORSE_VIEWER (self), g_value_get_object (value));
		break;

	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
		break;
	}
}
static SeahorseObject* 
seahorse_keyserver_results_get_selected (SeahorseViewer* base) 
{
	SeahorseKeyserverResults* self;
	self = SEAHORSE_KEYSERVER_RESULTS (base);
	return seahorse_key_manager_store_get_selected_object (self->pv->view);
}
static void
seahorse_keyserver_results_finalize (GObject *obj)
{
	SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (obj);

	g_free (self->pv->search_string);
	self->pv->search_string = NULL;
	
	if (self->pv->object_actions)
		g_object_unref (self->pv->object_actions);
	self->pv->object_actions = NULL;
	
	if (self->pv->objects)
		g_object_unref (self->pv->objects);
	self->pv->objects = NULL;
	
	if (self->pv->store)
		g_object_unref (self->pv->store);
	self->pv->store = NULL;
	
	if (self->pv->view)
		gtk_tree_view_set_model (self->pv->view, NULL);
	self->pv->view = NULL;
	
	G_OBJECT_CLASS (seahorse_keyserver_results_parent_class)->finalize (obj);
}
static gboolean
on_delete_event (GtkWidget* widget, GdkEvent* event, gpointer user_data)
{
    SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (user_data);

    gtk_widget_destroy (GTK_WIDGET (self));
    return TRUE;
}
static void
on_row_activated (GtkListBox *key_list, GtkListBoxRow *row, gpointer user_data)
{
    SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (user_data);
    SeahorseKeyserverResultsRow *_row = SEAHORSE_KEYSERVER_RESULTS_ROW (row);

    g_return_if_fail (SEAHORSE_IS_VIEWABLE (_row->key));

    seahorse_viewable_view (_row->key, GTK_WINDOW (self));
}
static void
seahorse_keyserver_results_finalize (GObject *obj)
{
    SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (obj);

    g_clear_pointer (&self->search_string, g_free);
    g_clear_object (&self->collection);
    g_clear_object (&self->builder);

    G_OBJECT_CLASS (seahorse_keyserver_results_parent_class)->finalize (obj);
}
static void 
seahorse_keyserver_results_set_selected (SeahorseViewer* base, SeahorseObject* value) 
{
	SeahorseKeyserverResults* self = SEAHORSE_KEYSERVER_RESULTS (base);
	GList* keys = NULL;

	if (value != NULL)
		keys = g_list_prepend (keys, value);

	seahorse_viewer_set_selected_objects (SEAHORSE_VIEWER (self), keys);
	g_list_free (keys);;
	g_object_notify (G_OBJECT (self), "selected");
}
static void
on_item_added (GcrCollection *collection, GObject *item, gpointer user_data)
{
    SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (user_data);
    g_autoptr(SeahorseKeyserverResultsRow) row = NULL;

    g_return_if_fail (G_IS_OBJECT (item));

    row = seahorse_keyserver_results_row_new (item);
    gtk_list_box_insert (self->key_list,
                         GTK_WIDGET (g_steal_pointer (&row)),
                         -1);
}
/**
* obj: The SeahorseKeyserverResults object to get properties from
* prop_id: the ide of the property to get
* value: Value returned
* pspec: GParamSpec for the warning
*
* Supported properties: PROP_SEARCH and PROP_SELECTED
*
**/
static void
seahorse_keyserver_results_get_property (GObject *obj, guint prop_id, GValue *value,
                           GParamSpec *pspec)
{
	SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (obj);

	switch (prop_id) {
	case PROP_SEARCH:
		g_value_set_string (value, seahorse_keyserver_results_get_search (self));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
		break;
	}
}
static void
on_search_completed (GObject *source, GAsyncResult *result, gpointer user_data)
{
    SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (user_data);
    SeahorsePgpBackend *backend = seahorse_pgp_backend_get ();
    g_autoptr(GError) error = NULL;

    seahorse_pgp_backend_search_remote_finish (backend, result, &error);
    if (error != NULL) {
        g_dbus_error_strip_remote_error (error);
        seahorse_util_show_error (GTK_WIDGET (self),
                                  _("The search for keys failed."),
                                  error->message);
    }

    g_object_unref (self);
}
static void
on_search_completed (GObject *source,
                     GAsyncResult *result,
                     gpointer user_data)
{
	SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (user_data);
	GError *error = NULL;
	GtkWindow *window;

	seahorse_pgp_backend_search_remote_finish (NULL, result, &error);
	if (error != NULL) {
		window = seahorse_catalog_get_window (SEAHORSE_CATALOG (self));
		g_dbus_error_strip_remote_error (error);
		seahorse_util_show_error (GTK_WIDGET (window),
		                          _("The search for keys failed."), error->message);
		g_error_free (error);
	}

	g_object_unref (self);
}
static void
seahorse_keyserver_results_constructed (GObject *obj)
{
    SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (obj);
    GtkWindow *window = GTK_WINDOW (self);
    g_autofree gchar* title = NULL;

    G_OBJECT_CLASS (seahorse_keyserver_results_parent_class)->constructed (obj);

    if (g_utf8_strlen (self->search_string, -1) == 0) {
        title = g_strdup (_("Remote keys"));
    } else {
        title = g_strdup_printf (_("Remote keys containing “%s”"), self->search_string);
    }

    gtk_window_set_default_size (window, 640, 476);
    gtk_window_set_title (window, title);
    gtk_widget_set_visible (GTK_WIDGET (window), TRUE);

    g_signal_connect (window, "delete-event",
                      G_CALLBACK (on_delete_event), self);

    self->builder = gtk_builder_new_from_resource ("/org/gnome/Seahorse/seahorse-keyserver-results.ui");
    gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (self))),
                       GTK_WIDGET (gtk_builder_get_object (self->builder, "keyserver-results")));

    /* init key list */
    self->key_list = GTK_LIST_BOX (gtk_builder_get_object (self->builder, "key_list"));
    gtk_list_box_set_header_func (self->key_list, key_list_header_func, NULL, NULL);
    g_signal_connect_object (self->key_list, "row-activated",
                             G_CALLBACK (on_row_activated), self, 0);
    gtk_widget_show (GTK_WIDGET (self->key_list));

    /* Make sure the listbox gets updated with the collection */
    g_signal_connect_object (self->collection, "added",
                             G_CALLBACK (on_item_added), self, 0);

    /* Set focus to the current key list */
    gtk_widget_grab_focus (GTK_WIDGET (self->key_list));
}
static GObject* 
seahorse_keyserver_results_constructor (GType type, guint n_props, GObjectConstructParam *props) 
{
	SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (G_OBJECT_CLASS (seahorse_keyserver_results_parent_class)->constructor(type, n_props, props));
	GtkActionGroup* actions;
	GtkTreeSelection *selection;
	GtkWindow *window;
	char* title;

	g_return_val_if_fail (self, NULL);	


	if (g_utf8_strlen (self->pv->search_string, -1) == 0) {
		title = g_strdup (_("Remote Keys"));
	} else {
		title = g_strdup_printf (_ ("Remote Keys Containing '%s'"), self->pv->search_string);
	}

	window = seahorse_viewer_get_window (SEAHORSE_VIEWER (self));
	gtk_window_set_title (window, title);
	g_free (title);
	
	g_signal_connect (window, "delete-event", G_CALLBACK (on_delete_event), self);
	
	actions = gtk_action_group_new ("general");
	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
	gtk_action_group_add_actions (actions, GENERAL_ENTRIES, G_N_ELEMENTS (GENERAL_ENTRIES), self);
	seahorse_viewer_include_actions (SEAHORSE_VIEWER (self), actions);

	actions = gtk_action_group_new ("keyserver");
	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
	gtk_action_group_add_actions (actions, SERVER_ENTRIES, G_N_ELEMENTS (SERVER_ENTRIES), self);
	seahorse_viewer_include_actions (SEAHORSE_VIEWER (self), actions);

	/* init key list & selection settings */
	self->pv->view = GTK_TREE_VIEW (seahorse_widget_get_widget (SEAHORSE_WIDGET (self), "key_list"));
	selection = gtk_tree_view_get_selection (self->pv->view);
	gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
	g_signal_connect_object (selection, "changed", G_CALLBACK (on_view_selection_changed), self, 0);
	g_signal_connect_object (self->pv->view, "row-activated", G_CALLBACK (on_row_activated), self, 0);
	g_signal_connect_object (self->pv->view, "button-press-event", G_CALLBACK (on_key_list_button_pressed), self, 0);
	g_signal_connect_object (self->pv->view, "popup-menu", G_CALLBACK (on_key_list_popup_menu), self, 0);
	gtk_widget_realize (GTK_WIDGET (self->pv->view));
	
	/* Set focus to the current key list */
	gtk_widget_grab_focus (GTK_WIDGET (self->pv->view));
	
	/* To avoid flicker */
	seahorse_viewer_ensure_updated (SEAHORSE_VIEWER (self));
	seahorse_widget_show (SEAHORSE_WIDGET (SEAHORSE_VIEWER (self)));
	
	/* Our predicate for filtering keys */
	self->pv->pred.tag = g_quark_from_string ("openpgp");
	self->pv->pred.location = SEAHORSE_LOCATION_REMOTE;
	self->pv->pred.custom = (SeahorseObjectPredicateFunc)on_filter_objects;
	self->pv->pred.custom_target = self;
	
	/* Our set all nicely filtered */
	self->pv->objects = seahorse_set_new_full (&self->pv->pred);
	self->pv->store = seahorse_key_manager_store_new (self->pv->objects, self->pv->view);
	on_view_selection_changed (selection, self);
	
	return G_OBJECT (self);
}
static void 
seahorse_keyserver_results_set_selected_objects (SeahorseViewer* base, GList* keys) 
{
	SeahorseKeyserverResults * self = SEAHORSE_KEYSERVER_RESULTS (base);
	seahorse_key_manager_store_set_selected_objects (self->pv->view, keys);
}
static void
seahorse_keyserver_results_constructed (GObject *obj)
{
	SeahorseKeyserverResults *self = SEAHORSE_KEYSERVER_RESULTS (obj);
	GtkActionGroup* actions;
	GtkTreeSelection *selection;
	GtkWindow *window;
	GtkBuilder *builder;
	char* title;

	G_OBJECT_CLASS (seahorse_keyserver_results_parent_class)->constructed (obj);

	if (g_utf8_strlen (self->pv->search_string, -1) == 0) {
		title = g_strdup (_("Remote Keys"));
	} else {
		title = g_strdup_printf (_ ("Remote Keys Containing '%s'"), self->pv->search_string);
	}

	window = seahorse_catalog_get_window (SEAHORSE_CATALOG (self));
	gtk_window_set_default_geometry(window, 640, 476);
	gtk_widget_set_events (GTK_WIDGET (window), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
	gtk_window_set_title (window, title);
	gtk_widget_set_visible (GTK_WIDGET (window), TRUE);
	g_free (title);

	g_signal_connect (window, "delete-event", G_CALLBACK (on_delete_event), self);

	actions = gtk_action_group_new ("general");
	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
	gtk_action_group_add_actions (actions, GENERAL_ENTRIES, G_N_ELEMENTS (GENERAL_ENTRIES), self);
	seahorse_catalog_include_actions (SEAHORSE_CATALOG (self), actions);

	actions = gtk_action_group_new ("keyserver");
	gtk_action_group_set_translation_domain (actions, GETTEXT_PACKAGE);
	gtk_action_group_add_actions (actions, SERVER_ENTRIES, G_N_ELEMENTS (SERVER_ENTRIES), self);
	seahorse_catalog_include_actions (SEAHORSE_CATALOG (self), actions);

	self->pv->import_actions = gtk_action_group_new ("import");
	gtk_action_group_set_translation_domain (self->pv->import_actions, GETTEXT_PACKAGE);
	gtk_action_group_add_actions (self->pv->import_actions, IMPORT_ENTRIES, G_N_ELEMENTS (IMPORT_ENTRIES), self);
	g_object_set (gtk_action_group_get_action (self->pv->import_actions, "key-import-keyring"), "is-important", TRUE, NULL);
	seahorse_catalog_include_actions (SEAHORSE_CATALOG (self), self->pv->import_actions);

	/* init key list & selection settings */
	builder = seahorse_catalog_get_builder (SEAHORSE_CATALOG (self));
	self->pv->view = GTK_TREE_VIEW (gtk_builder_get_object (builder, "key_list"));
	selection = gtk_tree_view_get_selection (self->pv->view);
	gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
	g_signal_connect_object (selection, "changed", G_CALLBACK (on_view_selection_changed), self, 0);
	g_signal_connect_object (self->pv->view, "row-activated", G_CALLBACK (on_row_activated), self, 0);
	g_signal_connect_object (self->pv->view, "button-press-event", G_CALLBACK (on_key_list_button_pressed), self, 0);
	g_signal_connect_object (self->pv->view, "popup-menu", G_CALLBACK (on_key_list_popup_menu), self, 0);
	gtk_widget_realize (GTK_WIDGET (self->pv->view));

	/* Set focus to the current key list */
	gtk_widget_grab_focus (GTK_WIDGET (self->pv->view));

	/* To avoid flicker */
	seahorse_catalog_ensure_updated (SEAHORSE_CATALOG (self));
	gtk_widget_show (GTK_WIDGET (self));

	self->pv->store = seahorse_key_manager_store_new (GCR_COLLECTION (self->pv->collection),
	                                                  self->pv->view,
	                                                  &self->pv->pred,
	                                                  self->pv->settings);
	on_view_selection_changed (selection, self);

	/* Include actions from the backend */
	actions = NULL;
	g_object_get (seahorse_pgp_backend_get (), "actions", &actions, NULL);
	seahorse_catalog_include_actions (SEAHORSE_CATALOG (self), actions);
	g_object_unref (actions);
}
static GList *
seahorse_keyserver_results_get_selected_objects (SeahorseCatalog *catalog)
{
	SeahorseKeyserverResults * self = SEAHORSE_KEYSERVER_RESULTS (catalog);
	return seahorse_key_manager_store_get_selected_objects (self->pv->view);
}