+ ev_page_action_widget_set_page_cache (proxy, page_cache);
+ proxy->signal_id = signal_id;
+}
+
+static gboolean
+build_new_tree_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GtkTreeModel *filter_model = GTK_TREE_MODEL (data);
+ EvLink *link;
+
+ gtk_tree_model_get (model, iter,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
+ -1);
+
+ if (link && ev_link_get_link_type (link) == EV_LINK_TYPE_PAGE) {
+ GtkTreeIter filter_iter;
+
+ gtk_list_store_append (GTK_LIST_STORE (filter_model), &filter_iter);
+ gtk_list_store_set (GTK_LIST_STORE (filter_model), &filter_iter,
+ 0, iter,
+ -1);
+ }
+
+ if (link)
+ g_object_unref (link);
+
+ return FALSE;
+}
+
+static GtkTreeModel *
+get_filter_model_from_model (GtkTreeModel *model)
+{
+ GtkTreeModel *filter_model;
+
+ filter_model =
+ (GtkTreeModel *) g_object_get_data (G_OBJECT (model), EPA_FILTER_MODEL_DATA);
+ if (filter_model == NULL) {
+ filter_model = (GtkTreeModel *) gtk_list_store_new (1, GTK_TYPE_TREE_ITER);
+
+ gtk_tree_model_foreach (model,
+ build_new_tree_cb,
+ filter_model);
+ g_object_set_data_full (G_OBJECT (model), EPA_FILTER_MODEL_DATA, filter_model, g_object_unref);
+ }
+
+ return filter_model;
+}
+
+static gboolean
+match_selected_cb (GtkEntryCompletion *completion,
+ GtkTreeModel *filter_model,
+ GtkTreeIter *filter_iter,
+ EvPageActionWidget *proxy)
+{
+ EvLink *link;
+ GtkTreeIter *iter;
+
+ gtk_tree_model_get (filter_model, filter_iter,
+ 0, &iter,
+ -1);
+ gtk_tree_model_get (proxy->model, iter,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
+ -1);
+
+ g_signal_emit (proxy, widget_signals[WIDGET_ACTIVATE_LINK], 0, link);
+
+ if (link)
+ g_object_unref (link);
+
+ gtk_tree_iter_free (iter);
+
+ return TRUE;
+}
+
+
+static void
+display_completion_text (GtkCellLayout *cell_layout,
+ GtkCellRenderer *renderer,
+ GtkTreeModel *filter_model,
+ GtkTreeIter *filter_iter,
+ EvPageActionWidget *proxy)
+{
+ EvLink *link;
+ GtkTreeIter *iter;
+
+ gtk_tree_model_get (filter_model, filter_iter,
+ 0, &iter,
+ -1);
+ gtk_tree_model_get (proxy->model, iter,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
+ -1);
+
+ g_object_set (renderer, "text", ev_link_get_title (link), NULL);
+
+ if (link)
+ g_object_unref (link);
+
+ gtk_tree_iter_free (iter);
+}
+
+static gboolean
+match_completion (GtkEntryCompletion *completion,
+ const gchar *key,
+ GtkTreeIter *filter_iter,
+ EvPageActionWidget *proxy)
+{
+ EvLink *link;
+ GtkTreeIter *iter;
+ const gchar *text = NULL;
+
+ gtk_tree_model_get (gtk_entry_completion_get_model (completion),
+ filter_iter,
+ 0, &iter,
+ -1);
+ gtk_tree_model_get (proxy->model, iter,
+ EV_DOCUMENT_LINKS_COLUMN_LINK, &link,
+ -1);
+
+
+ if (link) {
+ text = ev_link_get_title (link);
+ g_object_unref (link);
+ }
+
+ gtk_tree_iter_free (iter);
+
+ if (text && key ) {
+ gchar *normalized_text;
+ gchar *normalized_key;
+ gchar *case_normalized_text;
+ gchar *case_normalized_key;
+ gboolean retval = FALSE;
+
+ normalized_text = g_utf8_normalize (text, -1, G_NORMALIZE_ALL);
+ normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
+ case_normalized_text = g_utf8_casefold (normalized_text, -1);
+ case_normalized_key = g_utf8_casefold (normalized_key, -1);
+
+ if (strstr (case_normalized_text, case_normalized_key))
+ retval = TRUE;
+
+ g_free (normalized_text);
+ g_free (normalized_key);
+ g_free (case_normalized_text);
+ g_free (case_normalized_key);
+
+ return retval;
+ }
+
+ return FALSE;
+}
+
+
+static void
+update_model (EvPageAction *page, GParamSpec *pspec, EvPageActionWidget *proxy)
+{
+ GtkTreeModel *model;
+ GtkTreeModel *filter_model;
+
+ g_object_get (G_OBJECT (page),
+ "model", &model,
+ NULL);
+ if (model != NULL) {
+ /* Magik */
+ GtkEntryCompletion *completion;
+ GtkCellRenderer *renderer;
+
+ proxy->model = model;
+ filter_model = get_filter_model_from_model (model);
+
+ completion = gtk_entry_completion_new ();
+
+ /* popup-set-width is 2.7.0 only */
+ g_object_set (G_OBJECT (completion),
+ "popup-set-width", FALSE,
+ "model", filter_model,
+ NULL);
+
+ g_signal_connect (completion, "match-selected", G_CALLBACK (match_selected_cb), proxy);
+ gtk_entry_completion_set_match_func (completion,
+ (GtkEntryCompletionMatchFunc) match_completion,
+ proxy, NULL);
+
+ /* Set up the layout */
+ renderer = (GtkCellRenderer *)
+ g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ "width_chars", 30,
+ NULL);
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), renderer, TRUE);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (completion),
+ renderer,
+ (GtkCellLayoutDataFunc) display_completion_text,
+ proxy, NULL);
+ gtk_entry_set_completion (GTK_ENTRY (proxy->entry), completion);
+
+ g_object_unref (completion);
+ g_object_unref (model);
+ }
+}
+
+static void
+activate_link_cb (EvPageActionWidget *proxy, EvLink *link, EvPageAction *action)
+{
+ g_signal_emit (action, signals[ACTIVATE_LINK], 0, link);