[evolution/webkit-composer] Bug #689788, Bug #689792 - Links in WebKit composer Fixes links highlighting and other things relate



commit 76897955a942a91095e48679a732bab2228f5240
Author: Tomas Popela <tpopela redhat com>
Date:   Tue Apr 16 09:48:06 2013 +0200

    Bug #689788, Bug #689792 - Links in WebKit composer
    Fixes links highlighting and other things related to links in WebKit composer.

 e-util/e-editor-link-dialog.c |  15 +++-
 e-util/e-editor-selection.c   |  29 ++++++-
 e-util/e-editor-widget.c      | 176 ++++++++++++++++++++++++++++++++++++++++++
 e-util/e-editor-widget.h      |   2 +
 4 files changed, 219 insertions(+), 3 deletions(-)
---
diff --git a/e-util/e-editor-link-dialog.c b/e-util/e-editor-link-dialog.c
index 1674e19..a63f4bb 100644
--- a/e-util/e-editor-link-dialog.c
+++ b/e-util/e-editor-link-dialog.c
@@ -148,6 +148,11 @@ editor_link_dialog_ok (EEditorLinkDialog *dialog)
                                webkit_dom_range_get_end_container (range, NULL),
                                webkit_dom_range_get_end_offset (range, NULL),
                                NULL);
+               } else {
+                       /* get element that was clicked on */
+                       link = e_editor_widget_get_element_under_mouse_click (widget);
+                       if (!WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (link))
+                               link = NULL;
                }
        }
 
@@ -155,6 +160,10 @@ editor_link_dialog_ok (EEditorLinkDialog *dialog)
                webkit_dom_html_anchor_element_set_href (
                        WEBKIT_DOM_HTML_ANCHOR_ELEMENT (link),
                        gtk_entry_get_text (GTK_ENTRY (dialog->priv->url_edit)));
+               webkit_dom_html_element_set_inner_html (
+                       WEBKIT_DOM_HTML_ELEMENT (link),
+                       gtk_entry_get_text (GTK_ENTRY (dialog->priv->label_edit)),
+                       NULL);
        } else {
                gchar *text;
 
@@ -247,6 +256,11 @@ editor_link_dialog_show (GtkWidget *widget)
                        fragment = webkit_dom_range_clone_contents (range, NULL);
                        link = e_editor_dom_node_find_child_element (
                                        WEBKIT_DOM_NODE (fragment), "A");
+               } else {
+                       /* get element that was clicked on */
+                       link = e_editor_widget_get_element_under_mouse_click (editor_widget);
+                       if (!WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (link))
+                               link = NULL;
                }
        }
 
@@ -262,7 +276,6 @@ editor_link_dialog_show (GtkWidget *widget)
                        GTK_ENTRY (dialog->priv->url_edit), href);
                gtk_entry_set_text (
                        GTK_ENTRY (dialog->priv->label_edit), text);
-               gtk_widget_set_sensitive (dialog->priv->label_edit, FALSE);
 
                g_free (text);
                g_free (href);
diff --git a/e-util/e-editor-selection.c b/e-util/e-editor-selection.c
index 598c7ce..3ee2b8c 100644
--- a/e-util/e-editor-selection.c
+++ b/e-util/e-editor-selection.c
@@ -2013,15 +2013,40 @@ e_editor_selection_unlink (EEditorSelection *selection)
 {
        EEditorWidget *editor_widget;
        EEditorWidgetCommand command;
+       WebKitDOMDocument *document;
+       WebKitDOMDOMWindow *window;
+       WebKitDOMDOMSelection *dom_selection;
+       WebKitDOMRange *range;
+       WebKitDOMElement *link;
 
        g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
 
        editor_widget = e_editor_selection_ref_editor_widget (selection);
        g_return_if_fail (editor_widget != NULL);
 
-       command = E_EDITOR_WIDGET_COMMAND_UNLINK;
-       e_editor_widget_exec_command (editor_widget, command, NULL);
+       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (editor_widget));
+       window = webkit_dom_document_get_default_view (document);
+       dom_selection = webkit_dom_dom_window_get_selection (window);
 
+       range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+       link = e_editor_dom_node_find_parent_element (
+                       webkit_dom_range_get_start_container (range, NULL), "A");
+
+       if (!link) {
+               gchar *text;
+               /* get element that was clicked on */
+               link = e_editor_widget_get_element_under_mouse_click (editor_widget);
+               if (!WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (link))
+                       link = NULL;
+
+               text = webkit_dom_html_element_get_inner_text (
+                               WEBKIT_DOM_HTML_ELEMENT (link));
+               webkit_dom_html_element_set_outer_html (WEBKIT_DOM_HTML_ELEMENT (link), text, NULL);
+               g_free (text);
+       } else {
+               command = E_EDITOR_WIDGET_COMMAND_UNLINK;
+               e_editor_widget_exec_command (editor_widget, command, NULL);
+       }
        g_object_unref (editor_widget);
 }
 
