[gnome-builder] egg: add suggestion test
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] egg: add suggestion test
- Date: Fri, 7 Apr 2017 21:56:28 +0000 (UTC)
commit 367544529e721d0ce2a411493650094408595c66
Author: Christian Hergert <chergert redhat com>
Date: Fri Apr 7 14:44:52 2017 -0700
egg: add suggestion test
contrib/Makefile.am | 2 +-
contrib/egg/Makefile.am | 17 ++
contrib/egg/test-suggestion.c | 325 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 343 insertions(+), 1 deletions(-)
---
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
index 201cc96..7f862e3 100644
--- a/contrib/Makefile.am
+++ b/contrib/Makefile.am
@@ -1,4 +1,5 @@
SUBDIRS = \
+ search \
egg \
gd \
libeditorconfig \
@@ -6,7 +7,6 @@ SUBDIRS = \
nautilus \
pnl \
rg \
- search \
gstyle \
tmpl \
xml \
diff --git a/contrib/egg/Makefile.am b/contrib/egg/Makefile.am
index 4f6d592..03a2294 100644
--- a/contrib/egg/Makefile.am
+++ b/contrib/egg/Makefile.am
@@ -122,6 +122,23 @@ test_suggestion_buffer_CFLAGS = $(EGG_CFLAGS)
test_suggestion_buffer_LDADD = $(EGG_LIBS) libegg-private.la
+if ENABLE_WEBKIT
+noinst_PROGRAMS += test-suggestion
+test_suggestion_SOURCES = test-suggestion.c
+test_suggestion_CFLAGS = \
+ $(EGG_CFLAGS) \
+ $(WEBKIT_CFLAGS) \
+ -I$(top_srcdir)/contrib/search \
+ $(NULL)
+test_suggestion_LDADD = \
+ $(EGG_LIBS) \
+ $(WEBKIT_LIBS) \
+ libegg-private.la \
+ $(top_builddir)/contrib/search/libsearch.la \
+ $(NULL)
+endif
+
+
if HAVE_INTROSPECTION
-include $(INTROSPECTION_MAKEFILE)
diff --git a/contrib/egg/test-suggestion.c b/contrib/egg/test-suggestion.c
new file mode 100644
index 0000000..c3bd830
--- /dev/null
+++ b/contrib/egg/test-suggestion.c
@@ -0,0 +1,325 @@
+/* test-suggestion.c
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <webkit2/webkit2.h>
+
+#include "egg-suggestion.h"
+#include "egg-suggestion-entry.h"
+#include "fuzzy.h"
+
+/*
+ * Most of this is exactly how you SHOULD NOT write a web browser
+ * shell. It's just dummy code to test the suggestions widget.
+ * Think for yourself before copying any of this code.
+ */
+
+typedef struct
+{
+ const gchar *icon_name;
+ const gchar *url;
+ const gchar *title;
+ const gchar *suffix;
+} DemoData;
+
+static Fuzzy *search_index;
+static const DemoData demo_data[] = {
+ { NULL, "https://twitter.com", "Twitter", "twitter.com" },
+ { NULL, "https://facebook.com", "Facebook", "facebook.com" },
+ { NULL, "https://google.com", "Google", "google.com" },
+ { NULL, "https://images.google.com", "Google Images", "images.google.com" },
+ { NULL, "https://news.ycombinator.com", "Hacker News", "news.ycombinator.com" },
+ { NULL, "https://reddit.com/r/gnome", "GNOME Desktop Environment", "reddit.com/r/gnome" },
+ { NULL, "https://reddit.com/r/linux", "Linux, GNU/Linux, free software", "reddit.com/r/linux" },
+ { NULL, "https://wiki.gnome.org", "GNOME Wiki", "wiki.gnome.org" },
+ { NULL, "https://gnome.org", "GNOME", "gnome.org" },
+ { NULL, "https://planet.gnome.org", "Planet GNOME", "planet.gnome.org" },
+ { NULL, "https://wiki.gnome.org/Apps/Builder", "GNOME Builder", "wiki.gnome.org/Apps/Builder" },
+};
+
+static void
+take_item (GListStore *store,
+ EggSuggestion *suggestion)
+{
+ g_list_store_append (store, suggestion);
+ g_object_unref (suggestion);
+}
+
+static gboolean
+is_a_url (const gchar *str)
+{
+ /* you obviously want something better */
+
+ if (strstr (str, ".com") ||
+ strstr (str, ".net") ||
+ strstr (str, ".org") ||
+ strstr (str, ".io") ||
+ strstr (str, ".ly"))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gint
+compare_match (gconstpointer a,
+ gconstpointer b)
+{
+ const FuzzyMatch *match_a = a;
+ const FuzzyMatch *match_b = b;
+
+ if (match_a->score < match_b->score)
+ return 1;
+ else if (match_a->score > match_b->score)
+ return -1;
+ else
+ return 0;
+}
+
+static gchar *
+suggest_suffix (EggSuggestion *suggestion,
+ const gchar *typed_text,
+ const DemoData *data)
+{
+ //g_print ("Suffix: Typed_Text=%s\n", typed_text);
+
+ if (g_str_has_prefix (data->suffix, typed_text))
+ return g_strdup (data->suffix + strlen (typed_text));
+
+ return NULL;
+}
+
+static gchar *
+replace_typed_text (EggSuggestion *suggestion,
+ const gchar *typed_text,
+ const DemoData *data)
+{
+ return g_strdup (data->url);
+}
+
+static GListModel *
+create_search_results (const gchar *full_query,
+ const gchar *query)
+{
+ GListStore *store = g_list_store_new (EGG_TYPE_SUGGESTION);
+ g_autoptr(GArray) matches = NULL;
+ g_autofree gchar *search_url = NULL;
+ g_autofree gchar *with_slashes = g_strdup_printf ("://%s", query);
+ gboolean exact = FALSE;
+
+ matches = fuzzy_match (search_index, query, 20);
+
+ g_array_sort (matches, compare_match);
+
+ for (guint i = 0; i < matches->len; i++)
+ {
+ const FuzzyMatch *match = &g_array_index (matches, FuzzyMatch, i);
+ const DemoData *data = match->value;
+ g_autofree gchar *markup = NULL;
+ EggSuggestion *item;
+
+ markup = fuzzy_highlight (search_index, data->url, query);
+
+ if (g_str_has_suffix (data->url, with_slashes))
+ exact = TRUE;
+
+ item = g_object_new (EGG_TYPE_SUGGESTION,
+ "id", data->url,
+ "icon-name", data->icon_name,
+ "title", markup,
+ "subtitle", data->title,
+ NULL);
+ g_signal_connect (item, "suggest-suffix", G_CALLBACK (suggest_suffix), (gpointer)data);
+ g_signal_connect (item, "replace-typed-text", G_CALLBACK (replace_typed_text), (gpointer)data);
+ take_item (store, item);
+ }
+
+ if (!exact && is_a_url (full_query))
+ {
+ g_autofree gchar *url = g_strdup_printf ("http://%s", full_query);
+ take_item (store,
+ g_object_new (EGG_TYPE_SUGGESTION,
+ "id", url,
+ "icon-name", NULL,
+ "title", query,
+ "subtitle", NULL,
+ NULL));
+ }
+
+ search_url = g_strdup_printf ("https://www.google.com/search?q=%s", full_query);
+ take_item (store,
+ g_object_new (EGG_TYPE_SUGGESTION,
+ "id", search_url,
+ "title", full_query,
+ "subtitle", "Google Search",
+ "icon-name", "edit-find-symbolic",
+ NULL));
+
+ return G_LIST_MODEL (store);
+}
+
+static gboolean
+key_press (GtkWidget *widget,
+ GdkEventKey *key,
+ GtkEntry *param)
+{
+ if (key->keyval == GDK_KEY_l && (key->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
+ {
+ gtk_widget_grab_focus (GTK_WIDGET (param));
+ gtk_editable_select_region (GTK_EDITABLE (param), 0, -1);
+ }
+ else if (key->keyval == GDK_KEY_w && (key->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
+ gtk_window_close (GTK_WINDOW (widget));
+
+ return FALSE;
+}
+
+static void
+search_changed (EggSuggestionEntry *entry,
+ gpointer user_data)
+{
+ g_autoptr(GListModel) model = NULL;
+ GString *str = g_string_new (NULL);
+ const gchar *text;
+
+ g_assert (EGG_IS_SUGGESTION_ENTRY (entry));
+
+ text = egg_suggestion_entry_get_typed_text (entry);
+
+ for (const gchar *iter = text; *iter; iter = g_utf8_next_char (iter))
+ {
+ gunichar ch = g_utf8_get_char (iter);
+
+ if (!g_unichar_isspace (ch))
+ g_string_append_unichar (str, ch);
+ }
+
+ if (str->len)
+ model = create_search_results (text, str->str);
+
+ egg_suggestion_entry_set_model (entry, model);
+}
+
+static void
+suggestion_activated (EggSuggestionEntry *entry,
+ EggSuggestion *suggestion,
+ WebKitWebView *webview)
+{
+ const gchar *uri = egg_suggestion_get_id (suggestion);
+
+ g_print ("Activated suggestion: %s\n", uri);
+
+ gtk_widget_grab_focus (GTK_WIDGET (webview));
+ webkit_web_view_load_uri (webview, uri);
+ gtk_entry_set_text (GTK_ENTRY (entry), uri);
+}
+
+static void
+notify_uri_cb (WebKitWebView *webview,
+ GParamSpec *pspec,
+ EggSuggestionEntry *entry)
+{
+ const gchar *uri;
+
+ g_assert (WEBKIT_IS_WEB_VIEW (webview));
+ g_assert (EGG_IS_SUGGESTION_ENTRY (entry));
+
+ uri = webkit_web_view_get_uri (webview);
+
+ gtk_entry_set_text (GTK_ENTRY (entry), uri);
+}
+
+int
+main (gint argc,
+ gchar *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *header;
+ GtkWidget *entry;
+ GtkWidget *box;
+ GtkWidget *button;
+ GtkWidget *webkit;
+
+ gtk_init (&argc, &argv);
+
+ search_index = fuzzy_new (FALSE);
+
+ for (guint i = 0; i < G_N_ELEMENTS (demo_data); i++)
+ {
+ const DemoData *data = &demo_data[i];
+
+ fuzzy_insert (search_index, data->url, (gpointer)data);
+ }
+
+ window = g_object_new (GTK_TYPE_WINDOW,
+ "default-width", 1100,
+ "default-height", 600,
+ NULL);
+ header = g_object_new (GTK_TYPE_HEADER_BAR,
+ "show-close-button", TRUE,
+ "visible", TRUE,
+ NULL);
+
+ webkit = g_object_new (WEBKIT_TYPE_WEB_VIEW,
+ "visible", TRUE,
+ NULL);
+ webkit_web_view_load_html (WEBKIT_WEB_VIEW (webkit),
+ "<html><body style='background: #4a86cf;'></body></html>",
+ NULL);
+ gtk_container_add (GTK_CONTAINER (window), webkit);
+
+ box = g_object_new (GTK_TYPE_BOX,
+ "orientation", GTK_ORIENTATION_HORIZONTAL,
+ "visible", TRUE,
+ "spacing", 0,
+ NULL);
+ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (box)), "linked");
+
+ entry = g_object_new (EGG_TYPE_SUGGESTION_ENTRY,
+ "halign", GTK_ALIGN_CENTER,
+ "hexpand", FALSE,
+ "max-width-chars", 55,
+ "visible", TRUE,
+ "width-chars", 30,
+ NULL);
+ gtk_box_set_center_widget (GTK_BOX (box), entry);
+ g_signal_connect (entry, "changed", G_CALLBACK (search_changed), NULL);
+ g_signal_connect (entry, "suggestion-activated", G_CALLBACK (suggestion_activated), webkit);
+
+ button = g_object_new (GTK_TYPE_BUTTON,
+ "halign", GTK_ALIGN_START,
+ "hexpand", FALSE,
+ "visible", TRUE,
+ "child", g_object_new (GTK_TYPE_IMAGE,
+ "visible", TRUE,
+ "icon-name", "web-browser-symbolic",
+ NULL),
+ NULL);
+ gtk_box_pack_end (GTK_BOX (box), button, FALSE, FALSE, 0);
+
+ gtk_window_set_titlebar (GTK_WINDOW (window), header);
+ gtk_header_bar_set_custom_title (GTK_HEADER_BAR (header), box);
+
+ g_signal_connect (webkit, "notify::uri", G_CALLBACK (notify_uri_cb), entry);
+ g_signal_connect (window, "delete-event", gtk_main_quit, NULL);
+ g_signal_connect (window, "key-press-event", G_CALLBACK (key_press), entry);
+ gtk_window_present (GTK_WINDOW (window));
+
+ gtk_main ();
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]