[evolution/wip/tpopela/composer-dnd: 5/6] Fix the replace dialog functionality
- From: Tomas Popela <tpopela src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/wip/tpopela/composer-dnd: 5/6] Fix the replace dialog functionality
- Date: Fri, 17 Mar 2017 14:58:25 +0000 (UTC)
commit 90ffd759eca2f1d3541a2d667a07ea23f6eb0fe2
Author: Tomas Popela <tpopela redhat com>
Date: Wed Mar 15 13:08:02 2017 +0100
Fix the replace dialog functionality
There were many problems with it:
* We have to use the sync call to the extension while replacing the
content as otherwise the active selection could be lost (the
WebKitFindController could jump to another occurrence) and the
replace could fail.
* We were sending messages to the extension even if the searched text
was not found.
* While performing the 'replace all' action wrong web extension
function was called (to replace the whole editor content) - we have
to call the e_content_editor_replace().
* The history was not saved at all for the 'replace all' action.
* Undoing the replace history event was wrong as it always expected,
that the replaced string was a word.
Add two new unit tests /replace/dialog and /replace-all/dialog.
src/e-util/test-html-editor-units.c | 44 ++++++++++++
src/modules/webkit-editor/e-webkit-editor.c | 71 +++++++++++++-------
.../web-extension/e-editor-dom-functions.c | 35 ++++++++--
.../web-extension/e-editor-dom-functions.h | 4 +
.../web-extension/e-editor-undo-redo-manager.c | 5 +-
.../web-extension/e-editor-web-extension.c | 16 +++++
6 files changed, 144 insertions(+), 31 deletions(-)
---
diff --git a/src/e-util/test-html-editor-units.c b/src/e-util/test-html-editor-units.c
index 2778855..af9c900 100644
--- a/src/e-util/test-html-editor-units.c
+++ b/src/e-util/test-html-editor-units.c
@@ -2659,6 +2659,48 @@ test_delete_after_quoted (TestFixture *fixture)
g_test_fail ();
}
+static void
+test_replace_dialog (TestFixture *fixture)
+{
+ if (!test_utils_run_simple_test (fixture,
+ "mode:plain\n"
+ "type:text to replace\n"
+ "undo:save\n" /* 1 */
+ "seq:h\n"
+ "action:show-replace\n"
+ "type:to\t2\n"
+ "type:\t\t\t\t\t\t\n" /* Jump to 'Replace' */
+ "seq:n\n" /* Press it */
+ "seq:^\n" /* Close the dialog */
+ "undo:undo\n"
+ "undo:test:1\n"
+ "undo:redo\n",
+ HTML_PREFIX "<div style=\"width: 71ch;\">text 2 replace</div>" HTML_SUFFIX,
+ "text 2 replace"))
+ g_test_fail ();
+}
+
+static void
+test_replace_dialog_all (TestFixture *fixture)
+{
+ if (!test_utils_run_simple_test (fixture,
+ "mode:plain\n"
+ "type:text to replace\n"
+ "undo:save\n" /* 1 */
+ "seq:h\n"
+ "action:show-replace\n"
+ "type:e\t3\n"
+ "type:\t\t\t\t\t\t\t\n" /* Jump to 'Replace All' */
+ "seq:n\n" /* Press it */
+ "seq:^\n" /* Close the dialog */
+ "undo:undo\n"
+ "undo:test:1\n"
+ "undo:redo\n",
+ HTML_PREFIX "<div style=\"width: 71ch;\">t3xt to r3plac3</div>" HTML_SUFFIX,
+ "t3xt to r3plac3"))
+ g_test_fail ();
+}
+
gint
main (gint argc,
gchar *argv[])
@@ -2826,6 +2868,8 @@ main (gint argc,
test_utils_add_test ("/undo/link-paste/plain", test_undo_link_paste_plain);
test_utils_add_test ("/delete/quoted", test_delete_quoted);
test_utils_add_test ("/delete/after-quoted", test_delete_after_quoted);
+ test_utils_add_test ("/replace/dialog", test_replace_dialog);
+ test_utils_add_test ("/replace-all/dialog", test_replace_dialog_all);
test_add_html_editor_bug_tests ();
diff --git a/src/modules/webkit-editor/e-webkit-editor.c b/src/modules/webkit-editor/e-webkit-editor.c
index 053fc88..91dd309 100644
--- a/src/modules/webkit-editor/e-webkit-editor.c
+++ b/src/modules/webkit-editor/e-webkit-editor.c
@@ -131,6 +131,7 @@ struct _EWebKitEditorPrivate {
gchar *replace_with;
gulong found_text_handler_id;
gulong failed_to_find_text_handler_id;
+ gboolean current_text_not_found;
gboolean performing_drag;
gulong drag_data_received_handler_id;
@@ -2474,7 +2475,7 @@ webkit_editor_replace_caret_word (EContentEditor *editor,
return;
}
- e_util_invoke_g_dbus_proxy_call_with_error_check (
+ e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
wk_editor->priv->web_extension,
"DOMReplaceCaretWord",
g_variant_new ("(ts)", current_page_id (wk_editor), replacement),
@@ -2527,10 +2528,31 @@ find_flags_to_webkit_find_options (guint32 flags /* EContentEditorFindFlags */)
}
static void
+webkit_editor_replace (EContentEditor *editor,
+ const gchar *replacement)
+{
+ EWebKitEditor *wk_editor;
+
+ wk_editor = E_WEBKIT_EDITOR (editor);
+ if (!wk_editor->priv->web_extension) {
+ g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
+ return;
+ }
+
+ e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
+ wk_editor->priv->web_extension,
+ "DOMSelectionReplace",
+ g_variant_new ("(ts)", current_page_id (wk_editor), replacement),
+ wk_editor->priv->cancellable);
+}
+
+static void
webkit_find_controller_found_text_cb (WebKitFindController *find_controller,
guint match_count,
EWebKitEditor *wk_editor)
{
+ wk_editor->priv->current_text_not_found = FALSE;
+
if (wk_editor->priv->performing_replace_all) {
if (!wk_editor->priv->replaced_count)
wk_editor->priv->replaced_count = match_count;
@@ -2538,10 +2560,7 @@ webkit_find_controller_found_text_cb (WebKitFindController *find_controller,
/* Repeatedly search for 'word', then replace selection by
* 'replacement'. Repeat until there's at least one occurrence of
* 'word' in the document */
- e_content_editor_insert_content (
- E_CONTENT_EDITOR (wk_editor),
- wk_editor->priv->replace_with,
- E_CONTENT_EDITOR_INSERT_TEXT_PLAIN);
+ webkit_editor_replace (E_CONTENT_EDITOR (wk_editor), wk_editor->priv->replace_with);
webkit_find_controller_search_next (find_controller);
} else {
@@ -2553,9 +2572,26 @@ static void
webkit_find_controller_failed_to_find_text_cb (WebKitFindController *find_controller,
EWebKitEditor *wk_editor)
{
+ wk_editor->priv->current_text_not_found = TRUE;
+
if (wk_editor->priv->performing_replace_all) {
guint replaced_count = wk_editor->priv->replaced_count;
+ if (replaced_count > 0) {
+ if (!wk_editor->priv->web_extension) {
+ g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
+ } else {
+ e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
+ wk_editor->priv->web_extension,
+ "DOMInsertReplaceAllHistoryEvent",
+ g_variant_new ("(tss)",
+ current_page_id (wk_editor),
+ webkit_find_controller_get_search_text (find_controller),
+ wk_editor->priv->replace_with),
+ NULL);
+ }
+ }
+
webkit_editor_finish_search (wk_editor);
e_content_editor_emit_replace_all_done (E_CONTENT_EDITOR (wk_editor), replaced_count);
} else {
@@ -2581,6 +2617,7 @@ webkit_editor_prepare_find_controller (EWebKitEditor *wk_editor)
wk_editor->priv->performing_replace_all = FALSE;
wk_editor->priv->replaced_count = 0;
+ wk_editor->priv->current_text_not_found = FALSE;
g_free (wk_editor->priv->replace_with);
wk_editor->priv->replace_with = NULL;
}
@@ -2619,25 +2656,6 @@ webkit_editor_find (EContentEditor *editor,
}
static void
-webkit_editor_replace (EContentEditor *editor,
- const gchar *replacement)
-{
- EWebKitEditor *wk_editor;
-
- wk_editor = E_WEBKIT_EDITOR (editor);
- if (!wk_editor->priv->web_extension) {
- g_warning ("EHTMLEditorWebExtension not ready at %s!", G_STRFUNC);
- return;
- }
-
- e_util_invoke_g_dbus_proxy_call_with_error_check (
- wk_editor->priv->web_extension,
- "DOMSelectionReplace",
- g_variant_new ("(ts)", current_page_id (wk_editor), replacement),
- wk_editor->priv->cancellable);
-}
-
-static void
webkit_editor_replace_all (EContentEditor *editor,
guint32 flags,
const gchar *find_text,
@@ -2653,6 +2671,11 @@ webkit_editor_replace_all (EContentEditor *editor,
wk_editor = E_WEBKIT_EDITOR (editor);
wk_options = find_flags_to_webkit_find_options (flags);
+ wk_options |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+
+ if (wk_editor->priv->current_text_not_found)
+ return;
+
if (!wk_editor->priv->find_controller)
webkit_editor_prepare_find_controller (wk_editor);
diff --git a/src/modules/webkit-editor/web-extension/e-editor-dom-functions.c
b/src/modules/webkit-editor/web-extension/e-editor-dom-functions.c
index bd8481c..4ec1a8d 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-dom-functions.c
+++ b/src/modules/webkit-editor/web-extension/e-editor-dom-functions.c
@@ -17341,6 +17341,28 @@ e_editor_dom_selection_set_alignment (EEditorPage *editor_page,
e_editor_page_emit_content_changed (editor_page);
}
+void
+e_editor_dom_insert_replace_all_history_event (EEditorPage *editor_page,
+ const gchar *search_text,
+ const gchar *replacement)
+{
+ EEditorUndoRedoManager *manager;
+
+ g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+ manager = e_editor_page_get_undo_redo_manager (editor_page);
+
+ if (!e_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ EEditorHistoryEvent *ev = g_new0 (EEditorHistoryEvent, 1);
+ ev->type = HISTORY_REPLACE_ALL;
+
+ ev->data.string.from = g_strdup (search_text);
+ ev->data.string.to = g_strdup (replacement);
+
+ e_editor_undo_redo_manager_insert_history_event (manager, ev);
+ }
+}
+
/*
* e_html_editor_selection_replace:
* @selection: an #EEditorSelection
@@ -17354,14 +17376,17 @@ e_editor_dom_selection_replace (EEditorPage *editor_page,
{
EEditorHistoryEvent *ev = NULL;
EEditorUndoRedoManager *manager;
+ WebKitDOMRange *range = NULL;
g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
manager = e_editor_page_get_undo_redo_manager (editor_page);
- if (!e_editor_undo_redo_manager_is_operation_in_progress (manager)) {
- WebKitDOMRange *range = NULL;
+ if (!(range = e_editor_dom_get_current_range (editor_page)) ||
+ e_editor_dom_selection_is_collapsed (editor_page))
+ return;
+ if (!e_editor_undo_redo_manager_is_operation_in_progress (manager)) {
ev = g_new0 (EEditorHistoryEvent, 1);
ev->type = HISTORY_REPLACE;
@@ -17371,14 +17396,12 @@ e_editor_dom_selection_replace (EEditorPage *editor_page,
&ev->before.end.x,
&ev->before.end.y);
- range = e_editor_dom_get_current_range (editor_page);
-
ev->data.string.from = webkit_dom_range_get_text (range);
ev->data.string.to = g_strdup (replacement);
-
- g_clear_object (&range);
}
+ g_clear_object (&range);
+
e_editor_dom_exec_command (editor_page, E_CONTENT_EDITOR_COMMAND_INSERT_TEXT, replacement);
if (ev) {
diff --git a/src/modules/webkit-editor/web-extension/e-editor-dom-functions.h
b/src/modules/webkit-editor/web-extension/e-editor-dom-functions.h
index 226cde1..04cb85f 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-dom-functions.h
+++ b/src/modules/webkit-editor/web-extension/e-editor-dom-functions.h
@@ -349,6 +349,10 @@ EContentEditorAlignment
void e_editor_dom_selection_set_alignment
(EEditorPage *editor_page,
EContentEditorAlignment alignment);
+void e_editor_dom_insert_replace_all_history_event
+ (EEditorPage *editor_page,
+ const gchar *search_text,
+ const gchar *replacement);
void e_editor_dom_selection_replace (EEditorPage *editor_page,
const gchar *replacement);
void e_editor_dom_replace_caret_word (EEditorPage *editor_page,
diff --git a/src/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c
b/src/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c
index 541ff49..2f4831a 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c
+++ b/src/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c
@@ -1625,6 +1625,7 @@ undo_redo_replace (EEditorPage *editor_page,
e_editor_dom_selection_restore_to_history_event_state (editor_page, undo ? event->after :
event->before);
if (undo) {
+ gint ii = 0;
WebKitDOMDOMWindow *dom_window = NULL;
WebKitDOMDOMSelection *dom_selection = NULL;
@@ -1632,7 +1633,9 @@ undo_redo_replace (EEditorPage *editor_page,
dom_selection = webkit_dom_dom_window_get_selection (dom_window);
g_clear_object (&dom_window);
- webkit_dom_dom_selection_modify (dom_selection, "extend", "left", "word");
+ for (ii = g_utf8_strlen (event->data.string.to, -1); ii--;)
+ webkit_dom_dom_selection_modify (dom_selection, "extend", "left", "character");
+
g_clear_object (&dom_selection);
}
diff --git a/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
b/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
index 8f27eee..d9477db 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
+++ b/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
@@ -501,6 +501,11 @@ static const gchar *introspection_xml =
" <arg type='t' name='page_id' direction='in'/>"
" <arg type='s' name='uri' direction='in'/>"
" </method>"
+" <method name='DOMInsertReplaceAllHistoryEvent'>"
+" <arg type='t' name='page_id' direction='in'/>"
+" <arg type='s' name='search_text' direction='in'/>"
+" <arg type='s' name='replacement' direction='in'/>"
+" </method>"
" <method name='DOMSelectionReplace'>"
" <arg type='t' name='page_id' direction='in'/>"
" <arg type='s' name='replacement' direction='in'/>"
@@ -1918,6 +1923,17 @@ handle_method_call (GDBusConnection *connection,
e_editor_dom_insert_image (editor_page, uri);
g_dbus_method_invocation_return_value (invocation, NULL);
+ } else if (g_strcmp0 (method_name, "DOMInsertReplaceAllHistoryEvent") == 0) {
+ const gchar *replacement, *search_text;
+
+ g_variant_get (parameters, "(t&s&s)", &page_id, &search_text, &replacement);
+
+ editor_page = get_editor_page_or_return_dbus_error (invocation, extension, page_id);
+ if (!editor_page)
+ goto error;
+
+ e_editor_dom_insert_replace_all_history_event (editor_page, search_text, replacement);
+ g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "DOMSelectionReplace") == 0) {
const gchar *replacement;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]