diff --git a/e-util/e-editor-widget.c b/e-util/e-editor-widget.c
index 18a2451..d07bfc8 100644
--- a/e-util/e-editor-widget.c
+++ b/e-util/e-editor-widget.c
@@ -59,6 +59,8 @@ struct _EEditorWidgetPrivate {
 
        EEditorSelection *selection;
 
+       WebKitDOMElement *element_under_mouse;
+
        GSettings *font_settings;
        GSettings *aliasing_settings;
 
@@ -301,6 +303,147 @@ static const gchar *emoticons_icon_names[] = {
 };
 
 static void
+editor_widget_check_magic_links (EEditorWidget *widget,
+                                WebKitDOMRange *range)
+{
+       gchar *node_text;
+       gchar **urls;
+       GRegex *regex = NULL;
+       GMatchInfo *match_info;
+       gint start_pos_url, end_pos_url, end_input;
+       WebKitDOMNode *node;
+
+       const gchar *url_pattern = "((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[\\-;:&=\\+\\$,\\w]+@)?"
+                                  "[A-Za-z0-9\\.\\-]+|(?:www\\.|[\\-;:&=\\+\\$,\\w]+@)"
+                                  "[A-Za-z0-9\\.\\-]+)((?:\\/[\\+~%\\/\\.\\w\\-]*)?\\?"
+                                  "?(?:[\\-\\+=&;% \\ \\w]*)#?(?:[\\.\\!\\/\\\\w]*))?)\\s";
+
+       node = webkit_dom_range_get_end_container (range, NULL);
+
+       if (!WEBKIT_DOM_IS_TEXT (node))
+               return;
+
+       node_text = webkit_dom_text_get_whole_text (WEBKIT_DOM_TEXT (node));
+       if (!node_text)
+               return;
+
+       end_input = webkit_dom_range_get_end_offset (range, NULL) - 1;
+
+       regex = g_regex_new (url_pattern, 0, 0, NULL);
+
+       if (!regex) {
+               g_free (node_text);
+               return;
+       }
+
+       g_regex_match_all (regex, node_text, G_REGEX_MATCH_NOTEMPTY, &match_info);
+       urls = g_match_info_fetch_all (match_info);
+
+       if (urls) {
+               gchar *html, *url, *final_url;
+               WebKitDOMDocument *document;
+               WebKitDOMDOMWindow *window;
+               WebKitDOMDOMSelection *selection;
+
+               g_match_info_fetch_pos (match_info, 0, &start_pos_url, &end_pos_url);
+
+               url = g_strndup (urls[0], end_input - start_pos_url);
+
+               /* Select the link and put it inside <A> */
+               document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
+               window = webkit_dom_document_get_default_view (document);
+               selection = webkit_dom_dom_window_get_selection (window);
+
+               webkit_dom_dom_selection_set_base_and_extent (
+                       selection, webkit_dom_range_get_end_container (range, NULL),
+                       end_input, webkit_dom_range_get_end_container (range, NULL),
+                       start_pos_url, NULL);
+
+               if (g_str_has_prefix (url, "www"))
+                       final_url = g_strconcat ("http://";, url, NULL);
+               else
+                       final_url = g_strdup (url);
+
+               html = g_strdup_printf ("<a href=\"%s\">%s</a>", final_url, url);
+
+               e_editor_selection_insert_html (widget->priv->selection, html);
+
+               webkit_dom_dom_selection_modify (selection, "move", "right", "character");
+
+               g_free (html);
+               g_free (url);
+               g_free (final_url);
+       }
+       else {
+               gchar *href, *text, *url;
+               gint diff;
+               WebKitDOMElement *parent;
+
+               parent = webkit_dom_node_get_parent_element (node);
+               /* if parent is href => we're editing the link */
+               if (!WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent)) {
+                       g_match_info_free (match_info);
+                       g_regex_unref (regex);
+                       g_free (node_text);
+                       return;
+               }
+
+               /* edit only if href and description are the same */
+               href = webkit_dom_html_anchor_element_get_href (
+                               WEBKIT_DOM_HTML_ANCHOR_ELEMENT (parent));
+               text = webkit_dom_html_element_get_inner_text (
+                               WEBKIT_DOM_HTML_ELEMENT (parent));
+
+               if (strstr (href, "://") && !strstr (text, "://")) {
+                       url = strstr (href, "://") + 3;
+                       diff = strlen (text) - strlen (url);
+
+                       if (text [strlen (text) - 1] != '/')
+                               diff++;
+
+                       if (g_strcmp0 (url, text) != 0 && ABS (diff) == 1) {
+                               gchar *inner_html, *protocol, *new_href;
+
+                               protocol = g_strndup (href, strstr (href, "://") - href + 3);
+                               inner_html = webkit_dom_html_element_get_inner_html (WEBKIT_DOM_HTML_ELEMENT 
(parent));
+                               new_href = g_strconcat (protocol, inner_html, NULL);
+
+                               webkit_dom_html_anchor_element_set_href (WEBKIT_DOM_HTML_ANCHOR_ELEMENT 
(parent), new_href);
+
+                               g_free (new_href);
+                               g_free (protocol);
+                               g_free (inner_html);
+                       }
+               }
+               else {
+                       diff = strlen (text) - strlen (href);
+                       if (text [strlen (text) - 1] != '/')
+                               diff++;
+
+                       if (g_strcmp0 (href, text) != 0 && ABS (diff) == 1) {
+                               gchar *inner_html;
+                               gchar *new_href;
+
+                               inner_html = webkit_dom_html_element_get_inner_html (WEBKIT_DOM_HTML_ELEMENT 
(parent));
+                               new_href = g_strconcat (inner_html, NULL);
+
+                               webkit_dom_html_anchor_element_set_href (WEBKIT_DOM_HTML_ANCHOR_ELEMENT 
(parent), new_href);
+
+                               g_free (new_href);
+                               g_free (inner_html);
+                       }
+
+               }
+               g_free (text);
+               g_free (href);
+       }
+
+       g_match_info_free (match_info);
+       g_regex_unref (regex);
+       g_free (node_text);
+}
+
+static void
 editor_widget_check_magic_smileys (EEditorWidget *widget,
                                    WebKitDOMRange *range)
 {
@@ -610,6 +753,29 @@ editor_widget_constructed (GObject *object)
        G_OBJECT_CLASS (e_editor_widget_parent_class)->constructed (object);
 }
 
