[evolution/webkit: 180/196] Drop ESearchingTokenizer a reimplement highlighting directly in EWebView



commit ef9371618afccc348fa4db63c9f9dd04af997c3b
Author: Dan VrÃtil <dvratil redhat com>
Date:   Tue Mar 6 17:04:34 2012 +0100

    Drop ESearchingTokenizer a reimplement highlighting directly in EWebView

 data/webview.css                     |    5 +
 mail/e-mail-paned-view.c             |   24 +-
 widgets/misc/Makefile.am             |    2 -
 widgets/misc/e-search-bar.c          |    6 -
 widgets/misc/e-searching-tokenizer.c | 1210 ----------------------------------
 widgets/misc/e-searching-tokenizer.h |   91 ---
 widgets/misc/e-web-view.c            |  190 ++++++
 widgets/misc/e-web-view.h            |    4 +
 8 files changed, 209 insertions(+), 1323 deletions(-)
---
diff --git a/data/webview.css b/data/webview.css
index 30a37dc..687d06c 100644
--- a/data/webview.css
+++ b/data/webview.css
@@ -76,6 +76,11 @@ object { /* GtkWidgets */
   margin-bottom: 2px;
 }
 
+.__evo-highlight {
+  color: purple;
+  font-weight: bold;
+}
+
 /***** PRINTING *******/
 
 .printing-header {
diff --git a/mail/e-mail-paned-view.c b/mail/e-mail-paned-view.c
index 0902bbf..4b27b09 100644
--- a/mail/e-mail-paned-view.c
+++ b/mail/e-mail-paned-view.c
@@ -728,27 +728,23 @@ static void
 mail_paned_view_set_search_strings (EMailView *view,
                                     GSList *search_strings)
 {
-#if 0  /* WEBKIT */
-	EPreviewPane *preview_pane;
-	ESearchBar *search_bar;
-	ESearchingTokenizer *tokenizer;
+	EMailDisplay *display;
+        EWebView *web_view;
+        EMailReader *reader;
 
 	reader = E_MAIL_READER (view);
-	preview_pane = e_mail_reader_get_preview_pane (reader);
-	search_bar = e_preview_pane_get_search_bar (preview_pane);
-	tokenizer = e_search_bar_get_tokenizer (search_bar);
+	display = e_mail_reader_get_mail_display (reader);
+        if (!display)
+                return;
+
+        web_view = E_WEB_VIEW (display);
 
-	e_searching_tokenizer_set_secondary_case_sensitivity (tokenizer, FALSE);
-	e_searching_tokenizer_set_secondary_search_string (tokenizer, NULL);
+        e_web_view_clear_highlights (web_view);
 
 	while (search_strings != NULL) {
-		e_searching_tokenizer_add_secondary_search_string (
-			tokenizer, search_strings->data);
+		e_web_view_add_highlight (web_view, search_strings->data);
 		search_strings = g_slist_next (search_strings);
 	}
-
-	e_search_bar_changed (search_bar);
-#endif
 }
 
 static GalViewInstance *
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index 35155d1..ab7efa0 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -49,7 +49,6 @@ widgetsinclude_HEADERS =			\
 	e-preview-pane.h			\
 	e-printable.h				\
 	e-search-bar.h				\
-	e-searching-tokenizer.h			\
 	e-selectable.h				\
 	e-selection-model.h			\
 	e-selection-model-array.h		\
@@ -132,7 +131,6 @@ libemiscwidgets_la_SOURCES =			\
 	e-preview-pane.c			\
 	e-printable.c				\
 	e-search-bar.c				\
-	e-searching-tokenizer.c			\
 	e-selectable.c				\
 	e-selection-model.c			\
 	e-selection-model-array.c		\
diff --git a/widgets/misc/e-search-bar.c b/widgets/misc/e-search-bar.c
index 17a3732..0e39aa1 100644
--- a/widgets/misc/e-search-bar.c
+++ b/widgets/misc/e-search-bar.c
@@ -510,12 +510,6 @@ e_search_bar_init (ESearchBar *search_bar)
 
 	search_bar->priv = E_SEARCH_BAR_GET_PRIVATE (search_bar);
 
-#if 0  /* WEBKIT */
-	g_signal_connect_swapped (
-		search_bar->priv->tokenizer, "match",
-		G_CALLBACK (search_bar_update_matches), search_bar);
-#endif
-
 	gtk_box_set_spacing (GTK_BOX (search_bar), 12);
 
 	container = GTK_WIDGET (search_bar);
diff --git a/widgets/misc/e-web-view.c b/widgets/misc/e-web-view.c
index 4c766e0..319d6cb 100644
--- a/widgets/misc/e-web-view.c
+++ b/widgets/misc/e-web-view.c
@@ -58,6 +58,8 @@ struct _EWebViewPrivate {
 
 	GHashTable *js_callbacks;
 
+        GSList *highlights;
+
 	GtkAction *open_proxy;
 	GtkAction *print_proxy;
 	GtkAction *save_as_proxy;
@@ -349,6 +351,135 @@ web_view_menu_item_select_cb (EWebView *web_view,
 }
 
 static void
+replace_text (WebKitDOMNode *node,
+              const gchar *text,
+              WebKitDOMNode *replacement)
+{
+        /* NodeType 3 = TEXT_NODE */
+        if (webkit_dom_node_get_node_type (node) == 3) {
+
+                gint text_length = strlen (text);
+
+                while (node) {
+
+                        WebKitDOMNode *current_node, *replacement_node;
+                        const gchar *node_data, *offset;
+                        goffset split_offset;
+                        gint data_length;
+
+                        current_node = node;
+
+                        /* Don't use the WEBKIT_DOM_CHARACTER_DATA macro for
+                         * casting. WebKit lies about type of the object and
+                         * GLib will throw runtime warning about node not being
+                         * WebKitDOMCharacterData, but the function will return
+                         * correct and valid data.
+                         * IMO it's bug in the Gtk bindings and WebKit internally
+                         * handles it by the nodeType so therefor it works
+                         * event for "invalid" objects. But really, who knows..?
+                         */
+                        node_data = webkit_dom_character_data_get_data (
+                                        (WebKitDOMCharacterData *) node);
+
+                        offset = strstr (node_data, text);
+                        if (!offset) {
+                                node = NULL;
+                                continue;
+                        }
+
+                        split_offset = offset - node_data + text_length;
+                        replacement_node =
+                                webkit_dom_node_clone_node (replacement, TRUE);
+
+                        data_length = webkit_dom_character_data_get_length(
+                                        (WebKitDOMCharacterData *) node);
+                        if (split_offset < data_length) {
+
+                                WebKitDOMNode *parent_node;
+
+                                node = WEBKIT_DOM_NODE (
+                                        webkit_dom_text_split_text (
+                                                (WebKitDOMText *) node,
+                                                offset - node_data + text_length,
+                                                NULL));
+                                parent_node = webkit_dom_node_get_parent_node(node);
+                                webkit_dom_node_insert_before (
+                                        parent_node, replacement_node,
+                                        node, NULL);
+
+                        } else {
+                                WebKitDOMNode *parent_node;
+
+                                parent_node = webkit_dom_node_get_parent_node (node);
+                                webkit_dom_node_append_child (
+                                        parent_node,
+                                        replacement_node, NULL);
+                        }
+
+                        webkit_dom_character_data_delete_data (
+                                (WebKitDOMCharacterData *) (current_node),
+                                offset - node_data, text_length, NULL);
+                }
+
+        } else {
+
+                WebKitDOMNode *child, *next_child;
+
+                /* Iframe? Let's traverse inside! */
+                if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (node)) {
+
+                        WebKitDOMDocument *frame_document;
+
+                        frame_document =
+                                webkit_dom_html_iframe_element_get_content_document(
+                                        WEBKIT_DOM_HTML_IFRAME_ELEMENT (node));
+                        replace_text (WEBKIT_DOM_NODE (frame_document),
+                                      text, replacement);
+
+                } else {
+
+                        child = webkit_dom_node_get_first_child (node);
+                        while (child) {
+                                next_child = webkit_dom_node_get_next_sibling (child);
+                                replace_text (child, text, replacement);
+                                child = next_child;
+                        }
+                }
+        }
+
+}
+
+
+static void
+web_view_update_document_highlights (EWebView *web_view)
+{
+        WebKitDOMDocument *document;
+        GSList *iter;
+
+        document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (web_view));
+
+        for (iter = web_view->priv->highlights; iter; iter = iter->next) {
+
+                WebKitDOMDocumentFragment *frag;
+                WebKitDOMElement *span;
+
+                span = webkit_dom_document_create_element (document, "span", NULL);
+                webkit_dom_html_element_set_class_name (
+                        WEBKIT_DOM_HTML_ELEMENT (span), "__evo-highlight");
+                webkit_dom_html_element_set_inner_text (
+                        WEBKIT_DOM_HTML_ELEMENT (span), iter->data, NULL);
+
+                frag = webkit_dom_document_create_document_fragment (document);
+                webkit_dom_node_append_child (
+                        WEBKIT_DOM_NODE (frag), WEBKIT_DOM_NODE (span), NULL);
+
+                replace_text(WEBKIT_DOM_NODE (document),
+                        iter->data, WEBKIT_DOM_NODE (frag));
+        }
+}
+
+
+static void
 web_view_menu_item_deselect_cb (EWebView *web_view)
 {
 	e_web_view_status_message (web_view, NULL);
@@ -438,6 +569,20 @@ web_view_navigation_policy_decision_requested_cb (EWebView *web_view,
 }
 
 static void
+web_view_load_status_changed_cb (WebKitWebView *web_view,
+                                 GParamSpec *pspec,
+                                 gpointer user_data)
+{
+        WebKitLoadStatus status;
+
+        status = webkit_web_view_get_load_status (web_view);
+        if (status != WEBKIT_LOAD_FINISHED)
+                return;
+
+        web_view_update_document_highlights (E_WEB_VIEW (web_view));
+}
+
+static void
 web_view_set_property (GObject *object,
                        guint property_id,
                        const GValue *value,
@@ -657,6 +802,11 @@ web_view_dispose (GObject *object)
 		priv->js_callbacks = NULL;
 	}
 
+	if (priv->highlights != NULL) {
+                g_slist_free_full (priv->highlights, g_free);
+                priv->highlights = NULL;
+        }
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -1538,6 +1688,8 @@ e_web_view_init (EWebView *web_view)
 
 	web_view->priv = E_WEB_VIEW_GET_PRIVATE (web_view);
 
+        web_view->priv->highlights = NULL;
+
 	g_signal_connect (
 		web_view, "create-plugin-widget",
 		G_CALLBACK (web_view_create_plugin_widget_cb), NULL);
@@ -1551,6 +1703,10 @@ e_web_view_init (EWebView *web_view)
 		G_CALLBACK (web_view_navigation_policy_decision_requested_cb),
 		NULL);
 
