From 5bd7606103182a824b530a24a1f4753e04c145ec Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 23 Jun 2015 23:22:42 +0100 Subject: Update GTK url bar completion to navigate on selection --- gtk/completion.c | 140 ++++++++++++++++++++++++++++++++++++++++++------------ gtk/completion.h | 30 ++++++++---- gtk/scaffolding.c | 32 ++++--------- 3 files changed, 142 insertions(+), 60 deletions(-) (limited to 'gtk') diff --git a/gtk/completion.c b/gtk/completion.c index a0df08ad9..1f86cc790 100644 --- a/gtk/completion.c +++ b/gtk/completion.c @@ -16,47 +16,48 @@ * along with this program. If not, see . */ +/** + * \file + * Implementation of url entry completion. + */ + #include -#include "gtk/completion.h" #include "content/urldb.h" #include "utils/log.h" +#include "utils/messages.h" +#include "utils/utils.h" #include "utils/nsoption.h" +#include "desktop/searchweb.h" +#include "desktop/browser.h" -GtkListStore *nsgtk_completion_list; - -static void nsgtk_completion_empty(void); -static bool nsgtk_completion_udb_callback(nsurl *url, - const struct url_data *data); - -void nsgtk_completion_init(void) -{ - nsgtk_completion_list = gtk_list_store_new(1, G_TYPE_STRING); +#include "gtk/window.h" +#include "gtk/completion.h" -} +GtkListStore *nsgtk_completion_list; -gboolean nsgtk_completion_match(GtkEntryCompletion *completion, - const gchar *key, - GtkTreeIter *iter, - gpointer user_data) +/** + * completion row matcher + */ +static gboolean nsgtk_completion_match(GtkEntryCompletion *completion, + const gchar *key, + GtkTreeIter *iter, + gpointer user_data) { - char *b[4096]; /* no way of finding out its length :( */ - gtk_tree_model_get(GTK_TREE_MODEL(nsgtk_completion_list), iter, - 0, b, -1); - - /* TODO: work out why this works, when there's no code to implement - * it. I boggle. */ - + /* the completion list is modified to only contain valid + * entries so this simply returns TRUE to indicate all rows + * are in the list should be shown. + */ return TRUE; } -void nsgtk_completion_empty(void) -{ - gtk_list_store_clear(nsgtk_completion_list); -} -bool nsgtk_completion_udb_callback(nsurl *url, const struct url_data *data) +/** + * callback for each entry to add to completion list + */ +static bool +nsgtk_completion_udb_callback(nsurl *url, const struct url_data *data) { GtkTreeIter iter; @@ -68,10 +69,89 @@ bool nsgtk_completion_udb_callback(nsurl *url, const struct url_data *data) return true; } -void nsgtk_completion_update(const char *prefix) +/** + * event handler for when a completion suggestion is selected. + */ +static gboolean +nsgtk_completion_match_select(GtkEntryCompletion *widget, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer user_data) +{ + GValue value = {0, }; + struct nsgtk_scaffolding *g = user_data; + struct browser_window *bw = nsgtk_get_browser_window(nsgtk_scaffolding_top_level(g)); + nserror ret; + nsurl *url; + + gtk_tree_model_get_value(model, iter, 0, &value); + + ret = search_web_omni(g_value_get_string(&value), + SEARCH_WEB_OMNI_NONE, + &url); + + g_value_unset(&value); + + if (ret == NSERROR_OK) { + ret = browser_window_navigate(bw, + url, NULL, BW_NAVIGATE_HISTORY, + NULL, NULL, NULL); + nsurl_unref(url); + } + if (ret != NSERROR_OK) { + warn_user(messages_get_errorcode(ret), 0); + } + + return TRUE; +} + +/* exported interface documented in completion.h */ +void nsgtk_completion_init(void) { - nsgtk_completion_empty(); + nsgtk_completion_list = gtk_list_store_new(1, G_TYPE_STRING); + +} + +/* exported interface documented in completion.h */ +gboolean nsgtk_completion_update(GtkEntry *entry) +{ + gtk_list_store_clear(nsgtk_completion_list); + if (nsoption_bool(url_suggestion) == true) { - urldb_iterate_partial(prefix, nsgtk_completion_udb_callback); + urldb_iterate_partial(gtk_entry_get_text(entry), + nsgtk_completion_udb_callback); } + + return TRUE; +} + +/* exported interface documented in completion.h */ +GtkEntryCompletion *nsgtk_url_entry_completion_new(struct nsgtk_scaffolding *gs) +{ + GtkEntryCompletion *completion; + + completion = gtk_entry_completion_new(); + gtk_entry_completion_set_match_func(completion, + nsgtk_completion_match, NULL, NULL); + + gtk_entry_completion_set_model(completion, + GTK_TREE_MODEL(nsgtk_completion_list)); + + gtk_entry_completion_set_text_column(completion, 0); + + gtk_entry_completion_set_minimum_key_length(completion, 1); + + /* enable popup for completion */ + gtk_entry_completion_set_popup_completion(completion, TRUE); + + /* when selected callback */ + g_signal_connect(G_OBJECT(completion), "match-selected", + G_CALLBACK(nsgtk_completion_match_select), gs); + + g_object_set(G_OBJECT(completion), + "popup-set-width", TRUE, + "popup-single-match", TRUE, + NULL); + + return completion; } diff --git a/gtk/completion.h b/gtk/completion.h index 67de43d8e..9a1db293d 100644 --- a/gtk/completion.h +++ b/gtk/completion.h @@ -16,17 +16,31 @@ * along with this program. If not, see . */ +/** + * \file + * Interface to url entry completion. + */ + #ifndef _NETSURF_GTK_COMPLETION_H_ #define _NETSURF_GTK_COMPLETION_H_ -#include - -extern GtkListStore *nsgtk_completion_list; +struct nsgtk_scaffolding; +/** + * initialise completion list store + */ void nsgtk_completion_init(void); -void nsgtk_completion_update(const char *prefix); -gboolean nsgtk_completion_match(GtkEntryCompletion *completion, - const gchar *key, - GtkTreeIter *iter, - gpointer user_data); + +/** + * update completion list store. + */ +gboolean nsgtk_completion_update(GtkEntry *entry); + +/** + * create a new entry completion on a scaffold. + * + * \param gs The scaffoliding which the url entry is in. + */ +GtkEntryCompletion *nsgtk_url_entry_completion_new(struct nsgtk_scaffolding *gs); + #endif diff --git a/gtk/scaffolding.c b/gtk/scaffolding.c index a45224c81..215fe1a05 100644 --- a/gtk/scaffolding.c +++ b/gtk/scaffolding.c @@ -401,16 +401,15 @@ gboolean nsgtk_window_url_activate_event(GtkWidget *widget, gpointer data) return TRUE; } - -gboolean nsgtk_window_url_changed(GtkWidget *widget, GdkEventKey *event, - gpointer data) +/** + * update handler for URL entry widget + */ +gboolean +nsgtk_window_url_changed(GtkWidget *widget, + GdkEventKey *event, + gpointer data) { - const char *prefix; - - prefix = gtk_entry_get_text(GTK_ENTRY(widget)); - nsgtk_completion_update(prefix); - - return TRUE; + return nsgtk_completion_update(GTK_ENTRY(widget)); } /** @@ -2165,7 +2164,7 @@ struct nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) gtk_widget_set_size_request(GTK_WIDGET( gs->buttons[HISTORY_BUTTON]->button), 20, -1); - /* create the local history window to be associated with this browser */ + /* create the local history window to be associated with this scaffold */ gs->history_window = malloc(sizeof(struct gtk_history_window)); gs->history_window->g = gs; gs->history_window->window = @@ -2196,18 +2195,7 @@ struct nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) /* set up URL bar completion */ - gs->url_bar_completion = gtk_entry_completion_new(); - gtk_entry_completion_set_match_func(gs->url_bar_completion, - nsgtk_completion_match, NULL, NULL); - gtk_entry_completion_set_model(gs->url_bar_completion, - GTK_TREE_MODEL(nsgtk_completion_list)); - gtk_entry_completion_set_text_column(gs->url_bar_completion, 0); - gtk_entry_completion_set_minimum_key_length(gs->url_bar_completion, 1); - gtk_entry_completion_set_popup_completion(gs->url_bar_completion, TRUE); - g_object_set(G_OBJECT(gs->url_bar_completion), - "popup-set-width", TRUE, - "popup-single-match", TRUE, - NULL); + gs->url_bar_completion = nsgtk_url_entry_completion_new(gs); /* set up the throbber. */ gs->throb_frame = 0; -- cgit v1.2.3