[evolution] I#289 - 'Search web' context menu option for selection in EWebView
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] I#289 - 'Search web' context menu option for selection in EWebView
- Date: Wed, 30 Jan 2019 13:46:18 +0000 (UTC)
commit a0f102812e1e6998ff4ddccd3d9fa6e6be379e7b
Author: Milan Crha <mcrha redhat com>
Date: Wed Jan 30 14:45:05 2019 +0100
I#289 - 'Search web' context menu option for selection in EWebView
Closes https://gitlab.gnome.org/GNOME/evolution/issues/289
data/org.gnome.evolution.shell.gschema.xml.in | 5 +
data/ui/evolution-mail-reader.ui | 1 +
src/e-util/e-web-view.c | 175 ++++++++++++++++++++++++++
src/e-util/e-web-view.h | 13 ++
src/e-util/widgets.error.xml | 5 +
src/mail/e-mail-browser.c | 6 +-
src/mail/e-mail-reader.c | 31 +++++
src/web-extensions/e-dom-utils.c | 49 ++------
8 files changed, 246 insertions(+), 39 deletions(-)
---
diff --git a/data/org.gnome.evolution.shell.gschema.xml.in b/data/org.gnome.evolution.shell.gschema.xml.in
index ebfd602c8b..e982c9f7eb 100644
--- a/data/org.gnome.evolution.shell.gschema.xml.in
+++ b/data/org.gnome.evolution.shell.gschema.xml.in
@@ -125,6 +125,11 @@
<_summary>The last extension being used when backing up Evolution data.</_summary>
<_description>It can be either “.gz” or “.xz” and it influences what extension will be preselected in
the file chooser.</_description>
</key>
+ <key name="search-web-uri-prefix" type="s">
+ <default>'https://duckduckgo.com/?q='</default>
+ <_summary>Prefix of the URI to use to search the web with selected text.</_summary>
+ <_description>The prefix of a URL to be used for searches on the web. The actual text selection is
escaped and appended to this string. The URI should start with https://.</_description>
+ </key>
<child name="window" schema="org.gnome.evolution.window"/>
</schema>
</schemalist>
diff --git a/data/ui/evolution-mail-reader.ui b/data/ui/evolution-mail-reader.ui
index eff05c2971..ea90e50bb7 100644
--- a/data/ui/evolution-mail-reader.ui
+++ b/data/ui/evolution-mail-reader.ui
@@ -178,6 +178,7 @@
</popup>
<popup name='mail-preview-popup'>
<menuitem action='popup-copy-clipboard'/>
+ <menuitem action='mail-popup-search-web'/>
<separator/>
<menuitem action='mail-popup-reply-sender'/>
<menuitem action='mail-popup-reply-all'/>
diff --git a/src/e-util/e-web-view.c b/src/e-util/e-web-view.c
index a25dc472ec..df5721300a 100644
--- a/src/e-util/e-web-view.c
+++ b/src/e-util/e-web-view.c
@@ -144,6 +144,7 @@ static const gchar *ui =
"<ui>"
" <popup name='context'>"
" <menuitem action='copy-clipboard'/>"
+" <menuitem action='search-web'/>"
" <separator/>"
" <placeholder name='custom-actions-1'>"
" <menuitem action='open'/>"
@@ -207,6 +208,63 @@ action_copy_clipboard_cb (GtkAction *action,
e_web_view_copy_clipboard (web_view);
}
+static void
+e_web_view_search_web_get_selection_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ gchar *text;
+ GError *local_error = NULL;
+
+ g_return_if_fail (E_IS_WEB_VIEW (source));
+
+ text = e_web_view_get_selection_content_text_finish (E_WEB_VIEW (source), result, &local_error);
+
+ if (local_error &&
+ !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ e_alert_submit (E_ALERT_SINK (source), "widgets:get-selected-text-failed",
local_error->message, NULL);
+ } else if (!local_error) {
+ GSettings *settings;
+ gchar *uri_prefix;
+ gchar *escaped;
+ gchar *uri;
+
+ g_strstrip (text);
+
+ settings = e_util_ref_settings ("org.gnome.evolution.shell");
+ uri_prefix = g_settings_get_string (settings, "search-web-uri-prefix");
+ g_object_unref (settings);
+
+ escaped = camel_url_encode (text, "& ?#:;,/\\");
+
+ uri = g_strconcat (uri_prefix, escaped, NULL);
+ if (uri && g_ascii_strncasecmp (uri, "https://", 8) == 0) {
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (source));
+
+ e_show_uri (GTK_IS_WINDOW (toplevel) ? GTK_WINDOW (toplevel) : NULL, uri);
+ } else {
+ g_printerr ("Incorrect URI provided, expects https:// prefix, but has got: '%s'\n",
uri ? uri : "null");
+ }
+
+ g_free (uri_prefix);
+ g_free (escaped);
+ g_free (uri);
+ }
+
+ g_clear_error (&local_error);
+ g_free (text);
+}
+
+static void
+action_search_web_cb (GtkAction *action,
+ EWebView *web_view)
+{
+ e_web_view_get_selection_content_text (web_view, web_view->priv->load_cancellable,
+ e_web_view_search_web_get_selection_cb, NULL);
+}
+
static void
action_http_open_cb (GtkAction *action,
EWebView *web_view)
@@ -410,6 +468,13 @@ static GtkActionEntry selection_entries[] = {
"<Control>c",
N_("Copy the selection"),
G_CALLBACK (action_copy_clipboard_cb) },
+
+ { "search-web",
+ NULL,
+ N_("Search _Web…"),
+ NULL,
+ N_("Search the Web with the selected text"),
+ G_CALLBACK (action_search_web_cb) }
};
static GtkActionEntry standard_entries[] = {
@@ -3501,6 +3566,116 @@ e_web_view_get_selection_content_html_sync (EWebView *web_view,
return NULL;
}
+static void
+get_selection_content_text_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GDBusProxy *web_extension;
+ GTask *task = user_data;
+ GVariant *result_variant;
+ gchar *text_content = NULL;
+ GError *error = NULL;
+
+ g_return_if_fail (G_IS_DBUS_PROXY (source_object));
+ g_return_if_fail (G_IS_TASK (task));
+
+ web_extension = G_DBUS_PROXY (source_object);
+
+ result_variant = g_dbus_proxy_call_finish (web_extension, result, &error);
+ if (result_variant)
+ g_variant_get (result_variant, "(s)", &text_content);
+ g_variant_unref (result_variant);
+
+ g_task_return_pointer (task, text_content, g_free);
+ g_object_unref (task);
+
+ if (error)
+ g_dbus_error_strip_remote_error (error);
+
+ e_util_claim_dbus_proxy_call_error (web_extension, "GetSelectionContentText", error);
+ g_clear_error (&error);
+}
+
+void
+e_web_view_get_selection_content_text (EWebView *web_view,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDBusProxy *web_extension;
+ GTask *task;
+
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
+
+ task = g_task_new (web_view, cancellable, callback, user_data);
+
+ web_extension = e_web_view_get_web_extension_proxy (web_view);
+ if (web_extension) {
+ g_dbus_proxy_call (
+ web_extension,
+ "GetSelectionContentText",
+ g_variant_new (
+ "(t)",
+ webkit_web_view_get_page_id (
+ WEBKIT_WEB_VIEW (web_view))),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ get_selection_content_text_cb,
+ g_object_ref (task));
+ } else
+ g_task_return_pointer (task, NULL, NULL);
+}
+
+gchar *
+e_web_view_get_selection_content_text_finish (EWebView *web_view,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
+ g_return_val_if_fail (g_task_is_valid (result, web_view), FALSE);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+gchar *
+e_web_view_get_selection_content_text_sync (EWebView *web_view,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDBusProxy *web_extension;
+
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
+
+ web_extension = e_web_view_get_web_extension_proxy (web_view);
+ if (web_extension) {
+ GVariant *result;
+
+ result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_full (
+ web_extension,
+ "GetSelectionContentText",
+ g_variant_new (
+ "(t)",
+ webkit_web_view_get_page_id (
+ WEBKIT_WEB_VIEW (web_view))),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+
+ if (result) {
+ gchar *text_content = NULL;
+
+ g_variant_get (result, "(s)", &text_content);
+ g_variant_unref (result);
+ return text_content;
+ }
+ }
+
+ return NULL;
+}
+
const gchar *
e_web_view_get_citation_color_for_level (gint level)
{
diff --git a/src/e-util/e-web-view.h b/src/e-util/e-web-view.h
index fb1692ab53..474140dfb6 100644
--- a/src/e-util/e-web-view.h
+++ b/src/e-util/e-web-view.h
@@ -238,6 +238,19 @@ gchar * e_web_view_get_selection_content_html_sync
(EWebView *web_view,
GCancellable *cancellable,
GError **error);
+void e_web_view_get_selection_content_text
+ (EWebView *web_view,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gchar * e_web_view_get_selection_content_text_finish
+ (EWebView *web_view,
+ GAsyncResult *result,
+ GError **error);
+gchar * e_web_view_get_selection_content_text_sync
+ (EWebView *web_view,
+ GCancellable *cancellable,
+ GError **error);
void e_web_view_update_fonts (EWebView *web_view);
void e_web_view_cursor_image_copy (EWebView *web_view);
void e_web_view_cursor_image_save (EWebView *web_view);
diff --git a/src/e-util/widgets.error.xml b/src/e-util/widgets.error.xml
index 74fbd9f9a1..7e6b7c89d7 100644
--- a/src/e-util/widgets.error.xml
+++ b/src/e-util/widgets.error.xml
@@ -34,5 +34,10 @@
<secondary xml:space="preserve">{0}</secondary>
</error>
+ <error id="get-selected-text-failed" type="error">
+ <_primary>Could not get selected text.</_primary>
+ <secondary xml:space="preserve">{0}</secondary>
+ </error>
+
</error-list>
diff --git a/src/mail/e-mail-browser.c b/src/mail/e-mail-browser.c
index e476759f38..4dca830bdb 100644
--- a/src/mail/e-mail-browser.c
+++ b/src/mail/e-mail-browser.c
@@ -189,7 +189,11 @@ static EPopupActionEntry mail_browser_popup_entries[] = {
{ "popup-copy-clipboard",
NULL,
- "copy-clipboard" }
+ "copy-clipboard" },
+
+ { "popup-search-web",
+ NULL,
+ "search-web" }
};
static void
diff --git a/src/mail/e-mail-reader.c b/src/mail/e-mail-reader.c
index 363090127c..6992d2c306 100644
--- a/src/mail/e-mail-reader.c
+++ b/src/mail/e-mail-reader.c
@@ -2263,6 +2263,19 @@ action_mail_zoom_out_cb (GtkAction *action,
e_web_view_zoom_out (E_WEB_VIEW (display));
}
+static void
+action_mail_search_web_cb (GtkAction *action,
+ EMailReader *reader)
+{
+ EMailDisplay *display;
+ GtkAction *wv_action;
+
+ display = e_mail_reader_get_mail_display (reader);
+ wv_action = e_web_view_get_action (E_WEB_VIEW (display), "search-web");
+
+ gtk_action_activate (wv_action);
+}
+
static void
action_search_folder_recipient_cb (GtkAction *action,
EMailReader *reader)
@@ -2769,6 +2782,13 @@ static GtkActionEntry mail_reader_entries[] = {
N_("Save selected messages as an mbox file"),
G_CALLBACK (action_mail_save_as_cb) },
+ { "mail-search-web",
+ NULL,
+ N_("Search _Web…"),
+ NULL,
+ N_("Search the Web with the selected text"),
+ G_CALLBACK (action_mail_search_web_cb) },
+
{ "mail-show-source",
NULL,
N_("_Message Source"),
@@ -3030,6 +3050,10 @@ static EPopupActionEntry mail_reader_popup_entries[] = {
NULL,
"mail-save-as" },
+ { "mail-popup-search-web",
+ NULL,
+ "mail-search-web" },
+
{ "mail-popup-undelete",
NULL,
"mail-undelete" }
@@ -4263,6 +4287,7 @@ mail_reader_update_actions (EMailReader *reader,
GtkAction *action;
const gchar *action_name;
gboolean sensitive;
+ EMailDisplay *mail_display;
/* Be descriptive. */
gboolean any_messages_selected;
@@ -4331,6 +4356,8 @@ mail_reader_update_actions (EMailReader *reader,
any_messages_selected =
(single_message_selected || multiple_messages_selected);
+ mail_display = e_mail_reader_get_mail_display (reader);
+
if (any_messages_selected) {
MessageList *message_list;
gint row = -1, count = -1;
@@ -4703,6 +4730,10 @@ mail_reader_update_actions (EMailReader *reader,
action = e_mail_reader_get_action (reader, action_name);
gtk_action_set_sensitive (action, sensitive);
+ action = e_mail_reader_get_action (reader, "mail-search-web");
+ gtk_action_set_sensitive (action, single_message_selected &&
+ mail_display && e_web_view_is_selection_active (E_WEB_VIEW (mail_display)));
+
mail_reader_update_labels_menu (reader);
}
diff --git a/src/web-extensions/e-dom-utils.c b/src/web-extensions/e-dom-utils.c
index 30e94b025a..24e15dcb64 100644
--- a/src/web-extensions/e-dom-utils.c
+++ b/src/web-extensions/e-dom-utils.c
@@ -278,18 +278,14 @@ dom_selection_get_content_text (WebKitDOMDOMSelection *dom_selection)
return text;
}
-static gchar *
-get_frame_selection_content_text (WebKitDOMElement *iframe)
+gchar *
+e_dom_utils_get_selection_content_text (WebKitDOMDocument *content_document)
{
- WebKitDOMDocument *content_document;
WebKitDOMDOMWindow *dom_window = NULL;
WebKitDOMDOMSelection *dom_selection = NULL;
WebKitDOMHTMLCollection *frames = NULL;
gulong ii, length;
- content_document = webkit_dom_html_iframe_element_get_content_document (
- WEBKIT_DOM_HTML_IFRAME_ELEMENT (iframe));
-
if (!content_document)
return NULL;
@@ -298,8 +294,11 @@ get_frame_selection_content_text (WebKitDOMElement *iframe)
g_clear_object (&dom_window);
if (dom_selection && (webkit_dom_dom_selection_get_range_count (dom_selection) > 0)) {
gchar *text = dom_selection_get_content_text (dom_selection);
- g_clear_object (&dom_selection);
- return text;
+ if (text && *text) {
+ g_clear_object (&dom_selection);
+ return text;
+ }
+ g_free (text);
}
g_clear_object (&dom_selection);
@@ -311,41 +310,15 @@ get_frame_selection_content_text (WebKitDOMElement *iframe)
node = webkit_dom_html_collection_item (frames, ii);
- text = get_frame_selection_content_text (
- WEBKIT_DOM_ELEMENT (node));
+ text = e_dom_utils_get_selection_content_text (
+ webkit_dom_html_iframe_element_get_content_document (WEBKIT_DOM_HTML_IFRAME_ELEMENT
(node)));
- if (text != NULL) {
+ if (text && *text) {
g_clear_object (&frames);
return text;
}
- }
-
- g_clear_object (&frames);
- return NULL;
-}
-
-gchar *
-e_dom_utils_get_selection_content_text (WebKitDOMDocument *document)
-{
- WebKitDOMHTMLCollection *frames = NULL;
- gulong ii, length;
-
- frames = webkit_dom_document_get_elements_by_tag_name_as_html_collection (document, "iframe");
- length = webkit_dom_html_collection_get_length (frames);
-
- for (ii = 0; ii < length; ii++) {
- gchar *text;
- WebKitDOMNode *node;
-
- node = webkit_dom_html_collection_item (frames, ii);
-
- text = get_frame_selection_content_text (
- WEBKIT_DOM_ELEMENT (node));
- if (text != NULL) {
- g_clear_object (&frames);
- return text;
- }
+ g_free (text);
}
g_clear_object (&frames);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]