summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Catanzaro <mcatanzaro@igalia.com>2017-11-22 17:51:31 -0600
committerMichael Catanzaro <mcatanzaro@igalia.com>2017-11-22 17:51:31 -0600
commit513727c50807df004c985be4cc03191655d53fb3 (patch)
tree8b7e810615e6050fd1897d80b3dc12d273337a61
parentdf1db5026cef1343d33e11a1bd370b41ea1eeb14 (diff)
downloadepiphany-wip/libdazzle.tar.gz
Revert "Stop using DzlSuggestionEntry for now"wip/libdazzle
This reverts commit df1db5026cef1343d33e11a1bd370b41ea1eeb14.
-rw-r--r--embed/ephy-embed-shell.c3
-rw-r--r--embed/ephy-embed-shell.h5
-rw-r--r--embed/meson.build1
-rw-r--r--lib/ephy-suggestion.c174
-rw-r--r--lib/ephy-suggestion.h37
-rw-r--r--lib/meson.build2
-rw-r--r--lib/widgets/contrib/gd-two-lines-renderer.c621
-rw-r--r--lib/widgets/contrib/gd-two-lines-renderer.h75
-rw-r--r--lib/widgets/ephy-location-entry.c378
-rw-r--r--lib/widgets/ephy-location-entry.h20
-rw-r--r--lib/widgets/meson.build2
-rw-r--r--meson.build1
-rw-r--r--org.gnome.Epiphany.json12
-rw-r--r--src/ephy-completion-model.c625
-rw-r--r--src/ephy-completion-model.h53
-rw-r--r--src/ephy-location-controller.c133
-rw-r--r--src/ephy-suggestion-model.c476
-rw-r--r--src/ephy-suggestion-model.h46
-rw-r--r--src/ephy-window.c22
-rw-r--r--src/ephy-window.h3
-rw-r--r--src/meson.build3
-rw-r--r--src/search-provider/ephy-search-provider.c121
-rw-r--r--tests/ephy-completion-model-test.c101
-rw-r--r--tests/ephy-location-entry-test.c160
-rw-r--r--tests/meson.build14
25 files changed, 868 insertions, 2220 deletions
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index d0751ff33..0c1d38a1a 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -43,6 +43,7 @@
#include "ephy-web-app-utils.h"
#include "ephy-web-extension-proxy.h"
+#include <dazzle.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <stdlib.h>
@@ -103,7 +104,7 @@ static EphyEmbedShell *embed_shell = NULL;
static void ephy_embed_shell_tabs_catalog_iface_init (EphyTabsCatalogInterface *iface);
-G_DEFINE_TYPE_WITH_CODE (EphyEmbedShell, ephy_embed_shell, GTK_TYPE_APPLICATION,
+G_DEFINE_TYPE_WITH_CODE (EphyEmbedShell, ephy_embed_shell, DZL_TYPE_APPLICATION,
G_ADD_PRIVATE (EphyEmbedShell)
G_IMPLEMENT_INTERFACE (EPHY_TYPE_TABS_CATALOG,
ephy_embed_shell_tabs_catalog_iface_init))
diff --git a/embed/ephy-embed-shell.h b/embed/ephy-embed-shell.h
index c933d5037..c5b5dfd97 100644
--- a/embed/ephy-embed-shell.h
+++ b/embed/ephy-embed-shell.h
@@ -21,6 +21,7 @@
#pragma once
+#include <dazzle.h>
#include <webkit2/webkit2.h>
#include "ephy-downloads-manager.h"
@@ -34,7 +35,7 @@ G_BEGIN_DECLS
#define EPHY_TYPE_EMBED_SHELL (ephy_embed_shell_get_type ())
-G_DECLARE_DERIVABLE_TYPE (EphyEmbedShell, ephy_embed_shell, EPHY, EMBED_SHELL, GtkApplication)
+G_DECLARE_DERIVABLE_TYPE (EphyEmbedShell, ephy_embed_shell, EPHY, EMBED_SHELL, DzlApplication)
typedef enum
{
@@ -49,7 +50,7 @@ typedef enum
struct _EphyEmbedShellClass
{
- GtkApplicationClass parent_class;
+ DzlApplicationClass parent_class;
void (* restored_window) (EphyEmbedShell *shell);
};
diff --git a/embed/meson.build b/embed/meson.build
index 1f924f255..99315d704 100644
--- a/embed/meson.build
+++ b/embed/meson.build
@@ -37,6 +37,7 @@ libephyembed_deps = [
glib_dep,
gtk_dep,
icu_uc_dep,
+ libdazzle_dep,
libsecret_dep,
libsoup_dep,
m_dep,
diff --git a/lib/ephy-suggestion.c b/lib/ephy-suggestion.c
new file mode 100644
index 000000000..aefbf8a8a
--- /dev/null
+++ b/lib/ephy-suggestion.c
@@ -0,0 +1,174 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Igalia S.L.
+ *
+ * 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 "config.h"
+#include "ephy-suggestion.h"
+
+#include "ephy-uri-helpers.h"
+
+#include <dazzle.h>
+#include <glib.h>
+
+struct _EphySuggestion {
+ DzlSuggestion parent;
+
+ char *unescaped_title;
+};
+
+G_DEFINE_TYPE (EphySuggestion, ephy_suggestion, DZL_TYPE_SUGGESTION)
+
+enum {
+ PROP_0,
+ PROP_UNESCAPED_TITLE,
+ LAST_PROP
+};
+
+static GParamSpec *obj_properties[LAST_PROP];
+
+static void
+ephy_suggestion_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphySuggestion *self = EPHY_SUGGESTION (object);
+
+ switch (prop_id) {
+ case PROP_UNESCAPED_TITLE:
+ self->unescaped_title = g_strdup (g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_suggestion_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphySuggestion *self = EPHY_SUGGESTION (object);
+
+ switch (prop_id) {
+ case PROP_UNESCAPED_TITLE:
+ g_value_set_string (value, self->unescaped_title);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+char *
+ephy_suggestion_replace_typed_text (DzlSuggestion *self,
+ const char *typed_text)
+{
+ const char *url;
+
+ g_assert (EPHY_IS_SUGGESTION (self));
+
+ url = ephy_suggestion_get_uri (EPHY_SUGGESTION (self));
+
+ return g_strdup (url);
+}
+
+static void
+ephy_suggestion_class_init (EphySuggestionClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ DzlSuggestionClass *dzl_suggestion_class = DZL_SUGGESTION_CLASS (klass);
+
+ object_class->get_property = ephy_suggestion_get_property;
+ object_class->set_property = ephy_suggestion_set_property;
+
+ dzl_suggestion_class->replace_typed_text = ephy_suggestion_replace_typed_text;
+
+ obj_properties[PROP_UNESCAPED_TITLE] =
+ g_param_spec_string ("unescaped-title",
+ "Unescaped title",
+ "The title of the suggestion, not XML-escaped",
+ "",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+}
+
+static void
+ephy_suggestion_init (EphySuggestion *self)
+{
+}
+
+EphySuggestion *
+ephy_suggestion_new (const char *title,
+ const char *uri)
+{
+ EphySuggestion *suggestion;
+ char *escaped_title = g_markup_escape_text (title, -1);
+ char *decoded_uri = ephy_uri_decode (uri);
+ char *escaped_uri = g_markup_escape_text (decoded_uri, -1);
+
+ suggestion = g_object_new (EPHY_TYPE_SUGGESTION,
+ "icon-name", "web-browser-symbolic",
+ "id", uri,
+ "subtitle", escaped_uri,
+ "title", escaped_title,
+ "unescaped-title", title,
+ NULL);
+
+ g_free (escaped_title);
+ g_free (decoded_uri);
+ g_free (escaped_uri);
+
+ return suggestion;
+}
+
+EphySuggestion *
+ephy_suggestion_new_without_subtitle (const char *title,
+ const char *uri)
+{
+ EphySuggestion *suggestion;
+ char *escaped_title;
+
+ escaped_title = g_markup_escape_text (title, -1);
+ suggestion = g_object_new (EPHY_TYPE_SUGGESTION,
+ "icon-name", "web-browser-symbolic",
+ "id", uri,
+ "title", escaped_title,
+ "unescaped-title", title,
+ NULL);
+
+ g_free (escaped_title);
+
+ return suggestion;
+}
+
+const char *
+ephy_suggestion_get_unescaped_title (EphySuggestion *self)
+{
+ g_assert (EPHY_IS_SUGGESTION (self));
+
+ return self->unescaped_title;
+}
+
+const char *
+ephy_suggestion_get_uri (EphySuggestion *self)
+{
+ g_assert (EPHY_IS_SUGGESTION (self));
+
+ return dzl_suggestion_get_id (DZL_SUGGESTION (self));
+}
diff --git a/lib/ephy-suggestion.h b/lib/ephy-suggestion.h
new file mode 100644
index 000000000..c35edcf2c
--- /dev/null
+++ b/lib/ephy-suggestion.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Igalia S.L.
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include <dazzle.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_SUGGESTION (ephy_suggestion_get_type())
+
+G_DECLARE_FINAL_TYPE (EphySuggestion, ephy_suggestion, EPHY, SUGGESTION, DzlSuggestion)
+
+// FIXME: How about favicon?
+EphySuggestion *ephy_suggestion_new (const char *title,
+ const char *uri);
+EphySuggestion *ephy_suggestion_new_without_subtitle (const char *title,
+ const char *uri);
+const char *ephy_suggestion_get_unescaped_title (EphySuggestion *self);
+const char *ephy_suggestion_get_uri (EphySuggestion *self);
+
+G_END_DECLS
diff --git a/lib/meson.build b/lib/meson.build
index 298dd7e2d..b9f5d8e77 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -33,6 +33,7 @@ libephymisc_sources = [
'ephy-sqlite-connection.c',
'ephy-sqlite-statement.c',
'ephy-string.c',
+ 'ephy-suggestion.c',
'ephy-sync-utils.c',
'ephy-time-helpers.c',
'ephy-uri-helpers.c',
@@ -61,6 +62,7 @@ libephymisc_deps = [
gtk_dep,
icu_uc_dep,
json_glib_dep,
+ libdazzle_dep,
libsecret_dep,
libsoup_dep,
libxml_dep,
diff --git a/lib/widgets/contrib/gd-two-lines-renderer.c b/lib/widgets/contrib/gd-two-lines-renderer.c
deleted file mode 100644
index 5a029f7f2..000000000
--- a/lib/widgets/contrib/gd-two-lines-renderer.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * Copyright (c) 2011 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 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 Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Cosimo Cecchi <cosimoc@redhat.com>
- *
- */
-
-#include "gd-two-lines-renderer.h"
-#include <string.h>
-
-#define SUBTITLE_DIM_PERCENTAGE 0.55
-#define SUBTITLE_SIZE_PERCENTAGE 0.82
-
-G_DEFINE_TYPE (GdTwoLinesRenderer, gd_two_lines_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
-
-struct _GdTwoLinesRendererPrivate {
- gchar *line_two;
- gint text_lines;
-};
-
-enum {
- PROP_TEXT_LINES = 1,
- PROP_LINE_TWO,
- NUM_PROPERTIES
-};
-
-static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
-
-static PangoLayout *
-create_layout_with_attrs (GtkWidget *widget,
- const GdkRectangle *cell_area,
- GdTwoLinesRenderer *self,
- PangoEllipsizeMode ellipsize)
-{
- PangoLayout *layout;
- gint wrap_width, xpad;
- PangoWrapMode wrap_mode;
- PangoAlignment alignment;
-
- g_object_get (self,
- "wrap-width", &wrap_width,
- "wrap-mode", &wrap_mode,
- "alignment", &alignment,
- "xpad", &xpad,
- NULL);
-
- layout = pango_layout_new (gtk_widget_get_pango_context (widget));
-
- pango_layout_set_ellipsize (layout, ellipsize);
- pango_layout_set_alignment (layout, alignment);
-
- if (wrap_width != -1)
- {
- pango_layout_set_width (layout, wrap_width * PANGO_SCALE);
- pango_layout_set_wrap (layout, wrap_mode);
- }
- else
- {
- if (cell_area != NULL)
- pango_layout_set_width (layout, (cell_area->width - 2 * xpad) * PANGO_SCALE);
- else
- pango_layout_set_width (layout, -1);
-
- pango_layout_set_wrap (layout, PANGO_WRAP_CHAR);
- }
-
- return layout;
-}
-
-static void
-apply_subtitle_style_to_layout (GtkStyleContext *context,
- PangoLayout *layout,
- GtkStateFlags flags)
-{
- PangoFontDescription *desc;
- PangoAttrList *layout_attr;
- PangoAttribute *attr_alpha;
-
- gtk_style_context_save (context);
- gtk_style_context_set_state (context, flags);
- gtk_style_context_get (context, gtk_style_context_get_state (context),
- "font", &desc,
- NULL);
- gtk_style_context_restore (context);
-
- /* Set the font size */
- pango_font_description_set_size (desc, pango_font_description_get_size (desc) * SUBTITLE_SIZE_PERCENTAGE);
- pango_layout_set_font_description (layout, desc);
- pango_font_description_free (desc);
-
- /* Set the font alpha */
- layout_attr = pango_attr_list_new ();
- attr_alpha = pango_attr_foreground_alpha_new (SUBTITLE_DIM_PERCENTAGE * 65535);
- pango_attr_list_insert (layout_attr, attr_alpha);
-
- pango_layout_set_attributes (layout, layout_attr);
- pango_attr_list_unref (layout_attr);
-}
-
-static void
-gd_two_lines_renderer_prepare_layouts (GdTwoLinesRenderer *self,
- const GdkRectangle *cell_area,
- GtkWidget *widget,
- PangoLayout **layout_one,
- PangoLayout **layout_two)
-{
- PangoLayout *line_one;
- PangoLayout *line_two = NULL;
- gchar *text = NULL;
-
- g_object_get (self,
- "text", &text,
- NULL);
-
- line_one = create_layout_with_attrs (widget, cell_area,
- self, PANGO_ELLIPSIZE_MIDDLE);
-
- if (self->priv->line_two == NULL ||
- g_strcmp0 (self->priv->line_two, "") == 0)
- {
- pango_layout_set_height (line_one, - (self->priv->text_lines));
-
- if (text != NULL)
- pango_layout_set_text (line_one, text, -1);
- }
- else
- {
- GtkStyleContext *context;
-
- line_two = create_layout_with_attrs (widget, cell_area,
- self, PANGO_ELLIPSIZE_END);
-
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_save (context);
- apply_subtitle_style_to_layout (context, line_two, GTK_STATE_FLAG_NORMAL);
- gtk_style_context_restore (context);
-
- pango_layout_set_height (line_one, - (self->priv->text_lines - 1));
- pango_layout_set_height (line_two, -1);
- pango_layout_set_text (line_two, self->priv->line_two, -1);
-
- if (text != NULL)
- pango_layout_set_text (line_one, text, -1);
- }
-
- if (layout_one)
- *layout_one = line_one;
- if (layout_two)
- *layout_two = line_two;
-
- g_free (text);
-}
-
-static void
-gd_two_lines_renderer_get_size (GtkCellRenderer *cell,
- GtkWidget *widget,
- PangoLayout *layout_1,
- PangoLayout *layout_2,
- gint *width,
- gint *height,
- const GdkRectangle *cell_area,
- gint *x_offset_1,
- gint *x_offset_2,
- gint *y_offset)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
- gint xpad, ypad;
- PangoLayout *layout_one, *layout_two;
- GdkRectangle layout_one_rect, layout_two_rect, layout_union;
-
- if (layout_1 == NULL)
- {
- gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two);
- }
- else
- {
- layout_one = g_object_ref (layout_1);
-
- if (layout_2 != NULL)
- layout_two = g_object_ref (layout_2);
- else
- layout_two = NULL;
- }
-
- gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
- pango_layout_get_pixel_extents (layout_one, NULL, (PangoRectangle *) &layout_one_rect);
-
- if (layout_two != NULL)
- {
- pango_layout_get_pixel_extents (layout_two, NULL, (PangoRectangle *) &layout_two_rect);
-
- layout_union.width = MAX (layout_one_rect.width, layout_two_rect.width);
- layout_union.height = layout_one_rect.height + layout_two_rect.height;
- }
- else
- {
- layout_union = layout_one_rect;
- }
-
- if (cell_area)
- {
- gfloat xalign, yalign;
-
- gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
-
- layout_union.width = MIN (layout_union.width, cell_area->width - 2 * xpad);
- layout_union.height = MIN (layout_union.height, cell_area->height - 2 * ypad);
-
- if (x_offset_1)
- {
- if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
- *x_offset_1 = (1.0 - xalign) * (cell_area->width - (layout_one_rect.width + (2 * xpad)));
- else
- *x_offset_1 = xalign * (cell_area->width - (layout_one_rect.width + (2 * xpad)));
-
- *x_offset_1 = MAX (*x_offset_1, 0);
- }
- if (x_offset_2)
- {
- if (layout_two != NULL)
- {
- if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
- *x_offset_2 = (1.0 - xalign) * (cell_area->width - (layout_two_rect.width + (2 * xpad)));
- else
- *x_offset_2 = xalign * (cell_area->width - (layout_two_rect.width + (2 * xpad)));
-
- *x_offset_2 = MAX (*x_offset_2, 0);
- }
- else
- {
- *x_offset_2 = 0;
- }
- }
-
- if (y_offset)
- {
- *y_offset = yalign * (cell_area->height - (layout_union.height + (2 * ypad)));
- *y_offset = MAX (*y_offset, 0);
- }
- }
- else
- {
- if (x_offset_1) *x_offset_1 = 0;
- if (x_offset_2) *x_offset_2 = 0;
- if (y_offset) *y_offset = 0;
- }
-
- g_clear_object (&layout_one);
- g_clear_object (&layout_two);
-
- if (height)
- *height = ypad * 2 + layout_union.height;
-
- if (width)
- *width = xpad * 2 + layout_union.width;
-}
-
-static void
-gd_two_lines_renderer_render (GtkCellRenderer *cell,
- cairo_t *cr,
- GtkWidget *widget,
- const GdkRectangle *background_area,
- const GdkRectangle *cell_area,
- GtkCellRendererState flags)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
- GtkStyleContext *context;
- gint line_one_height;
- GtkStateFlags state;
- GdkRectangle area, render_area = *cell_area;
- gint xpad, ypad, x_offset_1, x_offset_2, y_offset;
- PangoLayout *layout_one, *layout_two;
- PangoRectangle layout_rect;
-
- /* fetch common information */
- context = gtk_widget_get_style_context (widget);
- gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two);
- gd_two_lines_renderer_get_size (cell, widget,
- layout_one, layout_two,
- NULL, NULL,
- cell_area,
- &x_offset_1, &x_offset_2, &y_offset);
- gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
-
- area = *cell_area;
- area.x += xpad;
- area.y += ypad;
-
- /* now render the first layout */
- pango_layout_get_pixel_extents (layout_one, NULL, &layout_rect);
-
- render_area = area;
- render_area.x += x_offset_1 - layout_rect.x;
-
- gtk_render_layout (context, cr,
- render_area.x,
- render_area.y,
- layout_one);
-
- /* render the second layout */
- if (layout_two != NULL)
- {
- pango_layout_get_pixel_size (layout_one,
- NULL, &line_one_height);
-
- gtk_style_context_save (context);
-
- apply_subtitle_style_to_layout (context, layout_two, flags);
-
- state = gtk_cell_renderer_get_state (cell, widget, flags);
- gtk_style_context_set_state (context, state);
-
- pango_layout_get_pixel_extents (layout_two, NULL, &layout_rect);
-
- render_area = area;
- render_area.x += x_offset_2 - layout_rect.x;
- render_area.y += line_one_height;
-
- gtk_render_layout (context, cr,
- render_area.x,
- render_area.y,
- layout_two);
-
- gtk_style_context_restore (context);
- }
-
- g_clear_object (&layout_one);
- g_clear_object (&layout_two);
-}
-
-static void
-gd_two_lines_renderer_get_preferred_width (GtkCellRenderer *cell,
- GtkWidget *widget,
- gint *minimum_size,
- gint *natural_size)
-{
- PangoContext *context;
- PangoFontMetrics *metrics;
- PangoFontDescription *font_desc;
- GtkStyleContext *style_context;
- gint nat_width, min_width;
- gint xpad, char_width, wrap_width, text_width;
- gint width_chars, ellipsize_chars;
-
- g_object_get (cell,
- "xpad", &xpad,
- "width-chars", &width_chars,
- "wrap-width", &wrap_width,
- NULL);
- style_context = gtk_widget_get_style_context (widget);
- gtk_cell_renderer_get_padding (cell, &xpad, NULL);
-
- gd_two_lines_renderer_get_size (cell, widget,
- NULL, NULL,
- &text_width, NULL,
- NULL,
- NULL, NULL, NULL);
-
- /* Fetch the average size of a character */
- context = gtk_widget_get_pango_context (widget);
- gtk_style_context_save (style_context);
- gtk_style_context_set_state (style_context, 0);
- gtk_style_context_get (style_context, gtk_style_context_get_state (style_context),
- "font", &font_desc, NULL);
- gtk_style_context_restore (style_context);
- metrics = pango_context_get_metrics (context, font_desc,
- pango_context_get_language (context));
-
- char_width = pango_font_metrics_get_approximate_char_width (metrics);
-
- pango_font_metrics_unref (metrics);
- pango_font_description_free (font_desc);
-
- /* enforce minimum width for ellipsized labels at ~3 chars */
- ellipsize_chars = 3;
-
- /* If no width-chars set, minimum for wrapping text will be the wrap-width */
- if (wrap_width > -1)
- min_width = xpad * 2 + MIN (text_width, wrap_width);
- else
- min_width = xpad * 2 +
- MIN (text_width,
- (PANGO_PIXELS (char_width) * MAX (width_chars, ellipsize_chars)));
-
- if (width_chars > 0)
- nat_width = xpad * 2 +
- MAX ((PANGO_PIXELS (char_width) * width_chars), text_width);
- else
- nat_width = xpad * 2 + text_width;
-
- nat_width = MAX (nat_width, min_width);
-
- if (minimum_size)
- *minimum_size = min_width;
-
- if (natural_size)
- *natural_size = nat_width;
-}
-
-static void
-gd_two_lines_renderer_get_preferred_height_for_width (GtkCellRenderer *cell,
- GtkWidget *widget,
- gint width,
- gint *minimum_size,
- gint *natural_size)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
- PangoLayout *layout_one, *layout_two;
- gint text_height, wrap_width;
- gint xpad, ypad;
-
- gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
- g_object_get (cell, "wrap-width", &wrap_width, NULL);
- gd_two_lines_renderer_prepare_layouts (self, NULL, widget, &layout_one, &layout_two);
-
- if (wrap_width != -1)
- wrap_width = MIN (width - 2 * xpad, wrap_width);
- else
- wrap_width = width - 2 * xpad;
-
- pango_layout_set_width (layout_one, wrap_width);
- if (layout_two != NULL)
- pango_layout_set_width (layout_two, wrap_width);
-
- gd_two_lines_renderer_get_size (cell, widget,
- layout_one, layout_two,
- NULL, &text_height,
- NULL,
- NULL, NULL, NULL);
-
- text_height += 2 * ypad;
-
- if (minimum_size != NULL)
- *minimum_size = text_height;
-
- if (natural_size != NULL)
- *natural_size = text_height;
-
- g_clear_object (&layout_one);
- g_clear_object (&layout_two);
-}
-
-static void
-gd_two_lines_renderer_get_preferred_height (GtkCellRenderer *cell,
- GtkWidget *widget,
- gint *minimum_size,
- gint *natural_size)
-{
- gint min_width;
-
- gtk_cell_renderer_get_preferred_width (cell, widget, &min_width, NULL);
- gd_two_lines_renderer_get_preferred_height_for_width (cell, widget, min_width,
- minimum_size, natural_size);
-}
-
-static void
-gd_two_lines_renderer_get_aligned_area (GtkCellRenderer *cell,
- GtkWidget *widget,
- GtkCellRendererState flags,
- const GdkRectangle *cell_area,
- GdkRectangle *aligned_area)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
- gint x_offset, x_offset_1, x_offset_2, y_offset;
- PangoLayout *layout_one, *layout_two;
-
- /* fetch common information */
- gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two);
- gd_two_lines_renderer_get_size (cell, widget,
- layout_one, layout_two,
- &aligned_area->width, &aligned_area->height,
- cell_area,
- &x_offset_1, &x_offset_2, &y_offset);
-
- x_offset = MIN (x_offset_1, x_offset_2);
-
- aligned_area->x = cell_area->x + x_offset;
- aligned_area->y = cell_area->y;
-
- g_clear_object (&layout_one);
- g_clear_object (&layout_two);
-}
-
-static void
-gd_two_lines_renderer_set_line_two (GdTwoLinesRenderer *self,
- const gchar *line_two)
-{
- if (g_strcmp0 (self->priv->line_two, line_two) == 0)
- return;
-
- g_free (self->priv->line_two);
- self->priv->line_two = g_strdup (line_two);
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LINE_TWO]);
-}
-
-static void
-gd_two_lines_renderer_set_text_lines (GdTwoLinesRenderer *self,
- gint text_lines)
-{
- if (self->priv->text_lines == text_lines)
- return;
-
- self->priv->text_lines = text_lines;
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TEXT_LINES]);
-}
-
-static void
-gd_two_lines_renderer_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object);
-
- switch (property_id)
- {
- case PROP_TEXT_LINES:
- gd_two_lines_renderer_set_text_lines (self, g_value_get_int (value));
- break;
- case PROP_LINE_TWO:
- gd_two_lines_renderer_set_line_two (self, g_value_get_string (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gd_two_lines_renderer_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object);
-
- switch (property_id)
- {
- case PROP_TEXT_LINES:
- g_value_set_int (value, self->priv->text_lines);
- break;
- case PROP_LINE_TWO:
- g_value_set_string (value, self->priv->line_two);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gd_two_lines_renderer_finalize (GObject *object)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object);
-
- g_free (self->priv->line_two);
-
- G_OBJECT_CLASS (gd_two_lines_renderer_parent_class)->finalize (object);
-}
-
-static void
-gd_two_lines_renderer_class_init (GdTwoLinesRendererClass *klass)
-{
- GtkCellRendererClass *cclass = GTK_CELL_RENDERER_CLASS (klass);
- GObjectClass *oclass = G_OBJECT_CLASS (klass);
-
- cclass->render = gd_two_lines_renderer_render;
- cclass->get_preferred_width = gd_two_lines_renderer_get_preferred_width;
- cclass->get_preferred_height = gd_two_lines_renderer_get_preferred_height;
- cclass->get_preferred_height_for_width = gd_two_lines_renderer_get_preferred_height_for_width;
- cclass->get_aligned_area = gd_two_lines_renderer_get_aligned_area;
-
- oclass->set_property = gd_two_lines_renderer_set_property;
- oclass->get_property = gd_two_lines_renderer_get_property;
- oclass->finalize = gd_two_lines_renderer_finalize;
-
- properties[PROP_TEXT_LINES] =
- g_param_spec_int ("text-lines",
- "Lines of text",
- "The total number of lines to be displayed",
- 2, G_MAXINT, 2,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- properties[PROP_LINE_TWO] =
- g_param_spec_string ("line-two",
- "Second line",
- "Second line",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- g_type_class_add_private (klass, sizeof (GdTwoLinesRendererPrivate));
- g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
-}
-
-static void
-gd_two_lines_renderer_init (GdTwoLinesRenderer *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_TWO_LINES_RENDERER,
- GdTwoLinesRendererPrivate);
-}
-
-GtkCellRenderer *
-gd_two_lines_renderer_new (void)
-{
- return g_object_new (GD_TYPE_TWO_LINES_RENDERER, NULL);
-}
diff --git a/lib/widgets/contrib/gd-two-lines-renderer.h b/lib/widgets/contrib/gd-two-lines-renderer.h
deleted file mode 100644
index 23bf70f08..000000000
--- a/lib/widgets/contrib/gd-two-lines-renderer.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2011 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 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 Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Cosimo Cecchi <cosimoc@redhat.com>
- *
- */
-
-#ifndef _GD_TWO_LINES_RENDERER_H
-#define _GD_TWO_LINES_RENDERER_H
-
-#include <glib-object.h>
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GD_TYPE_TWO_LINES_RENDERER gd_two_lines_renderer_get_type()
-
-#define GD_TWO_LINES_RENDERER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
- GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRenderer))
-
-#define GD_TWO_LINES_RENDERER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), \
- GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRendererClass))
-
-#define GD_IS_TWO_LINES_RENDERER(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
- GD_TYPE_TWO_LINES_RENDERER))
-
-#define GD_IS_TWO_LINES_RENDERER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), \
- GD_TYPE_TWO_LINES_RENDERER))
-
-#define GD_TWO_LINES_RENDERER_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), \
- GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRendererClass))
-
-typedef struct _GdTwoLinesRenderer GdTwoLinesRenderer;
-typedef struct _GdTwoLinesRendererClass GdTwoLinesRendererClass;
-typedef struct _GdTwoLinesRendererPrivate GdTwoLinesRendererPrivate;
-
-struct _GdTwoLinesRenderer
-{
- GtkCellRendererText parent;
-
- GdTwoLinesRendererPrivate *priv;
-};
-
-struct _GdTwoLinesRendererClass
-{
- GtkCellRendererTextClass parent_class;
-};
-
-GType gd_two_lines_renderer_get_type (void) G_GNUC_CONST;
-
-GtkCellRenderer *gd_two_lines_renderer_new (void);
-
-G_END_DECLS
-
-#endif /* _GD_TWO_LINES_RENDERER_H */
diff --git a/lib/widgets/ephy-location-entry.c b/lib/widgets/ephy-location-entry.c
index 74b590f9c..472d0ab66 100644
--- a/lib/widgets/ephy-location-entry.c
+++ b/lib/widgets/ephy-location-entry.c
@@ -31,10 +31,11 @@
#include "ephy-gui.h"
#include "ephy-lib-type-builtins.h"
#include "ephy-signal-accumulator.h"
+#include "ephy-suggestion.h"
#include "ephy-title-widget.h"
#include "ephy-uri-helpers.h"
-#include "gd-two-lines-renderer.h"
+#include <dazzle.h>
#include <gdk/gdkkeysyms.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
@@ -54,7 +55,7 @@
*/
struct _EphyLocationEntry {
- GtkEntry parent_instance;
+ DzlSuggestionEntry parent_instance;
GtkTreeModel *model;
@@ -91,12 +92,6 @@ struct _EphyLocationEntry {
static gboolean ephy_location_entry_reset_internal (EphyLocationEntry *, gboolean);
-static void extracell_data_func (GtkCellLayout *cell_layout,
- GtkCellRenderer *cell,
- GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gpointer data);
-
enum {
PROP_0,
PROP_ADDRESS,
@@ -115,11 +110,17 @@ static gint signals[LAST_SIGNAL] = { 0 };
static void ephy_location_entry_title_widget_interface_init (EphyTitleWidgetInterface *iface);
-G_DEFINE_TYPE_WITH_CODE (EphyLocationEntry, ephy_location_entry, GTK_TYPE_ENTRY,
+G_DEFINE_TYPE_WITH_CODE (EphyLocationEntry, ephy_location_entry, DZL_TYPE_SUGGESTION_ENTRY,
G_IMPLEMENT_INTERFACE (EPHY_TYPE_TITLE_WIDGET,
ephy_location_entry_title_widget_interface_init))
static void
+ephy_location_entry_activate (EphyLocationEntry *entry)
+{
+ g_signal_emit_by_name (entry, "activate");
+}
+
+static void
update_address_state (EphyLocationEntry *entry)
{
const char *text;
@@ -273,8 +274,12 @@ ephy_location_entry_get_property (GObject *object,
static void
ephy_location_entry_constructed (GObject *object)
{
+ EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object);
+
G_OBJECT_CLASS (ephy_location_entry_parent_class)->constructed (object);
+ dzl_suggestion_entry_set_position_func (DZL_SUGGESTION_ENTRY (entry), dzl_suggestion_entry_window_position_func, NULL, NULL);
+
#if GTK_CHECK_VERSION(3, 22, 20)
gtk_entry_set_input_hints (GTK_ENTRY (object), GTK_INPUT_HINT_NO_EMOJI);
#endif
@@ -361,6 +366,16 @@ ephy_location_entry_cut_clipboard (GtkEntry *entry)
}
static void
+ephy_location_entry_suggestion_activated (DzlSuggestionEntry *entry,
+ DzlSuggestion *suggestion)
+{
+ gtk_entry_set_text (GTK_ENTRY (entry), ephy_suggestion_get_uri (EPHY_SUGGESTION (suggestion)));
+
+ /* Now trigger the load.... */
+ ephy_location_entry_activate (EPHY_LOCATION_ENTRY (entry));
+}
+
+static void
ephy_location_entry_title_widget_interface_init (EphyTitleWidgetInterface *iface)
{
iface->get_address = ephy_location_entry_title_widget_get_address;
@@ -375,7 +390,9 @@ ephy_location_entry_class_init (EphyLocationEntryClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkEntryClass *entry_class = GTK_ENTRY_CLASS (klass);
+ DzlSuggestionEntryClass *dzl_entry_class = DZL_SUGGESTION_ENTRY_CLASS (klass);
+ object_class->constructed = ephy_location_entry_constructed;
object_class->get_property = ephy_location_entry_get_property;
object_class->set_property = ephy_location_entry_set_property;
object_class->constructed = ephy_location_entry_constructed;
@@ -387,6 +404,8 @@ ephy_location_entry_class_init (EphyLocationEntryClass *klass)
entry_class->copy_clipboard = ephy_location_entry_copy_clipboard;
entry_class->cut_clipboard = ephy_location_entry_cut_clipboard;
+ dzl_entry_class->suggestion_activated = ephy_location_entry_suggestion_activated;
+
g_object_class_override_property (object_class, PROP_ADDRESS, "address");
g_object_class_override_property (object_class, PROP_SECURITY_LEVEL, "security-level");
@@ -488,103 +507,18 @@ entry_key_press_cb (GtkEntry *entry,
/* Make sure the location is activated on CTRL+l even when the
* completion popup is shown and have an active keyboard grab.
*/
- ephy_location_entry_activate (location_entry);
- }
-
- return FALSE;
-}
-
-static gboolean
-entry_key_press_after_cb (GtkEntry *entry,
- GdkEventKey *event,
- EphyLocationEntry *lentry)
-{
- guint state = event->state & gtk_accelerator_get_default_mod_mask ();
-
- if ((event->keyval == GDK_KEY_Return ||
- event->keyval == GDK_KEY_KP_Enter ||
- event->keyval == GDK_KEY_ISO_Enter) &&
- (state == GDK_CONTROL_MASK ||
- state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))) {
- /* gtk_im_context_reset (entry->im_context); */
-
- lentry->needs_reset = TRUE;
- g_signal_emit_by_name (entry, "activate");
-
- return TRUE;
+ ephy_location_entry_focus (location_entry);
}
- if ((event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down)
- && state == 0) {
- /* If we are focusing the entry, with the cursor at the end of it
- * we emit the changed signal, so that the completion popup appears */
- const char *string;
-
- string = gtk_entry_get_text (entry);
- if (gtk_editable_get_position (GTK_EDITABLE (entry)) == (int)strlen (string)) {
- g_signal_emit_by_name (entry, "changed", 0);
- return TRUE;
- }
- }
+ if (event->keyval == GDK_KEY_Return ||
+ event->keyval == GDK_KEY_KP_Enter ||
+ event->keyval == GDK_KEY_ISO_Enter)
+ ephy_location_entry_activate (location_entry);
return FALSE;
}
static void
-entry_activate_after_cb (GtkEntry *entry,
- EphyLocationEntry *lentry)
-{
- lentry->user_changed = FALSE;
-
- if (lentry->needs_reset) {
- ephy_location_entry_reset_internal (lentry, TRUE);
- lentry->needs_reset = FALSE;
- }
-}
-
-static gboolean
-match_selected_cb (GtkEntryCompletion *completion,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- EphyLocationEntry *entry)
-{
- char *item = NULL;
- guint state;
-
- gtk_tree_model_get (model, iter,
- entry->action_col, &item, -1);
- if (item == NULL) return FALSE;
-
- ephy_gui_get_current_event (NULL, &state, NULL);
-
- entry->needs_reset = (state == GDK_CONTROL_MASK ||
- state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK));
-
- ephy_title_widget_set_address (EPHY_TITLE_WIDGET (entry), item);
- /* gtk_im_context_reset (GTK_ENTRY (entry)->im_context); */
- g_signal_emit_by_name (entry, "activate");
-
- g_free (item);
-
- return TRUE;
-}
-
-static void
-action_activated_after_cb (GtkEntryCompletion *completion,
- gint index,
- EphyLocationEntry *lentry)
-{
- guint state, button;
-
- ephy_gui_get_current_event (NULL, &state, &button);
- if ((state == GDK_CONTROL_MASK ||
- state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) ||
- button == 2) {
- ephy_location_entry_reset_internal (lentry, TRUE);
- }
-}
-
-static void
entry_clear_activate_cb (GtkMenuItem *item,
EphyLocationEntry *entry)
{
@@ -601,7 +535,7 @@ paste_received (GtkClipboard *clipboard,
{
if (text) {
gtk_entry_set_text (GTK_ENTRY (entry), text);
- g_signal_emit_by_name (entry, "activate");
+ ephy_location_entry_activate (entry);
}
}
@@ -758,11 +692,6 @@ ephy_location_entry_construct_contents (EphyLocationEntry *lentry)
"signal::key-press-event", G_CALLBACK (entry_key_press_cb), lentry,
"signal::changed", G_CALLBACK (editable_changed_cb), lentry,
NULL);
-
- g_signal_connect_after (entry, "key-press-event",
- G_CALLBACK (entry_key_press_after_cb), lentry);
- g_signal_connect_after (entry, "activate",
- G_CALLBACK (entry_activate_after_cb), lentry);
}
static void
@@ -839,238 +768,6 @@ schedule_dns_prefetch (EphyLocationEntry *entry, guint interval, const gchar *ur
}
#endif
-static gboolean
-cursor_on_match_cb (GtkEntryCompletion *completion,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- EphyLocationEntry *le)
-{
- char *url = NULL;
- GtkWidget *entry;
-
- gtk_tree_model_get (model, iter,
- le->url_col,
- &url, -1);
- entry = gtk_entry_completion_get_entry (completion);
-
- /* Prevent the update so we keep the highlight from our input.
- * See textcell_data_func().
- */
- le->block_update = TRUE;
- gtk_entry_set_text (GTK_ENTRY (entry), url);
- gtk_editable_set_position (GTK_EDITABLE (entry), -1);
- le->block_update = FALSE;
-
-#if 0
-/* FIXME: Refactor the DNS prefetch, this is a layering violation */
- schedule_dns_prefetch (le, 250, (const gchar *)url);
-#endif
-
- g_free (url);
-
- return TRUE;
-}
-
-static void
-extracell_data_func (GtkCellLayout *cell_layout,
- GtkCellRenderer *cell,
- GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gpointer data)
-{
- EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (data);
- gboolean is_bookmark = FALSE;
- GValue visible = { 0, };
-
- gtk_tree_model_get (tree_model, iter,
- entry->extra_col, &is_bookmark,
- -1);
-
- if (is_bookmark)
- g_object_set (cell,
- "icon-name", "user-bookmarks-symbolic",
- NULL);
-
- g_value_init (&visible, G_TYPE_BOOLEAN);
- g_value_set_boolean (&visible, is_bookmark);
- g_object_set_property (G_OBJECT (cell), "visible", &visible);
- g_value_unset (&visible);
-}
-
-/**
- * ephy_location_entry_set_match_func:
- * @entry: an #EphyLocationEntry widget
- * @match_func: a #GtkEntryCompletionMatchFunc
- * @user_data: user_data to pass to the @match_func
- * @notify: a #GDestroyNotify, like the one given to
- * gtk_entry_completion_set_match_func
- *
- * Sets the match_func for the internal #GtkEntryCompletion to @match_func.
- *
- **/
-void
-ephy_location_entry_set_match_func (EphyLocationEntry *entry,
- GtkEntryCompletionMatchFunc match_func,
- gpointer user_data,
- GDestroyNotify notify)
-{
- GtkEntryCompletion *completion;
-
- completion = gtk_entry_get_completion (GTK_ENTRY (entry));
- gtk_entry_completion_set_match_func (completion, match_func, user_data, notify);
-}
-
-/**
- * ephy_location_entry_set_completion:
- * @entry: an #EphyLocationEntry widget
- * @model: the #GtkModel for the completion
- * @text_col: column id to access #GtkModel relevant data
- * @action_col: column id to access #GtkModel relevant data
- * @keywords_col: column id to access #GtkModel relevant data
- * @relevance_col: column id to access #GtkModel relevant data
- * @url_col: column id to access #GtkModel relevant data
- * @extra_col: column id to access #GtkModel relevant data
- * @favicon_col: column id to access #GtkModel relevant data
- *
- * Initializes @entry to have a #GtkEntryCompletion using @model as the
- * internal #GtkModel. The *_col arguments are for internal data retrieval from
- * @model, like when setting the text property of one of the #GtkCellRenderer
- * of the completion.
- *
- **/
-void
-ephy_location_entry_set_completion (EphyLocationEntry *entry,
- GtkTreeModel *model,
- guint text_col,
- guint action_col,
- guint keywords_col,
- guint relevance_col,
- guint url_col,
- guint extra_col,
- guint favicon_col)
-{
- GtkEntryCompletion *completion;
- GtkCellRenderer *cell;
-
- entry->text_col = text_col;
- entry->action_col = action_col;
- entry->keywords_col = keywords_col;
- entry->relevance_col = relevance_col;
- entry->url_col = url_col;
- entry->extra_col = extra_col;
- entry->favicon_col = favicon_col;
-
- completion = gtk_entry_completion_new ();
- gtk_entry_completion_set_model (completion, model);
- g_signal_connect (completion, "match-selected",
- G_CALLBACK (match_selected_cb), entry);
- g_signal_connect_after (completion, "action-activated",
- G_CALLBACK (action_activated_after_cb), entry);
-
- cell = gtk_cell_renderer_pixbuf_new ();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion),
- cell, FALSE);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion),
- cell, "pixbuf", favicon_col);
-
- /* Pixel-perfect aligment with the location entry favicon
- * (16x16). Consider that this /might/ depend on the theme.
- *
- * The GtkEntryCompletion can not be themed so we work-around
- * that with padding and fixed sizes.
- * For the first cell, this is:
- *
- * ___+++++iiiiiiiiiiiiiiii++__ttt...bbb++++++__
- *
- * _ = widget spacing, can not be handled (3 px)
- * + = padding (5 px) (ICON_PADDING_LEFT)
- * i = the icon (16 px) (ICON_CONTENT_WIDTH)
- * + = padding (2 px) (ICON_PADDING_RIGHT) (cut by the fixed_size)
- * _ = spacing between cells, can not be handled (2 px)
- * t = the text (expands)
- * b = bookmark icon (16 px)
- * + = padding (6 px) (BKMK_PADDING_RIGHT)
- * _ = widget spacing, can not be handled (2 px)
- *
- * Each character is a pixel.
- *
- * The text cell and the bookmark icon cell are much more
- * flexible in its aligment, because they do not have to align
- * with anything in the entry.
- */
-
-#define ROW_PADDING_VERT 4
-
-#define ICON_PADDING_LEFT 5
-#define ICON_CONTENT_WIDTH 16
-#define ICON_PADDING_RIGHT 9
-
-#define ICON_CONTENT_HEIGHT 16
-
-#define TEXT_PADDING_LEFT 0
-
-#define BKMK_PADDING_RIGHT 6
-
- gtk_cell_renderer_set_padding
- (cell, ICON_PADDING_LEFT, ROW_PADDING_VERT);
- gtk_cell_renderer_set_fixed_size
- (cell,
- (ICON_PADDING_LEFT + ICON_CONTENT_WIDTH + ICON_PADDING_RIGHT),
- ICON_CONTENT_HEIGHT);
- gtk_cell_renderer_set_alignment (cell, 0.0, 0.5);
-
- cell = gd_two_lines_renderer_new ();
- g_object_set (cell,
- "ellipsize", PANGO_ELLIPSIZE_END,
- "text-lines", 2,
- NULL);
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion),
- cell, TRUE);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion),
- cell, "text", text_col);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion),
- cell, "line-two", url_col);
-
- /* Pixel-perfect aligment with the text in the location entry.
- * See above.
- */
- gtk_cell_renderer_set_padding
- (cell, TEXT_PADDING_LEFT, ROW_PADDING_VERT);
- gtk_cell_renderer_set_alignment (cell, 0.0, 0.5);
-
- /*
- * As the width of the entry completion is known in advance
- * (as big as the entry you are completing on), we can set
- * any fixed width (the 1 is just this random number here)
- * Since the height is known too, we avoid computing the actual
- * sizes of the cells, which takes a lot of CPU time and does
- * not get used anyway.
- */
- gtk_cell_renderer_set_fixed_size (cell, 1, -1);
- gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (cell), 2);
-
- cell = gtk_cell_renderer_pixbuf_new ();
- g_object_set (cell, "follow-state", TRUE, NULL);
- gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (completion),
- cell, FALSE);
- gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (completion),
- cell, extracell_data_func,
- entry,
- NULL);
-
- /* Pixel-perfect aligment. This just keeps the same margin from
- * the border than the favicon on the other side. See above. */
- gtk_cell_renderer_set_padding
- (cell, BKMK_PADDING_RIGHT, ROW_PADDING_VERT);
-
- g_object_set (completion, "inline-selection", TRUE, NULL);
- g_signal_connect (completion, "cursor-on-match",
- G_CALLBACK (cursor_on_match_cb), entry);
-
- gtk_entry_set_completion (GTK_ENTRY (entry), completion);
- g_object_unref (completion);
-}
-
/**
* ephy_location_entry_get_can_undo:
* @entry: an #EphyLocationEntry widget
@@ -1125,9 +822,8 @@ ephy_location_entry_reset_internal (EphyLocationEntry *entry,
ephy_title_widget_set_address (EPHY_TITLE_WIDGET (entry), text);
g_free (url);
- if (notify) {
+ if (notify)
g_signal_emit (entry, signals[USER_CHANGED], 0);
- }
entry->user_changed = FALSE;
@@ -1167,7 +863,7 @@ ephy_location_entry_reset (EphyLocationEntry *entry)
}
/**
- * ephy_location_entry_activate:
+ * ephy_location_entry_focus:
* @entry: an #EphyLocationEntry widget
*
* Set focus on @entry and select the text whithin. This is called when the
@@ -1175,7 +871,7 @@ ephy_location_entry_reset (EphyLocationEntry *entry)
*
**/
void
-ephy_location_entry_activate (EphyLocationEntry *entry)
+ephy_location_entry_focus (EphyLocationEntry *entry)
{
GtkWidget *toplevel, *widget = GTK_WIDGET (entry);
diff --git a/lib/widgets/ephy-location-entry.h b/lib/widgets/ephy-location-entry.h
index 490524a09..950d06158 100644
--- a/lib/widgets/ephy-location-entry.h
+++ b/lib/widgets/ephy-location-entry.h
@@ -23,6 +23,7 @@
#pragma once
+#include <dazzle.h>
#include <gtk/gtk.h>
#include "ephy-security-levels.h"
@@ -31,7 +32,7 @@ G_BEGIN_DECLS
#define EPHY_TYPE_LOCATION_ENTRY (ephy_location_entry_get_type())
-G_DECLARE_FINAL_TYPE (EphyLocationEntry, ephy_location_entry, EPHY, LOCATION_ENTRY, GtkEntry)
+G_DECLARE_FINAL_TYPE (EphyLocationEntry, ephy_location_entry, EPHY, LOCATION_ENTRY, DzlSuggestionEntry)
typedef enum {
EPHY_LOCATION_ENTRY_BOOKMARK_ICON_HIDDEN,
@@ -41,21 +42,6 @@ typedef enum {
GtkWidget *ephy_location_entry_new (void);
-void ephy_location_entry_set_completion (EphyLocationEntry *entry,
- GtkTreeModel *model,
- guint text_col,
- guint action_col,
- guint keywords_col,
- guint relevance_col,
- guint url_col,
- guint extra_col,
- guint favicon_col);
-
-void ephy_location_entry_set_match_func (EphyLocationEntry *entry,
- GtkEntryCompletionMatchFunc match_func,
- gpointer user_data,
- GDestroyNotify notify);
-
gboolean ephy_location_entry_get_can_undo (EphyLocationEntry *entry);
gboolean ephy_location_entry_get_can_redo (EphyLocationEntry *entry);
@@ -66,7 +52,7 @@ gboolean ephy_location_entry_reset (EphyLocationEntr
void ephy_location_entry_undo_reset (EphyLocationEntry *entry);
-void ephy_location_entry_activate (EphyLocationEntry *entry);
+void ephy_location_entry_focus (EphyLocationEntry *entry);
void ephy_location_entry_set_bookmark_icon_state (EphyLocationEntry *entry,
EphyLocationEntryBookmarkIconState state);
diff --git a/lib/widgets/meson.build b/lib/widgets/meson.build
index 1c5c8492d..c927648d3 100644
--- a/lib/widgets/meson.build
+++ b/lib/widgets/meson.build
@@ -7,7 +7,6 @@ enums = gnome.mkenums_simple('ephy-widgets-type-builtins',
)
libephywidgets_sources = [
- 'contrib/gd-two-lines-renderer.c',
'contrib/nautilus-floating-bar.c',
'ephy-certificate-dialog.c',
'ephy-downloads-popover.c',
@@ -30,6 +29,7 @@ libephywidgets_deps = [
gio_dep,
glib_dep,
gtk_dep,
+ libdazzle_dep,
libsoup_dep,
webkit2gtk_dep
]
diff --git a/meson.build b/meson.build
index 535d49990..9fa9df18a 100644
--- a/meson.build
+++ b/meson.build
@@ -63,6 +63,7 @@ hogweed_dep = dependency('hogweed', version: nettle_requirement)
icu_uc_dep = dependency('icu-uc', version: '>= 4.6')
iso_codes_dep = dependency('iso-codes', version: '>= 0.35')
json_glib_dep = dependency('json-glib-1.0', version: '>= 1.2.4')
+libdazzle_dep = dependency('libdazzle-1.0', version: '>= 3.25.90')
libnotify_dep = dependency('libnotify', version: '>= 0.5.1')
libsecret_dep = dependency('libsecret-1', version: '>= 0.14')
libsoup_dep = dependency('libsoup-2.4', version: '>= 2.48.0')
diff --git a/org.gnome.Epiphany.json b/org.gnome.Epiphany.json
index 0cec50c12..426b7b490 100644
--- a/org.gnome.Epiphany.json
+++ b/org.gnome.Epiphany.json
@@ -51,6 +51,18 @@
]
},
{
+ "name": "libdazzle",
+ "config-opts": [ "--libdir=/app/lib" ],
+ "buildsystem": "meson",
+ "builddir": true,
+ "sources": [
+ {
+ "type": "git",
+ "url": "https://git.gnome.org/browse/libdazzle"
+ }
+ ]
+ },
+ {
"name": "epiphany",
"config-opts": ["-Dtech_preview=true"],
"buildsystem": "meson",
diff --git a/src/ephy-completion-model.c b/src/ephy-completion-model.c
deleted file mode 100644
index e1faae148..000000000
--- a/src/ephy-completion-model.c
+++ /dev/null
@@ -1,625 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/*
- * Copyright © 2012 Igalia S.L.
- *
- * This file is part of Epiphany.
- *
- * Epiphany 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.
- *
- * Epiphany 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 Epiphany. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include "ephy-completion-model.h"
-
-#include "ephy-embed-prefs.h"
-#include "ephy-embed-shell.h"
-#include "ephy-favicon-helpers.h"
-#include "ephy-history-service.h"
-#include "ephy-shell.h"
-#include "ephy-uri-helpers.h"
-
-#include <string.h>
-
-enum {
- PROP_0,
- PROP_HISTORY_SERVICE,
- PROP_BOOKMARKS_MANAGER,
- LAST_PROP
-};
-
-struct _EphyCompletionModel {
- GtkListStore parent_instance;
-
- EphyHistoryService *history_service;
- GCancellable *cancellable;
-
- EphyBookmarksManager *bookmarks_manager;
- GSList *search_terms;
-};
-
-static GParamSpec *obj_properties[LAST_PROP];
-
-G_DEFINE_TYPE (EphyCompletionModel, ephy_completion_model, GTK_TYPE_LIST_STORE)
-
-static void
-ephy_completion_model_constructed (GObject *object)
-{
- GType types[N_COL] = { G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_INT, G_TYPE_STRING, G_TYPE_BOOLEAN,
- GDK_TYPE_PIXBUF };
-
- G_OBJECT_CLASS (ephy_completion_model_parent_class)->constructed (object);
-
- gtk_list_store_set_column_types (GTK_LIST_STORE (object),
- N_COL,
- types);
-}
-
-static void
-free_search_terms (GSList *search_terms)
-{
- GSList *iter;
-
- for (iter = search_terms; iter != NULL; iter = iter->next)
- g_regex_unref ((GRegex *)iter->data);
-
- g_slist_free (search_terms);
-}
-
-static void
-ephy_completion_model_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
-{
- EphyCompletionModel *self = EPHY_COMPLETION_MODEL (object);
-
- switch (property_id) {
- case PROP_HISTORY_SERVICE:
- self->history_service = EPHY_HISTORY_SERVICE (g_value_get_pointer (value));
- break;
- case PROP_BOOKMARKS_MANAGER:
- self->bookmarks_manager = EPHY_BOOKMARKS_MANAGER (g_value_get_object (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec);
- break;
- }
-}
-
-static void
-ephy_completion_model_finalize (GObject *object)
-{
- EphyCompletionModel *model = EPHY_COMPLETION_MODEL (object);
-
- if (model->search_terms) {
- free_search_terms (model->search_terms);
- model->search_terms = NULL;
- }
-
- if (model->cancellable) {
- g_cancellable_cancel (model->cancellable);
- g_clear_object (&model->cancellable);
- }
-
- G_OBJECT_CLASS (ephy_completion_model_parent_class)->finalize (object);
-}
-
-static void
-ephy_completion_model_class_init (EphyCompletionModelClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->set_property = ephy_completion_model_set_property;
- object_class->constructed = ephy_completion_model_constructed;
- object_class->finalize = ephy_completion_model_finalize;
-
- obj_properties[PROP_HISTORY_SERVICE] =
- g_param_spec_pointer ("history-service",
- "History Service",
- "The history service",
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_BOOKMARKS_MANAGER] =
- g_param_spec_object ("bookmarks-manager",
- "Bookmarks manager",
- "The bookmarks manager",
- EPHY_TYPE_BOOKMARKS_MANAGER,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
-}
-
-static void
-ephy_completion_model_init (EphyCompletionModel *model)
-{
-}
-
-static gboolean
-is_base_address (const char *address)
-{
- if (address == NULL)
- return FALSE;
-
- /* A base address is <scheme>://<host>/
- * Neither scheme nor host contain a slash, so we can use slashes
- * figure out if it's a base address.
- *
- * Note: previous code was using a GRegExp to do the same thing.
- * While regexps are much nicer to read, they're also a lot
- * slower.
- */
- address = strchr (address, '/');
- if (address == NULL ||
- address[1] != '/')
- return FALSE;
-
- address += 2;
- address = strchr (address, '/');
- if (address == NULL ||
- address[1] != 0)
- return FALSE;
-
- return TRUE;
-}
-
-static int
-get_relevance (const char *location,
- int visit_count,
- gboolean is_bookmark)
-{
- /* FIXME: use frecency. */
- int relevance = 0;
-
- /* We have three ordered groups: history's base addresses,
- bookmarks, deep history addresses. */
- if (is_bookmark)
- relevance = 1 << 5;
- else {
- visit_count = MIN (visit_count, (1 << 5) - 1);
-
- if (is_base_address (location))
- relevance = visit_count << 10;
- else
- relevance = visit_count;
- }
-
- return relevance;
-}
-
-typedef struct {
- char *title;
- char *location;
- char *keywords;
- int relevance;
- gboolean is_bookmark;
-} PotentialRow;
-
-typedef struct {
- GtkListStore *model;
- GtkTreeRowReference *row_reference;
-} IconLoadData;
-
-static void
-icon_loaded_cb (GObject *source, GAsyncResult *result, gpointer user_data)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
- IconLoadData *data = (IconLoadData *)user_data;
- WebKitFaviconDatabase *database = WEBKIT_FAVICON_DATABASE (source);
- GdkPixbuf *favicon = NULL;
- cairo_surface_t *icon_surface = webkit_favicon_database_get_favicon_finish (database, result, NULL);
-
- if (icon_surface) {
- favicon = ephy_pixbuf_get_from_surface_scaled (icon_surface, FAVICON_SIZE, FAVICON_SIZE);
- cairo_surface_destroy (icon_surface);
- }
-
- if (favicon) {
- /* The completion model might have changed its contents */
- if (gtk_tree_row_reference_valid (data->row_reference)) {
- path = gtk_tree_row_reference_get_path (data->row_reference);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (data->model), &iter, path);
- gtk_list_store_set (data->model, &iter, EPHY_COMPLETION_FAVICON_COL, favicon, -1);
- g_object_unref (favicon);
- gtk_tree_path_free (path);
- }
- }
-
- g_object_unref (data->model);
- gtk_tree_row_reference_free (data->row_reference);
- g_slice_free (IconLoadData, data);
-}
-
-static void
-set_row_in_model (EphyCompletionModel *model, int position, PotentialRow *row)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
- IconLoadData *data;
- WebKitFaviconDatabase *database;
- EphyEmbedShell *shell = ephy_embed_shell_get_default ();
-
- database = webkit_web_context_get_favicon_database (ephy_embed_shell_get_web_context (shell));
-
- gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &iter, position,
- EPHY_COMPLETION_TEXT_COL, row->title ? row->title : "",
- EPHY_COMPLETION_URL_COL, row->location,
- EPHY_COMPLETION_ACTION_COL, row->location,
- EPHY_COMPLETION_KEYWORDS_COL, row->keywords ? row->keywords : "",
- EPHY_COMPLETION_EXTRA_COL, row->is_bookmark,
- EPHY_COMPLETION_RELEVANCE_COL, row->relevance,
- -1);
-
- data = g_slice_new (IconLoadData);
- data->model = GTK_LIST_STORE (g_object_ref (model));
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
- data->row_reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (model), path);
- gtk_tree_path_free (path);
-
- webkit_favicon_database_get_favicon (database, row->location,
- NULL, icon_loaded_cb, data);
-}
-
-static void
-replace_rows_in_model (EphyCompletionModel *model, GSList *new_rows)
-{
- /* This is by far the simplest way of doing, and yet it gives
- * basically the same result than the other methods... */
- int i;
-
- gtk_list_store_clear (GTK_LIST_STORE (model));
-
- if (!new_rows)
- return;
-
- for (i = 0; new_rows != NULL; i++) {
- PotentialRow *row = (PotentialRow *)new_rows->data;
-
- set_row_in_model (model, i, row);
- new_rows = new_rows->next;
- }
-}
-
-static gboolean
-should_add_bookmark_to_model (EphyCompletionModel *model,
- const char *search_string,
- EphyBookmark *bookmark)
-{
- gboolean ret = TRUE;
- GSequence *tags;
- GSequenceIter *tag_iter;
- const char *url;
- const char *title;
- char *tag_string = NULL;
- char **tag_array;
- int i;
-
- title = ephy_bookmark_get_title (bookmark);
- url = ephy_bookmark_get_url (bookmark);
- tags = ephy_bookmark_get_tags (bookmark);
-
- tag_array = g_malloc0 ((g_sequence_get_length (tags) + 1) * sizeof (char *));
-
- for (i = 0, tag_iter = g_sequence_get_begin_iter (tags);
- !g_sequence_iter_is_end (tag_iter);
- i++, tag_iter = g_sequence_iter_next (tag_iter)) {
- tag_array[i] = g_sequence_get (tag_iter);
- }
-
- tag_string = g_strjoinv (" ", tag_array);
-
- if (model->search_terms) {
- GSList *iter;
- GRegex *current = NULL;
-
- for (iter = model->search_terms; iter != NULL; iter = iter->next) {
- current = (GRegex *)iter->data;
-
- if ((!g_regex_match (current, title ? title : "", G_REGEX_MATCH_NOTEMPTY, NULL)) &&
- (!g_regex_match (current, url ? url : "", G_REGEX_MATCH_NOTEMPTY, NULL)) &&
- (!g_regex_match (current, tag_string ? tag_string : "", G_REGEX_MATCH_NOTEMPTY, NULL))) {
- ret = FALSE;
- break;
- }
- }
- }
-
- g_free (tag_array);
- g_free (tag_string);
-
- return ret;
-}
-
-typedef struct {
- EphyCompletionModel *model;
- char *search_string;
- EphyHistoryJobCallback callback;
- gpointer user_data;
-} FindURLsData;
-
-static int
-find_url (gconstpointer a,
- gconstpointer b)
-{
- return g_strcmp0 (((PotentialRow *)a)->location,
- ((char *)b));
-}
-
-static PotentialRow *
-potential_row_new (const char *title, const char *location,
- const char *keywords, int visit_count,
- gboolean is_bookmark)
-{
- PotentialRow *row = g_slice_new0 (PotentialRow);
-
- row->title = g_strdup (title);
- row->location = g_strdup (location);
- row->keywords = g_strdup (keywords);
- row->relevance = get_relevance (location, visit_count, is_bookmark);
- row->is_bookmark = is_bookmark;
-
- return row;
-}
-
-static void
-free_potential_row (PotentialRow *row)
-{
- g_free (row->title);
- g_free (row->location);
- g_free (row->keywords);
-
- g_slice_free (PotentialRow, row);
-}
-
-static GSList *
-add_to_potential_rows (GSList *rows,
- const char *title,
- const char *location,
- const char *keywords,
- int visit_count,
- gboolean is_bookmark,
- gboolean search_for_duplicates)
-{
- gboolean found = FALSE;
- PotentialRow *row = potential_row_new (title, location, keywords, visit_count, is_bookmark);
-
- if (search_for_duplicates) {
- GSList *p;
-
- p = g_slist_find_custom (rows, location, find_url);
- if (p) {
- PotentialRow *match = (PotentialRow *)p->data;
- if (row->relevance > match->relevance)
- match->relevance = row->relevance;
-
- found = TRUE;
- free_potential_row (row);
- }
- }
-
- if (!found)
- rows = g_slist_prepend (rows, row);
-
- return rows;
-}
-
-static int
-sort_by_relevance (gconstpointer a, gconstpointer b)
-{
- PotentialRow *r1 = (PotentialRow *)a;
- PotentialRow *r2 = (PotentialRow *)b;
-
- if (r1->relevance < r2->relevance)
- return 1;
- else if (r1->relevance > r2->relevance)
- return -1;
- else
- return 0;
-}
-
-static void
-query_completed_cb (EphyHistoryService *service,
- gboolean success,
- gpointer result_data,
- FindURLsData *user_data)
-{
- EphyCompletionModel *model = user_data->model;
- GList *p, *urls;
- GSequence *bookmarks;
- GSequenceIter *iter;
- GSList *list = NULL;
-
- /* Bookmarks */
- bookmarks = ephy_bookmarks_manager_get_bookmarks (model->bookmarks_manager);
-
- /* FIXME: perhaps this could be done in a service thread? There
- * should never be a ton of bookmarks, but seems a bit cleaner and
- * consistent with what we do for the history. */
- for (iter = g_sequence_get_begin_iter (bookmarks);
- !g_sequence_iter_is_end (iter);
- iter = g_sequence_iter_next (iter)) {
- EphyBookmark *bookmark;
- const char *url, *title;
-
- bookmark = g_sequence_get (iter);
-
- if (should_add_bookmark_to_model (model, user_data->search_string, bookmark)) {
- url = ephy_bookmark_get_url (bookmark);
- title = ephy_bookmark_get_title (bookmark);
- list = add_to_potential_rows (list, title, url, NULL, 0, TRUE, FALSE);
- }
- }
-
- /* History */
- urls = (GList *)result_data;
-
- for (p = urls; p != NULL; p = p->next) {
- EphyHistoryURL *url = (EphyHistoryURL *)p->data;
-
- list = add_to_potential_rows (list, url->title, url->url, NULL, url->visit_count, FALSE, TRUE);
- }
-
- /* Sort the rows by relevance. */
- list = g_slist_sort (list, sort_by_relevance);
-
- /* Now that we have all the rows we want to insert, replace the rows
- * in the current model one by one, sorted by relevance. */
- replace_rows_in_model (model, list);
-
- /* Notify */
- if (user_data->callback)
- user_data->callback (service, success, result_data, user_data->user_data);
-
- g_free (user_data->search_string);
- g_slice_free (FindURLsData, user_data);
- g_list_free_full (urls, (GDestroyNotify)ephy_history_url_free);
- g_slist_free_full (list, (GDestroyNotify)free_potential_row);
- g_clear_object (&model->cancellable);
-}
-
-static void
-update_search_terms (EphyCompletionModel *model,
- const char *text)
-{
- const char *current;
- const char *ptr;
- char *tmp;
- char *term;
- GRegex *term_regex;
- GRegex *quote_regex;
- gint count;
- gboolean inside_quotes = FALSE;
-
- if (model->search_terms) {
- free_search_terms (model->search_terms);
- model->search_terms = NULL;
- }
-
- quote_regex = g_regex_new ("\"", G_REGEX_OPTIMIZE,
- G_REGEX_MATCH_NOTEMPTY, NULL);
-
- /*
- * This code loops through the string using pointer arythmetics.
- * Although the string we are handling may contain UTF-8 chars
- * this works because only ASCII chars affect what is actually
- * copied from the string as a search term.
- */
- for (count = 0, current = ptr = text; ptr[0] != '\0'; ptr++, count++) {
- /*
- * If we found a double quote character; we will
- * consume bytes up until the next quote, or
- * end of line;
- */
- if (ptr[0] == '"')
- inside_quotes = !inside_quotes;
-
- /*
- * If we found a space, and we are not looking for a
- * closing double quote, or if the next char is the
- * end of the string, append what we have already as
- * a search term.
- */
- if (((ptr[0] == ' ') && (!inside_quotes)) || ptr[1] == '\0') {
- /*
- * We special-case the end of the line because
- * we would otherwise not copy the last character
- * of the search string, since the for loop will
- * stop before that.
- */
- if (ptr[1] == '\0')
- count++;
-
- /*
- * remove quotes, and quote any regex-sensitive
- * characters
- */
- tmp = g_regex_escape_string (current, count);
- term = g_regex_replace (quote_regex, tmp, -1, 0,
- "", G_REGEX_MATCH_NOTEMPTY, NULL);
- g_strstrip (term);
- g_free (tmp);
-
- /* we don't want empty search terms */
- if (term[0] != '\0') {
- term_regex = g_regex_new (term,
- G_REGEX_CASELESS | G_REGEX_OPTIMIZE,
- G_REGEX_MATCH_NOTEMPTY, NULL);
- model->search_terms = g_slist_append (model->search_terms, term_regex);
- }
- g_free (term);
-
- /* count will be incremented by the for loop */
- count = -1;
- current = ptr + 1;
- }
- }
-
- g_regex_unref (quote_regex);
-}
-
-#define MAX_COMPLETION_HISTORY_URLS 8
-
-void
-ephy_completion_model_update_for_string (EphyCompletionModel *model,
- const char *search_string,
- EphyHistoryJobCallback callback,
- gpointer data)
-{
- char **strings;
- int i;
- GList *query = NULL;
- FindURLsData *user_data;
-
- g_return_if_fail (EPHY_IS_COMPLETION_MODEL (model));
- g_return_if_fail (search_string != NULL);
-
- /* Split the search string. */
- strings = g_strsplit (search_string, " ", -1);
- for (i = 0; strings[i]; i++)
- query = g_list_append (query, g_strdup (strings[i]));
- g_strfreev (strings);
-
- update_search_terms (model, search_string);
-
- user_data = g_slice_new (FindURLsData);
- user_data->model = model;
- user_data->search_string = g_strdup (search_string);
- user_data->callback = callback;
- user_data->user_data = data;
-
- if (model->cancellable) {
- g_cancellable_cancel (model->cancellable);
- g_object_unref (model->cancellable);
- }
- model->cancellable = g_cancellable_new ();
-
- ephy_history_service_find_urls (model->history_service,
- 0, 0,
- MAX_COMPLETION_HISTORY_URLS, 0,
- query,
- EPHY_HISTORY_SORT_MOST_VISITED,
- model->cancellable,
- (EphyHistoryJobCallback)query_completed_cb,
- user_data);
-}
-
-EphyCompletionModel *
-ephy_completion_model_new (EphyHistoryService *history_service,
- EphyBookmarksManager *bookmarks_manager)
-{
- g_return_val_if_fail (EPHY_IS_HISTORY_SERVICE (history_service), NULL);
- g_return_val_if_fail (EPHY_IS_BOOKMARKS_MANAGER (bookmarks_manager), NULL);
-
- return g_object_new (EPHY_TYPE_COMPLETION_MODEL,
- "history-service", history_service,
- "bookmarks-manager", bookmarks_manager,
- NULL);
-}
diff --git a/src/ephy-completion-model.h b/src/ephy-completion-model.h
deleted file mode 100644
index 912c3669e..000000000
--- a/src/ephy-completion-model.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/*
- * Copyright © 2012 Igalia S.L.
- *
- * This file is part of Epiphany.
- *
- * Epiphany 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.
- *
- * Epiphany 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 Epiphany. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "ephy-bookmarks-manager.h"
-#include "ephy-history-service.h"
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define EPHY_TYPE_COMPLETION_MODEL (ephy_completion_model_get_type ())
-
-G_DECLARE_FINAL_TYPE (EphyCompletionModel, ephy_completion_model, EPHY, COMPLETION_MODEL, GtkListStore)
-
-typedef enum
-{
- EPHY_COMPLETION_TEXT_COL,
- EPHY_COMPLETION_ACTION_COL,
- EPHY_COMPLETION_KEYWORDS_COL,
- EPHY_COMPLETION_RELEVANCE_COL,
- EPHY_COMPLETION_URL_COL,
- EPHY_COMPLETION_EXTRA_COL,
- EPHY_COMPLETION_FAVICON_COL,
- N_COL
-} EphyCompletionColumn;
-
-EphyCompletionModel *ephy_completion_model_new (EphyHistoryService *history_service,
- EphyBookmarksManager *bookmarks_manager);
-
-void ephy_completion_model_update_for_string (EphyCompletionModel *model,
- const char *string,
- EphyHistoryJobCallback callback,
- gpointer data);
-G_END_DECLS
diff --git a/src/ephy-location-controller.c b/src/ephy-location-controller.c
index c42e31f89..f46e232e2 100644
--- a/src/ephy-location-controller.c
+++ b/src/ephy-location-controller.c
@@ -22,8 +22,6 @@
#include "config.h"
#include "ephy-location-controller.h"
-
-#include "ephy-completion-model.h"
#include "ephy-debug.h"
#include "ephy-dnd.h"
#include "ephy-embed-container.h"
@@ -31,10 +29,12 @@
#include "ephy-link.h"
#include "ephy-location-entry.h"
#include "ephy-shell.h"
+#include "ephy-suggestion-model.h"
#include "ephy-title-widget.h"
#include "ephy-uri-helpers.h"
#include "ephy-widgets-type-builtins.h"
+#include <dazzle.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <string.h>
@@ -79,16 +79,6 @@ G_DEFINE_TYPE_WITH_CODE (EphyLocationController, ephy_location_controller, G_TYP
G_IMPLEMENT_INTERFACE (EPHY_TYPE_LINK,
NULL))
-static gboolean
-match_func (GtkEntryCompletion *completion,
- const char *key,
- GtkTreeIter *iter,
- gpointer data)
-{
- /* We want every row in the model to show up. */
- return TRUE;
-}
-
static void
entry_drag_data_received_cb (GtkWidget *widget,
GdkDragContext *context,
@@ -182,33 +172,18 @@ entry_activate_cb (GtkEntry *entry,
}
static void
-update_done_cb (EphyHistoryService *service,
- gboolean success,
- gpointer result_data,
- gpointer user_data)
-{
- /* FIXME: this hack is needed for the completion entry popup
- * to resize smoothly. See:
- * https://bugzilla.gnome.org/show_bug.cgi?id=671074 */
- gtk_entry_completion_complete (GTK_ENTRY_COMPLETION (user_data));
-}
-
-static void
user_changed_cb (GtkWidget *widget, EphyLocationController *controller)
{
const char *address;
- GtkTreeModel *model;
- GtkEntryCompletion *completion;
+ GListModel *model;
address = ephy_title_widget_get_address (EPHY_TITLE_WIDGET (widget));
LOG ("user_changed_cb, address %s", address);
- completion = gtk_entry_get_completion (GTK_ENTRY (widget));
- model = gtk_entry_completion_get_model (completion);
+ model = dzl_suggestion_entry_get_model (DZL_SUGGESTION_ENTRY (widget));
- ephy_completion_model_update_for_string (EPHY_COMPLETION_MODEL (model), address,
- update_done_cb, completion);
+ ephy_suggestion_model_query_async (EPHY_SUGGESTION_MODEL (model), address, NULL, NULL, NULL);
}
static void
@@ -292,84 +267,12 @@ switch_page_cb (GtkNotebook *notebook,
}
static void
-action_activated_cb (GtkEntryCompletion *completion,
- int index,
- EphyLocationController *controller)
-{
- GtkWidget *entry;
- char *content;
- char *url;
- char **engine_names;
-
- entry = gtk_entry_completion_get_entry (completion);
- content = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
- if (content == NULL)
- return;
-
- engine_names = ephy_search_engine_manager_get_names (controller->search_engine_manager);
- url = ephy_search_engine_manager_build_search_address (controller->search_engine_manager,
- engine_names[index],
- content);
- g_strfreev (engine_names);
-
- ephy_link_open (EPHY_LINK (controller), url, NULL,
- ephy_link_flags_from_current_event ());
- g_free (content);
- g_free (url);
-}
-
-static void
-fill_entry_completion_with_actions (GtkEntryCompletion *completion,
- EphyLocationController *controller)
-{
- char **engine_names;
-
- engine_names = ephy_search_engine_manager_get_names (controller->search_engine_manager);
-
- controller->num_search_engines_actions = 0;
-
- for (guint i = 0; engine_names[i] != NULL; i++) {
- gtk_entry_completion_insert_action_text (completion, i, engine_names[i]);
- controller->num_search_engines_actions++;
- }
-
- g_strfreev (engine_names);
-}
-
-static void
-add_completion_actions (EphyLocationController *controller,
- EphyLocationEntry *lentry)
-{
- GtkEntryCompletion *completion = gtk_entry_get_completion (GTK_ENTRY (lentry));
-
- fill_entry_completion_with_actions (completion, controller);
- g_signal_connect (completion, "action_activated",
- G_CALLBACK (action_activated_cb), controller);
-}
-
-static void
-search_engines_changed_cb (EphySearchEngineManager *manager,
- gpointer data)
-{
- EphyLocationController *controller;
- GtkEntryCompletion *completion;
-
- controller = EPHY_LOCATION_CONTROLLER (data);
- completion = gtk_entry_get_completion (GTK_ENTRY (controller->title_widget));
-
- for (guint i = 0; i < controller->num_search_engines_actions; i++)
- gtk_entry_completion_delete_action (completion, 0);
-
- fill_entry_completion_with_actions (completion, controller);
-}
-
-static void
ephy_location_controller_constructed (GObject *object)
{
EphyLocationController *controller = EPHY_LOCATION_CONTROLLER (object);
EphyHistoryService *history_service;
EphyBookmarksManager *bookmarks_manager;
- EphyCompletionModel *model;
+ EphySuggestionModel *model;
GtkWidget *notebook, *widget;
G_OBJECT_CLASS (ephy_location_controller_parent_class)->constructed (object);
@@ -389,27 +292,13 @@ ephy_location_controller_constructed (GObject *object)
history_service = ephy_embed_shell_get_global_history_service (ephy_embed_shell_get_default ());
bookmarks_manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
- model = ephy_completion_model_new (history_service, bookmarks_manager);
- ephy_location_entry_set_completion (EPHY_LOCATION_ENTRY (controller->title_widget),
- GTK_TREE_MODEL (model),
- EPHY_COMPLETION_TEXT_COL,
- EPHY_COMPLETION_ACTION_COL,
- EPHY_COMPLETION_KEYWORDS_COL,
- EPHY_COMPLETION_RELEVANCE_COL,
- EPHY_COMPLETION_URL_COL,
- EPHY_COMPLETION_EXTRA_COL,
- EPHY_COMPLETION_FAVICON_COL);
+ model = ephy_suggestion_model_new (history_service, bookmarks_manager);
+ dzl_suggestion_entry_set_model (DZL_SUGGESTION_ENTRY (controller->title_widget), G_LIST_MODEL (model));
g_object_unref (model);
- ephy_location_entry_set_match_func (EPHY_LOCATION_ENTRY (controller->title_widget),
- match_func,
- controller->title_widget,
- NULL);
-
- add_completion_actions (controller, EPHY_LOCATION_ENTRY (controller->title_widget));
-
- g_signal_connect_object (controller->search_engine_manager, "changed",
- G_CALLBACK (search_engines_changed_cb), controller, 0);
+/* FIXME: What to do with search engines? Add them to the model? Probably not?
+ * Make the bangs mandatory?
+ */
g_object_bind_property (controller, "editable",
controller->title_widget, "editable",
diff --git a/src/ephy-suggestion-model.c b/src/ephy-suggestion-model.c
new file mode 100644
index 000000000..9e12195ff
--- /dev/null
+++ b/src/ephy-suggestion-model.c
@@ -0,0 +1,476 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 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 "config.h"
+#include "ephy-suggestion-model.h"
+
+#include "ephy-embed-shell.h"
+#include "ephy-search-engine-manager.h"
+#include "ephy-suggestion.h"
+
+#include <dazzle.h>
+#include <glib/gi18n.h>
+
+#define MAX_COMPLETION_HISTORY_URLS 8
+
+struct _EphySuggestionModel {
+ GObject parent;
+ EphyHistoryService *history_service;
+ EphyBookmarksManager *bookmarks_manager;
+ GSequence *items;
+ GSList *search_terms;
+};
+
+enum {
+ PROP_0,
+ PROP_BOOKMARKS_MANAGER,
+ PROP_HISTORY_SERVICE,
+ N_PROPS
+};
+
+static void list_model_iface_init (GListModelInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EphySuggestionModel, ephy_suggestion_model, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+ephy_suggestion_model_finalize (GObject *object)
+{
+ EphySuggestionModel *self = (EphySuggestionModel *)object;
+
+ g_clear_object (&self->bookmarks_manager);
+ g_clear_object (&self->history_service);
+ g_clear_pointer (&self->items, g_sequence_free);
+
+ g_slist_free_full (self->search_terms, (GDestroyNotify)g_regex_unref);
+
+ G_OBJECT_CLASS (ephy_suggestion_model_parent_class)->finalize (object);
+}
+
+static void
+ephy_suggestion_model_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphySuggestionModel *self = EPHY_SUGGESTION_MODEL (object);
+
+ switch (prop_id) {
+ case PROP_HISTORY_SERVICE:
+ g_value_set_object (value, self->history_service);
+ break;
+ case PROP_BOOKMARKS_MANAGER:
+ g_value_set_object (value, self->bookmarks_manager);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_suggestion_model_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphySuggestionModel *self = EPHY_SUGGESTION_MODEL (object);
+
+ switch (prop_id) {
+ case PROP_HISTORY_SERVICE:
+ self->history_service = g_value_dup_object (value);
+ break;
+ case PROP_BOOKMARKS_MANAGER:
+ self->bookmarks_manager = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_suggestion_model_class_init (EphySuggestionModelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ephy_suggestion_model_finalize;
+ object_class->get_property = ephy_suggestion_model_get_property;
+ object_class->set_property = ephy_suggestion_model_set_property;
+
+ properties [PROP_BOOKMARKS_MANAGER] =
+ g_param_spec_object ("bookmarks-manager",
+ "Bookmarks Manager",
+ "The bookmarks manager for suggestions",
+ EPHY_TYPE_BOOKMARKS_MANAGER,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_HISTORY_SERVICE] =
+ g_param_spec_object ("history-service",
+ "History Service",
+ "The history service for suggestions",
+ EPHY_TYPE_HISTORY_SERVICE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ephy_suggestion_model_init (EphySuggestionModel *self)
+{
+ self->items = g_sequence_new (g_object_unref);
+}
+
+static GType
+ephy_suggestion_model_get_item_type (GListModel *model)
+{
+ return EPHY_TYPE_SUGGESTION;
+}
+
+static guint
+ephy_suggestion_model_get_n_items (GListModel *model)
+{
+ EphySuggestionModel *self = EPHY_SUGGESTION_MODEL (model);
+
+ return g_sequence_get_length (self->items);
+}
+
+static gpointer
+ephy_suggestion_model_get_item (GListModel *model,
+ guint position)
+{
+ EphySuggestionModel *self = EPHY_SUGGESTION_MODEL (model);
+ GSequenceIter *iter;
+ DzlSuggestion *suggestion;
+
+ iter = g_sequence_get_iter_at_pos (self->items, position);
+ suggestion = g_sequence_get (iter);
+
+ return g_object_ref (suggestion);
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+ iface->get_item_type = ephy_suggestion_model_get_item_type;
+ iface->get_item = ephy_suggestion_model_get_item;
+ iface->get_n_items = ephy_suggestion_model_get_n_items;
+}
+
+EphySuggestionModel *
+ephy_suggestion_model_new (EphyHistoryService *history_service,
+ EphyBookmarksManager *bookmarks_manager)
+{
+ g_assert (EPHY_IS_HISTORY_SERVICE (history_service));
+ g_assert (EPHY_IS_BOOKMARKS_MANAGER (bookmarks_manager));
+
+ return g_object_new (EPHY_TYPE_SUGGESTION_MODEL,
+ "history-service", history_service,
+ "bookmarks-manager", bookmarks_manager,
+ NULL);
+}
+
+static void
+update_search_terms (EphySuggestionModel *self,
+ const char *text)
+{
+ const char *current;
+ const char *ptr;
+ char *tmp;
+ char *term;
+ GRegex *term_regex;
+ GRegex *quote_regex;
+ gint count;
+ gboolean inside_quotes = FALSE;
+
+ g_assert (EPHY_IS_SUGGESTION_MODEL (self));
+
+ if (self->search_terms) {
+ g_slist_free_full (self->search_terms, (GDestroyNotify)g_regex_unref);
+ self->search_terms = NULL;
+ }
+
+ quote_regex = g_regex_new ("\"", G_REGEX_OPTIMIZE,
+ G_REGEX_MATCH_NOTEMPTY, NULL);
+
+ /*
+ * This code loops through the string using pointer arythmetics.
+ * Although the string we are handling may contain UTF-8 chars
+ * this works because only ASCII chars affect what is actually
+ * copied from the string as a search term.
+ */
+ for (count = 0, current = ptr = text; ptr[0] != '\0'; ptr++, count++) {
+ /*
+ * If we found a double quote character; we will
+ * consume bytes up until the next quote, or
+ * end of line;
+ */
+ if (ptr[0] == '"')
+ inside_quotes = !inside_quotes;
+
+ /*
+ * If we found a space, and we are not looking for a
+ * closing double quote, or if the next char is the
+ * end of the string, append what we have already as
+ * a search term.
+ */
+ if (((ptr[0] == ' ') && (!inside_quotes)) || ptr[1] == '\0') {
+ /*
+ * We special-case the end of the line because
+ * we would otherwise not copy the last character
+ * of the search string, since the for loop will
+ * stop before that.
+ */
+ if (ptr[1] == '\0')
+ count++;
+
+ /*
+ * remove quotes, and quote any regex-sensitive
+ * characters
+ */
+ tmp = g_regex_escape_string (current, count);
+ term = g_regex_replace (quote_regex, tmp, -1, 0,
+ "", G_REGEX_MATCH_NOTEMPTY, NULL);
+ g_strstrip (term);
+ g_free (tmp);
+
+ /* we don't want empty search terms */
+ if (term[0] != '\0') {
+ term_regex = g_regex_new (term,
+ G_REGEX_CASELESS | G_REGEX_OPTIMIZE,
+ G_REGEX_MATCH_NOTEMPTY, NULL);
+ self->search_terms = g_slist_append (self->search_terms, term_regex);
+ }
+ g_free (term);
+
+ /* count will be incremented by the for loop */
+ count = -1;
+ current = ptr + 1;
+ }
+ }
+
+ g_regex_unref (quote_regex);
+}
+
+static gboolean
+should_add_bookmark_to_model (EphySuggestionModel *self,
+ const char *search_string,
+ const char *title,
+ const char *location)
+{
+ gboolean ret = TRUE;
+
+ if (self->search_terms) {
+ GSList *iter;
+ GRegex *current = NULL;
+
+ for (iter = self->search_terms; iter != NULL; iter = iter->next) {
+ current = (GRegex *)iter->data;
+ if ((!g_regex_match (current, title ? title : "", G_REGEX_MATCH_NOTEMPTY, NULL)) &&
+ (!g_regex_match (current, location ? location : "", G_REGEX_MATCH_NOTEMPTY, NULL))) {
+ ret = FALSE;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static guint
+add_bookmarks (EphySuggestionModel *self,
+ const char *query)
+{
+ GSequence *bookmarks;
+ guint added = 0;
+
+ bookmarks = ephy_bookmarks_manager_get_bookmarks (self->bookmarks_manager);
+
+ for (GSequenceIter *iter = g_sequence_get_begin_iter (bookmarks);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter)) {
+ EphyBookmark *bookmark;
+ const char *url, *title;
+
+ bookmark = g_sequence_get (iter);
+
+ url = ephy_bookmark_get_url (bookmark);
+ title = ephy_bookmark_get_title (bookmark);
+
+ if (should_add_bookmark_to_model (self, query, title, url)) {
+ EphySuggestion *suggestion;
+
+ suggestion = ephy_suggestion_new (title, url);
+ g_sequence_append (self->items, suggestion);
+ added++;
+ }
+ }
+
+ return added;
+}
+
+static guint
+add_history (EphySuggestionModel *self,
+ GList *urls)
+{
+ guint added = 0;
+
+ for (const GList *p = urls; p != NULL; p = p->next) {
+ EphyHistoryURL *url = (EphyHistoryURL *)p->data;
+ EphySuggestion *suggestion;
+
+ suggestion = ephy_suggestion_new (url->title, url->url);
+ g_sequence_append (self->items, suggestion);
+ added++;
+ }
+
+ return added;
+}
+
+static guint
+add_search_engines (EphySuggestionModel *self,
+ const char *query)
+{
+ EphyEmbedShell *shell;
+ EphySearchEngineManager *manager;
+ char **engines;
+ guint added = 0;
+
+ shell = ephy_embed_shell_get_default ();
+ manager = ephy_embed_shell_get_search_engine_manager (shell);
+ engines = ephy_search_engine_manager_get_names (manager);
+
+ for (guint i = 0; engines[i] != NULL; i++) {
+ EphySuggestion *suggestion;
+ char *address;
+
+ address = ephy_search_engine_manager_build_search_address (manager, engines[i], query);
+ suggestion = ephy_suggestion_new_without_subtitle (engines[i], address);
+
+ g_sequence_append (self->items, suggestion);
+ added++;
+
+ g_free (address);
+ }
+
+ g_strfreev (engines);
+
+ return added;
+}
+
+static void
+query_completed_cb (EphyHistoryService *service,
+ gboolean success,
+ gpointer result_data,
+ gpointer user_data)
+{
+ GTask *task = user_data;
+ EphySuggestionModel *self;
+ const gchar *query;
+ GList *urls;
+ guint removed;
+ guint added;
+
+ self = g_task_get_source_object (task);
+ query = g_task_get_task_data (task);
+ urls = (GList *)result_data;
+
+ removed = g_sequence_get_length (self->items);
+
+ g_clear_pointer (&self->items, g_sequence_free);
+ self->items = g_sequence_new (g_object_unref);
+
+ added = add_bookmarks (self, query);
+ added += add_history (self, urls);
+ added += add_search_engines (self, query);
+
+ g_list_model_items_changed (G_LIST_MODEL (self), 0, removed, added);
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+void
+ephy_suggestion_model_query_async (EphySuggestionModel *self,
+ const gchar *query,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task = NULL;
+ char **strings;
+ GList *qlist = NULL;
+
+ g_assert (EPHY_IS_SUGGESTION_MODEL (self));
+ g_assert (query != NULL);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_source_tag (task, ephy_suggestion_model_query_async);
+ g_task_set_task_data (task, g_strdup (query), g_free);
+
+ /* Split the search string. */
+ strings = g_strsplit (query, " ", -1);
+ for (guint i = 0; strings[i]; i++)
+ qlist = g_list_append (qlist, g_strdup (strings[i]));
+
+ update_search_terms (self, query);
+
+ ephy_history_service_find_urls (self->history_service,
+ 0, 0,
+ MAX_COMPLETION_HISTORY_URLS, 0,
+ qlist,
+ EPHY_HISTORY_SORT_MOST_VISITED,
+ cancellable,
+ (EphyHistoryJobCallback)query_completed_cb,
+ task);
+
+ g_strfreev (strings);
+}
+
+gboolean
+ephy_suggestion_model_query_finish (EphySuggestionModel *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_assert (EPHY_IS_SUGGESTION_MODEL (self));
+ g_assert (G_IS_TASK (result));
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+EphySuggestion *
+ephy_suggestion_model_get_suggestion_with_uri (EphySuggestionModel *self,
+ const char *uri)
+{
+ GSequenceIter *iter;
+
+ g_assert (EPHY_IS_SUGGESTION_MODEL (self));
+ g_assert (uri != NULL && *uri != '\0');
+
+ for (iter = g_sequence_get_begin_iter (self->items);
+ !g_sequence_iter_is_end (iter); iter = g_sequence_iter_next (iter)) {
+ EphySuggestion *suggestion;
+
+ suggestion = g_sequence_get (iter);
+ if (strcmp (ephy_suggestion_get_uri (suggestion), uri) == 0)
+ return suggestion;
+ }
+
+ return NULL;
+}
diff --git a/src/ephy-suggestion-model.h b/src/ephy-suggestion-model.h
new file mode 100644
index 000000000..ba1ff06d1
--- /dev/null
+++ b/src/ephy-suggestion-model.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 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/>.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+#include "ephy-bookmarks-manager.h"
+#include "ephy-history-service.h"
+#include "ephy-suggestion.h"
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_SUGGESTION_MODEL (ephy_suggestion_model_get_type())
+
+G_DECLARE_FINAL_TYPE (EphySuggestionModel, ephy_suggestion_model, EPHY, SUGGESTION_MODEL, GObject)
+
+EphySuggestionModel *ephy_suggestion_model_new (EphyHistoryService *history_service,
+ EphyBookmarksManager *bookmarks_manager);
+void ephy_suggestion_model_query_async (EphySuggestionModel *self,
+ const gchar *query,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ephy_suggestion_model_query_finish (EphySuggestionModel *self,
+ GAsyncResult *result,
+ GError **error);
+EphySuggestion *ephy_suggestion_model_get_suggestion_with_uri (EphySuggestionModel *self,
+ const char *uri);
+
+G_END_DECLS
diff --git a/src/ephy-window.c b/src/ephy-window.c
index 96af17078..2883c0d02 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -53,6 +53,7 @@
#include "popup-commands.h"
#include "window-commands.h"
+#include <dazzle.h>
#include <gdk/gdkkeysyms.h>
#include <gdk/gdkx.h>
#include <gio/gio.h>
@@ -74,6 +75,10 @@ static void ephy_window_change_allow_popup_windows_state (GSimpleAction *action,
GVariant *state,
gpointer user_data);
+static void ephy_window_embed_container_iface_init (EphyEmbedContainerInterface *iface);
+
+static void ephy_window_link_iface_init (EphyLinkInterface *iface);
+
const struct {
const char *action_and_target;
const char *accelerators[9];
@@ -138,7 +143,7 @@ const struct {
#define SETTINGS_CONNECTION_DATA_KEY "EphyWindowSettings"
struct _EphyWindow {
- GtkApplicationWindow parent_instance;
+ DzlApplicationWindow parent_instance;
GtkWidget *header_bar;
EphyBookmarksManager *bookmarks_manager;
@@ -185,6 +190,13 @@ enum {
SENS_FLAG_IS_BLANK = 1 << 5
};
+G_DEFINE_TYPE_WITH_CODE (EphyWindow, ephy_window, DZL_TYPE_APPLICATION_WINDOW,
+ G_IMPLEMENT_INTERFACE (EPHY_TYPE_LINK,
+ ephy_window_link_iface_init)
+ G_IMPLEMENT_INTERFACE (EPHY_TYPE_EMBED_CONTAINER,
+ ephy_window_embed_container_iface_init))
+
+
static gint
impl_add_child (EphyEmbedContainer *container,
EphyEmbed *child,
@@ -393,12 +405,6 @@ ephy_window_link_iface_init (EphyLinkInterface *iface)
iface->open_link = ephy_window_open_link;
}
-G_DEFINE_TYPE_WITH_CODE (EphyWindow, ephy_window, GTK_TYPE_APPLICATION_WINDOW,
- G_IMPLEMENT_INTERFACE (EPHY_TYPE_LINK,
- ephy_window_link_iface_init)
- G_IMPLEMENT_INTERFACE (EPHY_TYPE_EMBED_CONTAINER,
- ephy_window_embed_container_iface_init))
-
static void
sync_chromes_visibility (EphyWindow *window)
{
@@ -3316,7 +3322,7 @@ ephy_window_activate_location (EphyWindow *window)
title_widget = ephy_header_bar_get_title_widget (EPHY_HEADER_BAR (window->header_bar));
if (EPHY_IS_LOCATION_ENTRY (title_widget))
- ephy_location_entry_activate (EPHY_LOCATION_ENTRY (title_widget));
+ ephy_location_entry_focus (EPHY_LOCATION_ENTRY (title_widget));
}
/**
diff --git a/src/ephy-window.h b/src/ephy-window.h
index ff01c3ffd..edec1a98f 100644
--- a/src/ephy-window.h
+++ b/src/ephy-window.h
@@ -25,13 +25,14 @@
#include "ephy-location-controller.h"
#include "ephy-web-view.h"
+#include <dazzle.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define EPHY_TYPE_WINDOW (ephy_window_get_type ())
-G_DECLARE_FINAL_TYPE (EphyWindow, ephy_window, EPHY, WINDOW, GtkApplicationWindow)
+G_DECLARE_FINAL_TYPE (EphyWindow, ephy_window, EPHY, WINDOW, DzlApplicationWindow)
typedef enum
{
diff --git a/src/meson.build b/src/meson.build
index 2d810a6c2..1373b58ab 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -22,7 +22,6 @@ libephymain_sources = [
'clear-data-dialog.c',
'cookies-dialog.c',
'ephy-action-helper.c',
- 'ephy-completion-model.c',
'ephy-encoding-dialog.c',
'ephy-encoding-row.c',
'ephy-header-bar.c',
@@ -34,6 +33,7 @@ libephymain_sources = [
'ephy-search-engine-dialog.c',
'ephy-session.c',
'ephy-shell.c',
+ 'ephy-suggestion-model.c',
'ephy-window.c',
'passwords-dialog.c',
'popup-commands.c',
@@ -102,7 +102,6 @@ executable('epiphany-search-provider',
install_rpath: pkglibdir
)
-
resource_files = files('resources/epiphany.gresource.xml')
resources = gnome.compile_resources('epiphany-resources',
resource_files,
diff --git a/src/search-provider/ephy-search-provider.c b/src/search-provider/ephy-search-provider.c
index daa04f36b..076c86b4d 100644
--- a/src/search-provider/ephy-search-provider.c
+++ b/src/search-provider/ephy-search-provider.c
@@ -23,11 +23,12 @@
#include "ephy-search-provider.h"
#include "ephy-bookmarks-manager.h"
-#include "ephy-completion-model.h"
#include "ephy-file-helpers.h"
#include "ephy-prefs.h"
#include "ephy-profile-utils.h"
#include "ephy-shell.h"
+#include "ephy-suggestion-model.h"
+#include "ephy-uri-helpers.h"
#include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
@@ -43,7 +44,7 @@ struct _EphySearchProvider {
GSettings *settings;
EphyBookmarksManager *bookmarks_manager;
- EphyCompletionModel *model;
+ EphySuggestionModel *model;
};
struct _EphySearchProviderClass {
@@ -55,29 +56,29 @@ G_DEFINE_TYPE (EphySearchProvider, ephy_search_provider, G_TYPE_APPLICATION)
#define INACTIVITY_TIMEOUT 60 * 1000 /* One minute, in milliseconds */
static void
-on_model_updated (EphyHistoryService *service,
- gboolean success,
- gpointer result_data,
- gpointer user_data)
+on_model_updated (GObject *source_object,
+ GAsyncResult *result,
+ GTask *task)
{
- GTask *task = user_data;
EphySearchProvider *self = g_task_get_source_object (task);
- GtkTreeModel *model = GTK_TREE_MODEL (self->model);
- GtkTreeIter iter;
+ EphySuggestion *suggestion;
GPtrArray *results;
const char *search_string;
- gboolean ok;
-
+ guint n_items;
+ GError *error = NULL;
results = g_ptr_array_new ();
- ok = gtk_tree_model_get_iter_first (model, &iter);
- while (ok) {
- char *result;
-
- result = gtk_tree_model_get_string_from_iter (model, &iter);
- g_ptr_array_add (results, result);
-
- ok = gtk_tree_model_iter_next (model, &iter);
+ if (ephy_suggestion_model_query_finish (self->model,
+ result,
+ &error)) {
+ n_items = g_list_model_get_n_items (G_LIST_MODEL (self->model));
+ for (guint i = 0; i < n_items; i++) {
+ suggestion = g_list_model_get_item (G_LIST_MODEL (self->model), i);
+ g_ptr_array_add (results, g_strdup (ephy_suggestion_get_uri (suggestion)));
+ }
+ } else {
+ g_warning ("Failed to query suggestion model: %s", error->message);
+ g_error_free (error);
}
search_string = g_task_get_task_data (task);
@@ -106,16 +107,16 @@ gather_results_async (EphySearchProvider *self,
{
GTask *task;
char *search_string;
-
task = g_task_new (self, cancellable, callback, user_data);
search_string = g_strjoinv (" ", terms);
g_task_set_task_data (task, search_string, g_free);
- ephy_completion_model_update_for_string (self->model,
- search_string,
- on_model_updated,
- task);
+ ephy_suggestion_model_query_async (self->model,
+ search_string,
+ cancellable,
+ (GAsyncReadyCallback)on_model_updated,
+ task);
}
static void
@@ -126,7 +127,6 @@ complete_request (GObject *object,
EphySearchProvider *self = EPHY_SEARCH_PROVIDER (object);
char **results;
GError *error;
-
error = NULL;
results = gather_results_finish (self, result, &error);
@@ -177,14 +177,8 @@ handle_get_result_metas (EphyShellSearchProvider2 *skeleton,
char **results,
EphySearchProvider *self)
{
- GtkTreeModel *model = GTK_TREE_MODEL (self->model);
- GtkTreeIter iter;
int i;
GVariantBuilder builder;
- GIcon *favicon;
- char *name, *url;
- gboolean is_bookmark;
-
g_application_hold (G_APPLICATION (self));
g_cancellable_cancel (self->cancellable);
@@ -201,54 +195,28 @@ handle_get_result_metas (EphyShellSearchProvider2 *skeleton,
g_variant_builder_add (&builder, "{sv}",
"gicon", g_variant_new_string ("org.gnome.Epiphany"));
g_variant_builder_close (&builder);
- continue;
- }
-
- if (!gtk_tree_model_get_iter_from_string (model, &iter, results[i]))
- continue;
-
- gtk_tree_model_get (model, &iter,
- EPHY_COMPLETION_TEXT_COL, &name,
- EPHY_COMPLETION_URL_COL, &url,
- EPHY_COMPLETION_FAVICON_COL, &favicon,
- EPHY_COMPLETION_EXTRA_COL, &is_bookmark,
- -1);
+ } else {
+ EphySuggestion *suggestion;
+ const char *title;
+ const char *uri;
+ char *decoded_uri;
- g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (&builder, "{sv}",
- "id", g_variant_new_string (url));
- g_variant_builder_add (&builder, "{sv}",
- "name", g_variant_new_string (name));
+ suggestion = ephy_suggestion_model_get_suggestion_with_uri (self->model, results[i]);
+ title = ephy_suggestion_get_unescaped_title (suggestion);
+ uri = ephy_suggestion_get_uri (suggestion);
+ decoded_uri = ephy_uri_decode (uri);
- if (favicon == NULL) {
- char *type;
-
- type = g_content_type_from_mime_type ("text/html");
- favicon = g_content_type_get_icon (type);
-
- if (is_bookmark) {
- GEmblem *emblem;
- GIcon *emblem_icon, *emblemed;
-
- emblem_icon = g_themed_icon_new ("emblem-favorite");
- emblem = g_emblem_new (emblem_icon);
-
- emblemed = g_emblemed_icon_new (favicon, emblem);
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}",
+ "id", g_variant_new_string (decoded_uri));
+ g_variant_builder_add (&builder, "{sv}",
+ "name", g_variant_new_string (title));
+ g_variant_builder_add (&builder, "{sv}",
+ "gicon", g_variant_new_string ("text-html"));
+ g_variant_builder_close (&builder);
- g_object_unref (emblem);
- g_object_unref (emblem_icon);
- g_object_unref (favicon);
- favicon = emblemed;
- }
+ g_free (decoded_uri);
}
-
- g_variant_builder_add (&builder, "{sv}",
- "icon", g_icon_serialize (favicon));
- g_variant_builder_close (&builder);
-
- g_object_unref (favicon);
- g_free (name);
- g_free (url);
}
ephy_shell_search_provider2_complete_get_result_metas (skeleton,
@@ -265,7 +233,6 @@ launch_uri (const char *uri,
guint timestamp)
{
char *str;
-
/* TODO: Handle the timestamp */
str = g_strdup_printf ("epiphany %s", uri);
g_spawn_command_line_async (str, NULL);
@@ -370,7 +337,7 @@ ephy_search_provider_init (EphySearchProvider *self)
filename = g_build_filename (ephy_dot_dir (), EPHY_HISTORY_FILE, NULL);
self->bookmarks_manager = ephy_bookmarks_manager_new ();
- self->model = ephy_completion_model_new (ephy_embed_shell_get_global_history_service (shell),
+ self->model = ephy_suggestion_model_new (ephy_embed_shell_get_global_history_service (shell),
self->bookmarks_manager);
g_free (filename);
diff --git a/tests/ephy-completion-model-test.c b/tests/ephy-completion-model-test.c
deleted file mode 100644
index 869d16b56..000000000
--- a/tests/ephy-completion-model-test.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/*
- * Copyright © 2012 Igalia S.L.
- *
- * This file is part of Epiphany.
- *
- * Epiphany 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.
- *
- * Epiphany 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 Epiphany. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include "ephy-completion-model.h"
-
-#include "ephy-debug.h"
-#include "ephy-embed-prefs.h"
-#include "ephy-file-helpers.h"
-#include "ephy-shell.h"
-
-static void
-test_ephy_completion_model_create (void)
-{
- EphyCompletionModel *model;
- model = ephy_completion_model_new (ephy_embed_shell_get_global_history_service (ephy_embed_shell_get_default ()),
- ephy_shell_get_bookmarks_manager (ephy_shell_get_default ()));
- g_assert (model);
- g_object_unref (model);
-}
-
-static void
-update_empty_cb (EphyHistoryService *service,
- gboolean success,
- gpointer result_data,
- GMainLoop *loop)
-{
- GList *results = (GList *)result_data;
-
- g_assert (success);
- g_assert (results == NULL);
-
- g_main_loop_quit (loop);
-}
-
-static void
-test_ephy_completion_model_update_empty (void)
-{
- EphyCompletionModel *model;
- GMainLoop *loop = NULL;
-
- model = ephy_completion_model_new (ephy_embed_shell_get_global_history_service (ephy_embed_shell_get_default ()),
- ephy_shell_get_bookmarks_manager (ephy_shell_get_default ()));
- g_assert (model);
-
- loop = g_main_loop_new (NULL, FALSE);
-
- ephy_completion_model_update_for_string (model, "hello",
- (EphyHistoryJobCallback)update_empty_cb,
- loop);
-
- g_main_loop_run (loop);
-
- g_object_unref (model);
- g_main_loop_unref (loop);
-}
-
-int
-main (int argc, char *argv[])
-{
- gboolean ret;
-
- gtk_test_init (&argc, &argv);
- ephy_debug_init ();
-
- if (!ephy_file_helpers_init (NULL,
- EPHY_FILE_HELPERS_PRIVATE_PROFILE | EPHY_FILE_HELPERS_ENSURE_EXISTS,
- NULL)) {
- g_debug ("Something wrong happened with ephy_file_helpers_init()");
- return -1;
- }
-
- _ephy_shell_create_instance (EPHY_EMBED_SHELL_MODE_TEST);
-
- g_test_add_func ("/src/ephy-completion-model/create",
- test_ephy_completion_model_create);
-
- g_test_add_func ("/src/ephy-completion-model/update_empty",
- test_ephy_completion_model_update_empty);
-
- ret = g_test_run ();
-
- return ret;
-}
diff --git a/tests/ephy-location-entry-test.c b/tests/ephy-location-entry-test.c
deleted file mode 100644
index bcd6bebaa..000000000
--- a/tests/ephy-location-entry-test.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/*
- * Copyright © 2008 Diego Escalante Urrelo
- *
- * This file is part of Epiphany.
- *
- * Epiphany 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.
- *
- * Epiphany 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 Epiphany. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include "ephy-debug.h"
-#include "ephy-location-entry.h"
-#include "ephy-title-widget.h"
-#include <glib.h>
-#include <gtk/gtk.h>
-
-static void
-test_entry_new (void)
-{
- GtkWidget *entry;
- entry = ephy_location_entry_new ();
-
- g_assert (GTK_IS_WIDGET (entry));
- g_assert (EPHY_IS_LOCATION_ENTRY (entry));
-}
-
-static void
-test_entry_get_entry (void)
-{
- EphyLocationEntry *entry;
- entry = EPHY_LOCATION_ENTRY (ephy_location_entry_new ());
-
- g_assert (GTK_IS_ENTRY (entry));
-}
-
-static void
-test_entry_set_location (void)
-{
- const char *set = "test";
- const char *get;
-
- EphyTitleWidget *widget;
- widget = EPHY_TITLE_WIDGET (ephy_location_entry_new ());
-
- ephy_title_widget_set_address (widget, set);
- get = ephy_title_widget_get_address (widget);
- g_assert_cmpstr (set, ==, get);
-}
-
-static void
-test_entry_set_location_null (void)
-{
- const char *set = "test";
- const char *get;
-
- EphyTitleWidget *widget;
- widget = EPHY_TITLE_WIDGET (ephy_location_entry_new ());
-
- ephy_title_widget_set_address (widget, NULL);
- get = ephy_title_widget_get_address (widget);
- g_assert_cmpstr (set, !=, get);
-}
-
-static void
-test_entry_get_location (void)
-{
- const char *set = "test";
- const char *get;
-
- EphyTitleWidget *widget;
- widget = EPHY_TITLE_WIDGET (ephy_location_entry_new ());
-
- ephy_title_widget_set_address (widget, set);
- get = ephy_title_widget_get_address (widget);
- g_assert_cmpstr (set, ==, get);
-}
-
-static void
-test_entry_get_location_empty (void)
-{
- const char *get;
-
- EphyTitleWidget *widget;
- widget = EPHY_TITLE_WIDGET (ephy_location_entry_new ());
-
- get = ephy_title_widget_get_address (widget);
- g_assert_cmpstr ("", ==, get);
-}
-
-static void
-test_entry_can_undo (void)
-{
- const char *test = "test";
-
- EphyLocationEntry *entry;
- entry = EPHY_LOCATION_ENTRY (ephy_location_entry_new ());
-
- g_assert_cmpint (ephy_location_entry_get_can_undo (entry), ==, FALSE);
-
- /* Use gtk_* function or otherwise user_changed won't be correctly handled
- * internally by the location entry (see editable_changed_cb and
- * block_update) */
- gtk_entry_set_text (GTK_ENTRY (entry), test);
- g_assert_cmpint (ephy_location_entry_get_can_undo (entry), ==, TRUE);
-}
-
-static void
-test_entry_can_redo (void)
-{
- const char *test = "test";
-
- EphyLocationEntry *entry;
- entry = EPHY_LOCATION_ENTRY (ephy_location_entry_new ());
- g_assert_cmpint (ephy_location_entry_get_can_redo (entry), ==, FALSE);
-
- /* Can't redo, in this point we can undo */
- ephy_title_widget_set_address (EPHY_TITLE_WIDGET (entry), test);
- g_assert_cmpint (ephy_location_entry_get_can_redo (entry), ==, FALSE);
-
- /* Reset should set redo to TRUE */
- ephy_location_entry_reset (entry);
- g_assert_cmpint (ephy_location_entry_get_can_redo (entry), ==, TRUE);
-}
-
-int
-main (int argc, char *argv[])
-{
- gtk_test_init (&argc, &argv);
- ephy_debug_init ();
-
- g_test_add_func ("/lib/widgets/ephy-location-entry/new",
- test_entry_new);
- g_test_add_func ("/lib/widgets/ephy-location-entry/get_entry",
- test_entry_get_entry);
- g_test_add_func ("/lib/widgets/ephy-location-entry/set_location",
- test_entry_set_location);
- g_test_add_func ("/lib/widgets/ephy-location-entry/get_location",
- test_entry_get_location);
- g_test_add_func ("/lib/widgets/ephy-location-entry/set_location_null",
- test_entry_set_location_null);
- g_test_add_func ("/lib/widgets/ephy-location-entry/get_location_empty",
- test_entry_get_location_empty);
- g_test_add_func ("/lib/widgets/ephy-location-entry/can_undo",
- test_entry_can_undo);
- g_test_add_func ("/lib/widgets/ephy-location-entry/can_redo",
- test_entry_can_redo);
-
- return g_test_run ();
-}
diff --git a/tests/meson.build b/tests/meson.build
index 8ced8ebb5..b86fc41a2 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -9,13 +9,7 @@ if get_option('unit_tests')
# ephytestutils_dep = declare_dependency(
# link_with: libephytestutils
# )
-
- completion_model_test = executable('test-ephy-completion-model',
- 'ephy-completion-model-test.c',
- dependencies: ephymain_dep
- )
- test('Completion model test', completion_model_test)
-
+ #
# FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=778153
# download_test = executable('test-ephy-download',
# 'ephy-download-test.c',
@@ -61,12 +55,6 @@ if get_option('unit_tests')
)
test('History test', history_test)
- location_entry_test = executable('test-location-entry',
- 'ephy-location-entry-test.c',
- dependencies: ephymain_dep
- )
- test('Location entry test', location_entry_test)
-
migration_test = executable('test-ephy-migration',
'ephy-migration-test.c',
dependencies: ephymain_dep