+        g_signal_connect (
+                web_view, "notify::load-status",
+                G_CALLBACK (web_view_load_status_changed_cb), NULL);
+
 	ui_manager = gtk_ui_manager_new ();
 	web_view->priv->ui_manager = ui_manager;
 
@@ -2387,6 +2543,40 @@ e_web_view_set_save_as_proxy (EWebView *web_view,
 	g_object_notify (G_OBJECT (web_view), "save-as-proxy");
 }
 
+GSList*
+e_web_view_get_highlights (EWebView *web_view)
+{
+        g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
+
+        return web_view->priv->highlights;
+}
+
+void
+e_web_view_add_highlight (EWebView *web_view,
+                          const gchar *highlight)
+{
+        g_return_if_fail (E_IS_WEB_VIEW (web_view));
+        g_return_if_fail (highlight && *highlight);
+
+        web_view->priv->highlights =
+                g_slist_append (web_view->priv->highlights, g_strdup (highlight));
+
+        web_view_update_document_highlights (web_view);
+}
+
+void e_web_view_clear_highlights (EWebView *web_view)
+{
+        g_return_if_fail (E_IS_WEB_VIEW (web_view));
+
+        if (!web_view->priv->highlights)
+                return;
+
+        g_slist_free_full (web_view->priv->highlights, g_free);
+        web_view->priv->highlights = NULL;
+
+        web_view_update_document_highlights (web_view);
+}
+
 GtkAction *
 e_web_view_get_action (EWebView *web_view,
                        const gchar *action_name)
diff --git a/widgets/misc/e-web-view.h b/widgets/misc/e-web-view.h
index 6b32501..1562d84 100644
--- a/widgets/misc/e-web-view.h
+++ b/widgets/misc/e-web-view.h
@@ -186,6 +186,10 @@ void		e_web_view_set_print_proxy	(EWebView *web_view,
 GtkAction *	e_web_view_get_save_as_proxy	(EWebView *web_view);
 void		e_web_view_set_save_as_proxy	(EWebView *web_view,
 						 GtkAction *save_as_proxy);
+GSList*         e_web_view_get_highlights       (EWebView *web_view);
+void            e_web_view_add_highlight        (EWebView *web_view,
+                                                 const gchar *highlight);
+void            e_web_view_clear_highlights     (EWebView *web_view);
 GtkAction *	e_web_view_get_action		(EWebView *web_view,
 						 const gchar *action_name);
 GtkActionGroup *e_web_view_get_action_group	(EWebView *web_view,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]