+static void
+editor_widget_save_element_under_mouse_click (GtkWidget *widget)
+{
+       gint x, y;
+       GdkDeviceManager *device_manager;
+       GdkDevice *pointer;
+       EEditorWidget *editor_widget;
+       WebKitDOMDocument *document;
+       WebKitDOMElement *element;
+
+       g_return_if_fail (E_IS_EDITOR_WIDGET (widget));
+
+       device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (widget)));
+       pointer = gdk_device_manager_get_client_pointer (device_manager);
+       gdk_window_get_device_position (gtk_widget_get_window (GTK_WIDGET (widget)), pointer, &x, &y, NULL);
+
+       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
+       element = webkit_dom_document_element_from_point (document, x, y);
+
+       editor_widget = E_EDITOR_WIDGET (widget);
+       editor_widget->priv->element_under_mouse = element;
+}
+
 static gboolean
 editor_widget_button_press_event (GtkWidget *widget,
                                   GdkEventButton *event)
@@ -619,6 +785,7 @@ editor_widget_button_press_event (GtkWidget *widget,
        if (event->button != 3) {
                event_handled = FALSE;
        } else {
+               editor_widget_save_element_under_mouse_click (widget);
                g_signal_emit (
                        widget, signals[POPUP_EVENT],
                        0, event, &event_handled);
@@ -724,6 +891,8 @@ editor_widget_key_release_event (GtkWidget *widget,
                editor_widget_check_magic_smileys (editor_widget, range);
        }
 
+       editor_widget_check_magic_links (editor_widget, range);
+
        if ((event->keyval == GDK_KEY_Control_L) ||
            (event->keyval == GDK_KEY_Control_R)) {
 
@@ -1864,3 +2033,10 @@ e_editor_widget_update_fonts (EEditorWidget *widget)
        pango_font_description_free (vw);
 }
 
+WebKitDOMElement *
+e_editor_widget_get_element_under_mouse_click (EEditorWidget *widget)
+{
+       g_return_val_if_fail (E_IS_EDITOR_WIDGET (widget), NULL);
+
+       return widget->priv->element_under_mouse;
+}
diff --git a/e-util/e-editor-widget.h b/e-util/e-editor-widget.h
index b349d2c..e2831ad 100644
--- a/e-util/e-editor-widget.h
+++ b/e-util/e-editor-widget.h
@@ -108,6 +108,8 @@ void                e_editor_widget_paste_clipboard_quoted
                                                (EEditorWidget *widget);
 void           e_editor_widget_update_fonts    (EEditorWidget *widget);
 
+WebKitDOMElement *
+               e_editor_widget_get_element_under_mouse_click (EEditorWidget *widget);
 G_END_DECLS
 
 #endif /* E_EDITOR_WIDGET_H */


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