[evolution] EMsgComposer - Move the signature handling to EHTMLEditorView
- From: Tomas Popela <tpopela src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] EMsgComposer - Move the signature handling to EHTMLEditorView
- Date: Fri, 29 Apr 2016 10:58:15 +0000 (UTC)
commit 7db8261ec9852e2e8136df36964bb349125bfb97
Author: Tomas Popela <tpopela redhat com>
Date: Fri Apr 29 12:48:21 2016 +0200
EMsgComposer - Move the signature handling to EHTMLEditorView
No change in functionality, just a preparation for WebKit2 port.
composer/e-composer-private.c | 503 ++---------------------------------------
composer/e-composer-private.h | 1 -
composer/e-msg-composer.c | 9 -
composer/e-msg-composer.h | 3 -
e-util/e-html-editor-view.c | 485 ++++++++++++++++++++++++++++++++++++++--
e-util/e-html-editor-view.h | 13 +
mail/em-composer-utils.c | 8 +-
7 files changed, 508 insertions(+), 514 deletions(-)
---
diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c
index 33fb951..3a83fb5 100644
--- a/composer/e-composer-private.c
+++ b/composer/e-composer-private.c
@@ -130,7 +130,6 @@ e_composer_private_constructed (EMsgComposer *composer)
priv->charset = e_composer_get_default_charset ();
- priv->is_from_new_message = FALSE;
priv->set_signature_from_message = FALSE;
priv->disable_signature = FALSE;
priv->busy = FALSE;
@@ -769,282 +768,17 @@ e_composer_selection_is_image_uris (EMsgComposer *composer,
return all_image_uris;
}
-static gboolean
-add_signature_delimiter (EMsgComposer *composer)
-{
- GSettings *settings;
- gboolean signature_delim;
-
- /* FIXME This should be an EMsgComposer property. */
- settings = e_util_ref_settings ("org.gnome.evolution.mail");
- signature_delim = !g_settings_get_boolean (
- settings, "composer-no-signature-delim");
- g_object_unref (settings);
-
- return signature_delim;
-}
-
-static gboolean
-use_top_signature (EMsgComposer *composer)
-{
- GSettings *settings;
- gboolean top_signature;
-
- /* FIXME This should be an EMsgComposer property. */
- settings = e_util_ref_settings ("org.gnome.evolution.mail");
- top_signature = g_settings_get_boolean (
- settings, "composer-top-signature");
- g_object_unref (settings);
-
- return top_signature;
-}
-
-static WebKitDOMElement *
-prepare_paragraph (EHTMLEditorSelection *selection,
- WebKitDOMDocument *document)
-{
- WebKitDOMElement *br, *paragraph;
-
- paragraph = e_html_editor_selection_get_paragraph_element (
- selection, document, -1, 0);
- webkit_dom_element_set_id (paragraph, "-x-evo-input-start");
- br = webkit_dom_document_create_element (document, "BR", NULL);
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (paragraph), WEBKIT_DOM_NODE (br), NULL);
-
- return paragraph;
-}
-
-static WebKitDOMElement *
-prepare_top_signature_spacer (EHTMLEditorSelection *selection,
- WebKitDOMDocument *document)
-{
- WebKitDOMElement *element;
-
- element = prepare_paragraph (selection, document);
- webkit_dom_element_remove_attribute (element, "id");
- element_add_class (element, "-x-evo-top-signature-spacer");
-
- return element;
-}
-
-static void
-composer_move_caret (EMsgComposer *composer)
-{
- EHTMLEditor *editor;
- EHTMLEditorView *view;
- EHTMLEditorSelection *editor_selection;
- GSettings *settings;
- gboolean start_bottom, top_signature;
- gboolean is_message_from_draft;
- gboolean is_message_from_edit_as_new;
- gboolean has_paragraphs_in_body = TRUE;
- WebKitDOMDocument *document;
- WebKitDOMElement *element, *signature;
- WebKitDOMHTMLElement *body;
- WebKitDOMNodeList *list;
-
- /* When there is an option composer-reply-start-bottom set we have
- * to move the caret between reply and signature. */
- settings = e_util_ref_settings ("org.gnome.evolution.mail");
- start_bottom = g_settings_get_boolean (settings, "composer-reply-start-bottom");
- g_object_unref (settings);
-
- editor = e_msg_composer_get_editor (composer);
- view = e_html_editor_get_view (editor);
- editor_selection = e_html_editor_view_get_selection (view);
- is_message_from_draft = e_html_editor_view_is_message_from_draft (view);
- is_message_from_edit_as_new =
- e_html_editor_view_is_message_from_edit_as_new (view);
-
- top_signature =
- use_top_signature (composer) &&
- !is_message_from_edit_as_new &&
- !composer->priv->is_from_new_message;
-
- document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
-
- body = webkit_dom_document_get_body (document);
- webkit_dom_element_set_attribute (
- WEBKIT_DOM_ELEMENT (body), "data-message", "", NULL);
-
- /* If editing message as new don't handle with caret */
- if (is_message_from_edit_as_new || is_message_from_draft) {
- if (is_message_from_edit_as_new)
- webkit_dom_element_set_attribute (
- WEBKIT_DOM_ELEMENT (body),
- "data-edit-as-new",
- "",
- NULL);
-
- if (is_message_from_edit_as_new && !is_message_from_draft) {
- element = WEBKIT_DOM_ELEMENT (body);
- e_html_editor_selection_block_selection_changed (editor_selection);
- goto move_caret;
- } else
- e_html_editor_selection_scroll_to_caret (editor_selection);
-
- return;
- }
-
- e_html_editor_selection_block_selection_changed (editor_selection);
-
- /* When the new message is written from the beginning - note it into body */
- if (composer->priv->is_from_new_message)
- webkit_dom_element_set_attribute (
- WEBKIT_DOM_ELEMENT (body), "data-new-message", "", NULL);
-
- list = webkit_dom_document_get_elements_by_class_name (document, "-x-evo-paragraph");
- signature = webkit_dom_document_query_selector (document, ".-x-evo-signature-wrapper", NULL);
- /* Situation when wrapped paragraph is just in signature and not in message body */
- if (webkit_dom_node_list_get_length (list) == 1)
- if (signature && webkit_dom_element_query_selector (signature, ".-x-evo-paragraph", NULL))
- has_paragraphs_in_body = FALSE;
-
- /*
- *
- * Keeping Signatures in the beginning of composer
- * ------------------------------------------------
- *
- * Purists are gonna blast me for this.
- * But there are so many people (read Outlook users) who want this.
- * And Evo is an exchange-client, Outlook-replacement etc.
- * So Here it goes :(
- *
- * -- Sankar
- *
- */
- if (signature && top_signature) {
- WebKitDOMElement *spacer;
-
- spacer = prepare_top_signature_spacer (editor_selection, document);
- webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (body),
- WEBKIT_DOM_NODE (spacer),
- webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (signature)),
- NULL);
- }
-
- if (webkit_dom_node_list_get_length (list) == 0)
- has_paragraphs_in_body = FALSE;
-
- element = webkit_dom_document_get_element_by_id (document, "-x-evo-input-start");
- if (!signature) {
- if (start_bottom) {
- if (!element) {
- element = prepare_paragraph (editor_selection, document);
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (body),
- WEBKIT_DOM_NODE (element),
- NULL);
- }
- } else
- element = WEBKIT_DOM_ELEMENT (body);
-
- g_object_unref (list);
- goto move_caret;
- }
-
- if (!has_paragraphs_in_body) {
- element = prepare_paragraph (editor_selection, document);
- if (top_signature) {
- if (start_bottom) {
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (body),
- WEBKIT_DOM_NODE (element),
- NULL);
- } else {
- webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (body),
- WEBKIT_DOM_NODE (element),
- WEBKIT_DOM_NODE (signature),
- NULL);
- }
- } else {
- if (start_bottom)
- webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (body),
- WEBKIT_DOM_NODE (element),
- WEBKIT_DOM_NODE (signature),
- NULL);
- else
- element = WEBKIT_DOM_ELEMENT (body);
- }
- } else {
- if (!element && top_signature) {
- element = prepare_paragraph (editor_selection, document);
- if (start_bottom) {
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (body),
- WEBKIT_DOM_NODE (element),
- NULL);
- } else {
- webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (body),
- WEBKIT_DOM_NODE (element),
- WEBKIT_DOM_NODE (signature),
- NULL);
- }
- } else if (element && top_signature && !start_bottom) {
- webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (body),
- WEBKIT_DOM_NODE (element),
- WEBKIT_DOM_NODE (signature),
- NULL);
- } else if (element && start_bottom) {
- /* Leave it how it is */
- } else
- element = WEBKIT_DOM_ELEMENT (body);
- }
-
- g_object_unref (list);
- move_caret:
- if (element) {
- WebKitDOMDOMSelection *dom_selection;
- WebKitDOMDOMWindow *dom_window;
- WebKitDOMRange *range;
-
- dom_window = webkit_dom_document_get_default_view (document);
- dom_selection = webkit_dom_dom_window_get_selection (dom_window);
- range = webkit_dom_document_create_range (document);
- webkit_dom_range_select_node_contents (
- range, WEBKIT_DOM_NODE (element), NULL);
- webkit_dom_range_collapse (range, TRUE, NULL);
- webkit_dom_dom_selection_remove_all_ranges (dom_selection);
- webkit_dom_dom_selection_add_range (dom_selection, range);
-
- g_clear_object (&dom_selection);
- g_clear_object (&dom_window);
- g_clear_object (&range);
- }
-
- if (start_bottom)
- e_html_editor_selection_scroll_to_caret (editor_selection);
-
- e_html_editor_view_force_spell_check_in_viewport (view);
-
- e_html_editor_selection_unblock_selection_changed (editor_selection);
-}
-
static void
composer_load_signature_cb (EMailSignatureComboBox *combo_box,
GAsyncResult *result,
EMsgComposer *composer)
{
- gchar *contents = NULL;
+ gchar *contents = NULL, *new_signature_id;
gsize length = 0;
- gboolean top_signature, is_html, html_mode, is_message_from_edit_as_new;
+ gboolean is_html;
GError *error = NULL;
- gulong list_length, ii;
EHTMLEditor *editor;
EHTMLEditorView *view;
- WebKitDOMDocument *document;
- WebKitDOMElement *signature_to_insert;
- WebKitDOMElement *insert_signature_in = NULL;
- WebKitDOMElement *signature_wrapper;
- WebKitDOMElement *element, *converted_signature = NULL;
- WebKitDOMHTMLElement *body;
- WebKitDOMNodeList *signatures;
e_mail_signature_combo_box_load_selected_finish (
combo_box, result, &contents, &length, &is_html, &error);
@@ -1053,236 +787,33 @@ composer_load_signature_cb (EMailSignatureComboBox *combo_box,
if (error != NULL) {
g_warning ("%s: %s", G_STRFUNC, error->message);
g_error_free (error);
- goto exit;
+ g_object_unref (composer);
+ return;
}
if (composer->priv->ignore_next_signature_change) {
composer->priv->ignore_next_signature_change = FALSE;
- goto exit;
+ g_object_unref (composer);
+ return;
}
editor = e_msg_composer_get_editor (composer);
view = e_html_editor_get_view (editor);
- is_message_from_edit_as_new =
- e_html_editor_view_is_message_from_edit_as_new (view);
-
- /* "Edit as New Message" sets is_message_from_edit_as_new.
- * Always put the signature at the bottom for that case. */
- top_signature =
- use_top_signature (composer) &&
- !is_message_from_edit_as_new &&
- !composer->priv->is_from_new_message;
-
- /* Create the DOM signature that is the same across all types of signatures. */
- document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
- signature_to_insert = webkit_dom_document_create_element (document, "span", NULL);
- webkit_dom_element_set_class_name (signature_to_insert, "-x-evo-signature");
- /* The combo box active ID is the signature's ESource UID. */
- webkit_dom_element_set_id (
- signature_to_insert, gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box)));
- insert_signature_in = signature_to_insert;
-
- html_mode = e_html_editor_view_get_html_mode (view);
-
- /* The signature has no content usually it means it is set to None. */
- if (!contents)
- goto insert;
-
- if (!is_html) {
- gchar *html;
-
- html = camel_text_to_html (contents, 0, 0);
- if (html) {
- g_free (contents);
-
- contents = html;
- length = strlen (contents);
- }
- insert_signature_in = webkit_dom_document_create_element (document, "pre", NULL);
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (signature_to_insert),
- WEBKIT_DOM_NODE (insert_signature_in),
- NULL);
- }
-
- /* If inserting HTML signature in plain text composer we have to convert it. */
- if (is_html && !html_mode && !strstr (contents, "data-evo-signature-plain-text-mode")) {
- gchar *inner_text;
-
- /* Save the converted signature to avoid parsing it later again
- * while inserting it into the view. */
- converted_signature = webkit_dom_document_create_element (document, "pre", NULL);
- webkit_dom_html_element_set_inner_html (
- WEBKIT_DOM_HTML_ELEMENT (converted_signature), contents, NULL);
- e_html_editor_view_convert_element_from_html_to_plain_text (view, converted_signature);
- inner_text = webkit_dom_html_element_get_inner_text (WEBKIT_DOM_HTML_ELEMENT
(converted_signature));
-
- g_free (contents);
- contents = inner_text ? g_strstrip (inner_text) : g_strdup ("");
- /* because of the -- \n check */
- is_html = FALSE;
- }
+ new_signature_id = e_html_editor_view_insert_signature (
+ view,
+ contents,
+ is_html,
+ gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box)),
+ &composer->priv->set_signature_from_message,
+ &composer->priv->check_if_signature_is_changed,
+ &composer->priv->ignore_next_signature_change);
- /* The signature dash convention ("-- \n") is specified
- * in the "Son of RFC 1036", section 4.3.2.
- * http://www.chemie.fu-berlin.de/outerspace/netnews/son-of-1036.html
- */
- if (add_signature_delimiter (composer)) {
- const gchar *delim;
- const gchar *delim_nl;
-
- if (is_html) {
- delim = "-- <BR>";
- delim_nl = "\n-- <BR>";
- } else {
- delim = "-- \n";
- delim_nl = "\n-- \n";
- }
-
- /* Skip the delimiter if the signature already has one. */
- if (g_ascii_strncasecmp (contents, delim, strlen (delim)) == 0)
- ; /* skip */
- else if (e_util_strstrcase (contents, delim_nl) != NULL)
- ; /* skip */
- else
- webkit_dom_html_element_set_inner_html (
- WEBKIT_DOM_HTML_ELEMENT (insert_signature_in), delim, NULL);
- }
+ if (new_signature_id && *new_signature_id)
+ gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), new_signature_id);
- if (converted_signature) {
- WebKitDOMNode *node;
-
- while ((node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (converted_signature))))
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (insert_signature_in), node, NULL);
- remove_node (WEBKIT_DOM_NODE (converted_signature));
- } else
- webkit_dom_html_element_insert_adjacent_html (
- WEBKIT_DOM_HTML_ELEMENT (insert_signature_in), "beforeend", contents, NULL);
-
- element = webkit_dom_element_query_selector (
- insert_signature_in, "[data-evo-signature-plain-text-mode]", NULL);
- if (element)
- webkit_dom_element_remove_attribute (
- element, "data-evo-signature-plain-text-mode");
+ g_free (new_signature_id);
g_free (contents);
-
-insert:
- /* Remove the old signature and insert the new one. */
- signatures = webkit_dom_document_get_elements_by_class_name (
- document, "-x-evo-signature-wrapper");
- list_length = webkit_dom_node_list_get_length (signatures);
- for (ii = 0; ii < list_length; ii++) {
- WebKitDOMNode *wrapper, *signature;
-
- wrapper = webkit_dom_node_list_item (signatures, ii);
- signature = webkit_dom_node_get_first_child (wrapper);
-
- /* Old messages will have the signature id in the name attribute, correct it. */
- dom_element_rename_attribute (WEBKIT_DOM_ELEMENT (signature), "name", "id");
-
- /* When we are editing a message with signature, we need to unset the
- * active signature id as if the signature in the message was edited
- * by the user we would discard these changes. */
- if (composer->priv->set_signature_from_message &&
- (is_message_from_edit_as_new || e_html_editor_view_is_message_from_draft (view))) {
- if (composer->priv->check_if_signature_is_changed) {
- /* Normalize the signature that we want to insert as the one in the
- * message already is normalized. */
- webkit_dom_node_normalize (WEBKIT_DOM_NODE (signature_to_insert));
- if (!webkit_dom_node_is_equal_node (WEBKIT_DOM_NODE (signature_to_insert),
signature)) {
- /* Signature in the body is different than the one with the
- * same id, so set the active signature to None and leave
- * the signature that is in the body. */
- gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), "none");
- composer->priv->ignore_next_signature_change = TRUE;
- }
-
- composer->priv->check_if_signature_is_changed = FALSE;
- composer->priv->set_signature_from_message = FALSE;
- } else {
- gchar *id;
-
- /* Load the signature and check if is it the same
- * as the signature in body or the user previously
- * changed it. */
- id = webkit_dom_element_get_id (WEBKIT_DOM_ELEMENT (signature));
- gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), id);
- g_free (id);
-
- composer->priv->check_if_signature_is_changed = TRUE;
- }
- g_object_unref (wrapper);
- g_object_unref (signatures);
- g_object_unref (composer);
-
- return;
- }
-
- /* If the top signature was set we have to remove the newline
- * that was inserted after it */
- if (top_signature) {
- WebKitDOMElement *spacer;
-
- spacer = webkit_dom_document_query_selector (
- document, ".-x-evo-top-signature-spacer", NULL);
- if (spacer)
- remove_node_if_empty (WEBKIT_DOM_NODE (spacer));
- }
- /* We have to remove the div containing the span with signature */
- remove_node (wrapper);
- g_object_unref (wrapper);
- }
- g_object_unref (signatures);
-
- body = webkit_dom_document_get_body (document);
- signature_wrapper = webkit_dom_document_create_element (document, "div", NULL);
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (signature_wrapper),
- WEBKIT_DOM_NODE (signature_to_insert),
- NULL);
- webkit_dom_element_set_class_name (signature_wrapper, "-x-evo-signature-wrapper");
-
- if (top_signature) {
- GSettings *settings;
- WebKitDOMNode *child;
-
- child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body));
-
- settings = e_util_ref_settings ("org.gnome.evolution.mail");
- if (g_settings_get_boolean (settings, "composer-reply-start-bottom")) {
- webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (body),
- WEBKIT_DOM_NODE (signature_wrapper),
- child,
- NULL);
- } else {
- /* When we are using signature on top the caret
- * should be before the signature */
- webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (body),
- WEBKIT_DOM_NODE (signature_wrapper),
- child,
- NULL);
- }
- g_object_unref (settings);
- } else {
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (body),
- WEBKIT_DOM_NODE (signature_wrapper),
- NULL);
- }
-
- if (is_html && html_mode)
- e_html_editor_view_fix_file_uri_images (view);
-
- composer_move_caret (composer);
-
- exit:
- /* Make sure the flag will be unset and won't influence user's choice */
- composer->priv->set_signature_from_message = FALSE;
-
g_object_unref (composer);
}
diff --git a/composer/e-composer-private.h b/composer/e-composer-private.h
index bf9a1ef..4672e55 100644
--- a/composer/e-composer-private.h
+++ b/composer/e-composer-private.h
@@ -95,7 +95,6 @@ struct _EMsgComposerPrivate {
gboolean busy;
gboolean disable_signature;
gboolean is_from_draft;
- gboolean is_from_new_message;
/* The web view is uneditable while the editor is busy.
* This is used to restore the previous editable state. */
gboolean saved_editable;
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index f8ec954..2f5fcfa 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -5755,15 +5755,6 @@ e_save_spell_languages (const GList *spell_dicts)
}
void
-e_msg_composer_is_from_new_message (EMsgComposer *composer,
- gboolean is_from_new_message)
-{
- g_return_if_fail (composer != NULL);
-
- composer->priv->is_from_new_message = is_from_new_message;
-}
-
-void
e_msg_composer_save_focused_widget (EMsgComposer *composer)
{
GtkWidget *widget;
diff --git a/composer/e-msg-composer.h b/composer/e-msg-composer.h
index cf055d6..daaca2b 100644
--- a/composer/e-msg-composer.h
+++ b/composer/e-msg-composer.h
@@ -193,9 +193,6 @@ GByteArray * e_msg_composer_get_raw_message_text
gboolean e_msg_composer_is_exiting (EMsgComposer *composer);
void e_save_spell_languages (const GList *spell_languages);
-void e_msg_composer_is_from_new_message
- (EMsgComposer *composer,
- gboolean is_from_new_message);
void e_msg_composer_save_focused_widget
(EMsgComposer *composer);
void e_msg_composer_restore_focus_on_composer
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index 1decac6..ac97beb 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -101,6 +101,7 @@ struct _EHTMLEditorViewPrivate {
gboolean is_editting_message;
gboolean is_message_from_draft;
gboolean is_message_from_edit_as_new;
+ gboolean is_new_message;
gboolean is_message_from_selection;
gboolean return_key_pressed;
gboolean space_key_pressed;
@@ -8159,6 +8160,24 @@ register_html_events_handlers (EHTMLEditorView *view,
view);
}
+static gboolean
+add_signature_delimiter (EHTMLEditorView *view)
+{
+ return !g_settings_get_boolean (view->priv->mail_settings, "composer-no-signature-delim");
+}
+
+static gboolean
+use_top_signature (EHTMLEditorView *view)
+{
+ return g_settings_get_boolean (view->priv->mail_settings, "composer-top-signature");
+}
+
+static gboolean
+start_typing_at_bottom (EHTMLEditorView *view)
+{
+ return g_settings_get_boolean (view->priv->mail_settings, "composer-reply-start-bottom");
+}
+
static void
html_editor_convert_view_content (EHTMLEditorView *view,
const gchar *preferred_text)
@@ -8167,7 +8186,6 @@ html_editor_convert_view_content (EHTMLEditorView *view,
gboolean start_bottom, empty = FALSE;
gchar *inner_html;
gint ii, length;
- GSettings *settings;
WebKitDOMDocument *document;
WebKitDOMDOMWindow *dom_window;
WebKitDOMElement *paragraph, *content_wrapper, *top_signature;
@@ -8176,9 +8194,7 @@ html_editor_convert_view_content (EHTMLEditorView *view,
WebKitDOMNodeList *list;
WebKitDOMNode *node;
- settings = e_util_ref_settings ("org.gnome.evolution.mail");
- start_bottom = g_settings_get_boolean (settings, "composer-reply-start-bottom");
- g_object_unref (settings);
+ start_bottom = start_typing_at_bottom (view);
document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
dom_window = webkit_dom_document_get_default_view (document);
@@ -10462,8 +10478,7 @@ static gchar *
process_content_for_plain_text (EHTMLEditorView *view)
{
EHTMLEditorSelection *selection;
- gboolean wrap = FALSE, quote = FALSE, clean = FALSE;
- gboolean converted, is_from_new_message;
+ gboolean wrap = FALSE, quote = FALSE, clean = FALSE, converted;
gint length, ii;
GString *plain_text;
WebKitDOMDocument *document;
@@ -10476,8 +10491,6 @@ process_content_for_plain_text (EHTMLEditorView *view)
body = WEBKIT_DOM_NODE (webkit_dom_document_get_body (document));
converted = webkit_dom_element_has_attribute (
WEBKIT_DOM_ELEMENT (body), "data-converted");
- is_from_new_message = webkit_dom_element_has_attribute (
- WEBKIT_DOM_ELEMENT (body), "data-new-message");
source = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (body), TRUE);
selection = e_html_editor_view_get_selection (view);
@@ -10486,7 +10499,7 @@ process_content_for_plain_text (EHTMLEditorView *view)
/* If composer is in HTML mode we have to move the content to plain version */
if (view->priv->html_mode) {
- if (converted || is_from_new_message) {
+ if (converted || view->priv->is_new_message) {
toggle_paragraphs_style_in_element (
view, WEBKIT_DOM_ELEMENT (source), FALSE);
remove_images_in_element (
@@ -11264,7 +11277,7 @@ e_html_editor_view_set_html_mode (EHTMLEditorView *view,
gboolean html_mode)
{
EHTMLEditorSelection *selection;
- gboolean is_from_new_message, converted, edit_as_new, message, convert;
+ gboolean is_new_message, converted, edit_as_new, message, convert;
gboolean reply, hide;
WebKitDOMElement *blockquote;
WebKitDOMHTMLElement *body;
@@ -11277,8 +11290,7 @@ e_html_editor_view_set_html_mode (EHTMLEditorView *view,
document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
body = webkit_dom_document_get_body (document);
- is_from_new_message = webkit_dom_element_has_attribute (
- WEBKIT_DOM_ELEMENT (body), "data-new-message");
+ is_new_message = view->priv->is_new_message;
converted = webkit_dom_element_has_attribute (
WEBKIT_DOM_ELEMENT (body), "data-converted");
edit_as_new = webkit_dom_element_has_attribute (
@@ -11286,11 +11298,11 @@ e_html_editor_view_set_html_mode (EHTMLEditorView *view,
message = webkit_dom_element_has_attribute (
WEBKIT_DOM_ELEMENT (body), "data-message");
- reply = !is_from_new_message && !edit_as_new && message;
+ reply = !is_new_message && !edit_as_new && message;
hide = !reply && !converted;
convert = message && ((!hide && reply && !converted) || (edit_as_new && !converted));
- convert = convert && !is_from_new_message;
+ convert = convert && !is_new_message;
/* If toggling from HTML to plain text mode, ask user first */
if (convert && view->priv->html_mode && !html_mode) {
@@ -11671,6 +11683,7 @@ e_html_editor_view_init (EHTMLEditorView *view)
view->priv->is_message_from_draft = FALSE;
view->priv->is_message_from_selection = FALSE;
view->priv->is_message_from_edit_as_new = FALSE;
+ view->priv->is_new_message = FALSE;
view->priv->convert_in_situ = FALSE;
view->priv->return_key_pressed = FALSE;
view->priv->space_key_pressed = FALSE;
@@ -12919,6 +12932,23 @@ e_html_editor_view_set_is_message_from_edit_as_new (EHTMLEditorView *view,
view->priv->is_message_from_edit_as_new = value;
}
+gboolean
+e_html_editor_view_content_is_new_message (EHTMLEditorView *view)
+{
+ g_return_val_if_fail (E_IS_HTML_EDITOR_VIEW (view), FALSE);
+
+ return view->priv->is_new_message;
+}
+
+void
+e_html_editor_view_set_content_is_new_message (EHTMLEditorView *view,
+ gboolean value)
+{
+ g_return_if_fail (E_IS_HTML_EDITOR_VIEW (view));
+
+ view->priv->is_new_message = value;
+}
+
void
e_html_editor_view_set_is_editting_message (EHTMLEditorView *view,
gboolean value)
@@ -15245,3 +15275,430 @@ e_html_editor_view_register_input_event_listener_on_body (EHTMLEditorView *view)
view->priv->body_input_event_removed = FALSE;
}
}
+
+static WebKitDOMElement *
+prepare_top_signature_spacer (EHTMLEditorSelection *selection,
+ WebKitDOMDocument *document)
+{
+ WebKitDOMElement *element;
+
+ element = prepare_paragraph (selection, document, FALSE);
+ webkit_dom_element_remove_attribute (element, "id");
+ element_add_class (element, "-x-evo-top-signature-spacer");
+
+ return element;
+}
+
+static void
+move_caret_after_signature_inserted (EHTMLEditorView *view)
+{
+ EHTMLEditorSelection *selection;
+ gboolean start_bottom, top_signature;
+ gboolean has_paragraphs_in_body = TRUE;
+ WebKitDOMDocument *document;
+ WebKitDOMElement *element, *signature;
+ WebKitDOMHTMLElement *body;
+ WebKitDOMNodeList *list;
+
+ /* When there is an option composer-reply-start-bottom set we have
+ * to move the caret between reply and signature. */
+ start_bottom = start_typing_at_bottom (view);
+ selection = e_html_editor_view_get_selection (view);
+
+ top_signature =
+ use_top_signature (view) &&
+ !view->priv->is_message_from_edit_as_new &&
+ !view->priv->is_new_message;
+
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+
+ body = webkit_dom_document_get_body (document);
+ webkit_dom_element_set_attribute (
+ WEBKIT_DOM_ELEMENT (body), "data-message", "", NULL);
+
+ /* If editing message as new don't handle with caret */
+ if (view->priv->is_message_from_edit_as_new || view->priv->is_message_from_draft) {
+ if (view->priv->is_message_from_edit_as_new)
+ webkit_dom_element_set_attribute (
+ WEBKIT_DOM_ELEMENT (body),
+ "data-edit-as-new",
+ "",
+ NULL);
+
+ if (view->priv->is_message_from_edit_as_new && !view->priv->is_message_from_draft) {
+ element = WEBKIT_DOM_ELEMENT (body);
+ e_html_editor_selection_block_selection_changed (selection);
+ goto move_caret;
+ } else
+ e_html_editor_selection_scroll_to_caret (selection);
+
+ return;
+ }
+
+ e_html_editor_selection_block_selection_changed (selection);
+
+ list = webkit_dom_document_get_elements_by_class_name (document, "-x-evo-paragraph");
+ signature = webkit_dom_document_query_selector (document, ".-x-evo-signature-wrapper", NULL);
+ /* Situation when wrapped paragraph is just in signature and not in message body */
+ if (webkit_dom_node_list_get_length (list) == 1)
+ if (signature && webkit_dom_element_query_selector (signature, ".-x-evo-paragraph", NULL))
+ has_paragraphs_in_body = FALSE;
+
+ /*
+ *
+ * Keeping Signatures in the beginning of composer
+ * ------------------------------------------------
+ *
+ * Purists are gonna blast me for this.
+ * But there are so many people (read Outlook users) who want this.
+ * And Evo is an exchange-client, Outlook-replacement etc.
+ * So Here it goes :(
+ *
+ * -- Sankar
+ *
+ */
+ if (signature && top_signature) {
+ WebKitDOMElement *spacer;
+
+ spacer = prepare_top_signature_spacer (selection, document);
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (spacer),
+ webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (signature)),
+ NULL);
+ }
+
+ if (webkit_dom_node_list_get_length (list) == 0)
+ has_paragraphs_in_body = FALSE;
+
+ element = webkit_dom_document_get_element_by_id (document, "-x-evo-input-start");
+ if (!signature) {
+ if (start_bottom) {
+ if (!element) {
+ element = prepare_paragraph (selection, document, FALSE);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ }
+ } else
+ element = WEBKIT_DOM_ELEMENT (body);
+
+ g_object_unref (list);
+ goto move_caret;
+ }
+
+ if (!has_paragraphs_in_body) {
+ element = prepare_paragraph (selection, document, FALSE);
+ if (top_signature) {
+ if (start_bottom) {
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ } else {
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ WEBKIT_DOM_NODE (signature),
+ NULL);
+ }
+ } else {
+ if (start_bottom)
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ WEBKIT_DOM_NODE (signature),
+ NULL);
+ else
+ element = WEBKIT_DOM_ELEMENT (body);
+ }
+ } else {
+ if (!element && top_signature) {
+ element = prepare_paragraph (selection, document, FALSE);
+ if (start_bottom) {
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ } else {
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ WEBKIT_DOM_NODE (signature),
+ NULL);
+ }
+ } else if (element && top_signature && !start_bottom) {
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ WEBKIT_DOM_NODE (signature),
+ NULL);
+ } else if (element && start_bottom) {
+ /* Leave it how it is */
+ } else
+ element = WEBKIT_DOM_ELEMENT (body);
+ }
+
+ g_object_unref (list);
+
+ move_caret:
+ if (element) {
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMRange *range;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+ range = webkit_dom_document_create_range (document);
+ webkit_dom_range_select_node_contents (
+ range, WEBKIT_DOM_NODE (element), NULL);
+ webkit_dom_range_collapse (range, TRUE, NULL);
+ webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+ webkit_dom_dom_selection_add_range (dom_selection, range);
+
+ g_clear_object (&dom_selection);
+ g_clear_object (&dom_window);
+ g_clear_object (&range);
+ }
+
+ if (start_bottom)
+ e_html_editor_selection_scroll_to_caret (selection);
+
+ e_html_editor_view_force_spell_check_in_viewport (view);
+
+ e_html_editor_selection_unblock_selection_changed (selection);
+}
+
+gchar *
+e_html_editor_view_insert_signature (EHTMLEditorView *view,
+ const gchar *content,
+ gboolean is_html,
+ const gchar *id,
+ gboolean *set_signature_from_message,
+ gboolean *check_if_signature_is_changed,
+ gboolean *ignore_next_signature_change)
+{
+ gchar *new_signature_id = NULL;
+ gchar *signature_text = NULL;
+ gboolean top_signature;
+ gulong list_length, ii;
+ WebKitDOMDocument *document;
+ WebKitDOMElement *signature_to_insert;
+ WebKitDOMElement *insert_signature_in = NULL;
+ WebKitDOMElement *signature_wrapper;
+ WebKitDOMElement *element, *converted_signature = NULL;
+ WebKitDOMHTMLElement *body;
+ WebKitDOMNodeList *signatures;
+
+ g_return_val_if_fail (E_IS_HTML_EDITOR_VIEW (view), NULL);
+ g_return_val_if_fail (set_signature_from_message != NULL, NULL);
+ g_return_val_if_fail (check_if_signature_is_changed != NULL, NULL);
+ g_return_val_if_fail (ignore_next_signature_change != NULL, NULL);
+
+ /* "Edit as New Message" sets is_message_from_edit_as_new.
+ * Always put the signature at the bottom for that case. */
+ top_signature =
+ use_top_signature (view) &&
+ !view->priv->is_message_from_edit_as_new &&
+ !view->priv->is_new_message;
+
+ /* Create the DOM signature that is the same across all types of signatures. */
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+ signature_to_insert = webkit_dom_document_create_element (document, "span", NULL);
+ webkit_dom_element_set_class_name (signature_to_insert, "-x-evo-signature");
+ /* The combo box active ID is the signature's ESource UID. */
+ webkit_dom_element_set_id (signature_to_insert, id);
+ insert_signature_in = signature_to_insert;
+
+ /* The signature has no content usually it means it is set to None. */
+ if (!content)
+ goto insert;
+
+ if (!is_html) {
+ gchar *html;
+
+ html = camel_text_to_html (content, 0, 0);
+ if (html) {
+ signature_text = html;
+ } else
+ signature_text = g_strdup (content);
+
+ insert_signature_in = webkit_dom_document_create_element (document, "pre", NULL);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (signature_to_insert),
+ WEBKIT_DOM_NODE (insert_signature_in),
+ NULL);
+ } else
+ signature_text = g_strdup (content);
+
+
+ /* If inserting HTML signature in the plain text composer we have to convert it. */
+ if (is_html && !view->priv->html_mode && !strstr (signature_text,
"data-evo-signature-plain-text-mode")) {
+ gchar *inner_text;
+
+ /* Save the converted signature to avoid parsing it later again
+ * while inserting it into the view. */
+ converted_signature = webkit_dom_document_create_element (document, "pre", NULL);
+ webkit_dom_html_element_set_inner_html (
+ WEBKIT_DOM_HTML_ELEMENT (converted_signature), signature_text, NULL);
+ e_html_editor_view_convert_element_from_html_to_plain_text (view, converted_signature);
+ inner_text = webkit_dom_html_element_get_inner_text (WEBKIT_DOM_HTML_ELEMENT
(converted_signature));
+
+ g_free (signature_text);
+ signature_text = inner_text ? g_strstrip (inner_text) : g_strdup ("");
+ /* because of the -- \n check */
+ is_html = FALSE;
+ }
+
+ /* The signature dash convention ("-- \n") is specified
+ * in the "Son of RFC 1036", section 4.3.2.
+ * http://www.chemie.fu-berlin.de/outerspace/netnews/son-of-1036.html
+ */
+ if (add_signature_delimiter (view)) {
+ const gchar *delim;
+ const gchar *delim_nl;
+
+ if (is_html) {
+ delim = "-- <BR>";
+ delim_nl = "\n-- <BR>";
+ } else {
+ delim = "-- \n";
+ delim_nl = "\n-- \n";
+ }
+
+ /* Skip the delimiter if the signature already has one. */
+ if (g_ascii_strncasecmp (signature_text, delim, strlen (delim)) == 0)
+ ; /* skip */
+ else if (e_util_strstrcase (signature_text, delim_nl) != NULL)
+ ; /* skip */
+ else
+ webkit_dom_html_element_set_inner_html (
+ WEBKIT_DOM_HTML_ELEMENT (insert_signature_in), delim, NULL);
+ }
+
+ if (converted_signature) {
+ WebKitDOMNode *node;
+
+ while ((node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (converted_signature))))
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (insert_signature_in), node, NULL);
+ remove_node (WEBKIT_DOM_NODE (converted_signature));
+ } else
+ webkit_dom_html_element_insert_adjacent_html (
+ WEBKIT_DOM_HTML_ELEMENT (insert_signature_in), "beforeend", signature_text, NULL);
+
+ element = webkit_dom_element_query_selector (
+ insert_signature_in, "[data-evo-signature-plain-text-mode]", NULL);
+ if (element)
+ webkit_dom_element_remove_attribute (
+ element, "data-evo-signature-plain-text-mode");
+ g_free (signature_text);
+
+insert:
+ /* Remove the old signature and insert the new one. */
+ signatures = webkit_dom_document_get_elements_by_class_name (
+ document, "-x-evo-signature-wrapper");
+ list_length = webkit_dom_node_list_get_length (signatures);
+ for (ii = 0; ii < list_length; ii++) {
+ WebKitDOMNode *wrapper, *signature;
+
+ wrapper = webkit_dom_node_list_item (signatures, ii);
+ signature = webkit_dom_node_get_first_child (wrapper);
+
+ /* Old messages will have the signature id in the name attribute, correct it. */
+ dom_element_rename_attribute (WEBKIT_DOM_ELEMENT (signature), "name", "id");
+
+ /* When we are editing a message with signature, we need to unset the
+ * active signature id as if the signature in the message was edited
+ * by the user we would discard these changes. */
+ if (*set_signature_from_message &&
+ (view->priv->is_message_from_edit_as_new || view->priv->is_message_from_draft)) {
+ if (*check_if_signature_is_changed) {
+ /* Normalize the signature that we want to insert as the one in the
+ * message already is normalized. */
+ webkit_dom_node_normalize (WEBKIT_DOM_NODE (signature_to_insert));
+ if (!webkit_dom_node_is_equal_node (WEBKIT_DOM_NODE (signature_to_insert),
signature)) {
+ /* Signature in the body is different than the one with the
+ * same id, so set the active signature to None and leave
+ * the signature that is in the body. */
+ new_signature_id = g_strdup ("none");
+ *ignore_next_signature_change = TRUE;
+ }
+
+ *check_if_signature_is_changed = FALSE;
+ *set_signature_from_message = FALSE;
+ } else {
+ /* Load the signature and check if is it the same
+ * as the signature in body or the user previously
+ * changed it. */
+ new_signature_id = webkit_dom_element_get_id (WEBKIT_DOM_ELEMENT (signature));
+ *check_if_signature_is_changed = TRUE;
+ }
+ g_object_unref (wrapper);
+ g_object_unref (signatures);
+
+ return new_signature_id;
+ }
+
+ /* If the top signature was set we have to remove the newline
+ * that was inserted after it */
+ if (top_signature) {
+ WebKitDOMElement *spacer;
+
+ spacer = webkit_dom_document_query_selector (
+ document, ".-x-evo-top-signature-spacer", NULL);
+ if (spacer)
+ remove_node_if_empty (WEBKIT_DOM_NODE (spacer));
+ }
+ /* We have to remove the div containing the span with signature */
+ remove_node (wrapper);
+ g_object_unref (wrapper);
+ }
+ g_object_unref (signatures);
+
+ body = webkit_dom_document_get_body (document);
+ signature_wrapper = webkit_dom_document_create_element (document, "div", NULL);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (signature_wrapper),
+ WEBKIT_DOM_NODE (signature_to_insert),
+ NULL);
+ webkit_dom_element_set_class_name (signature_wrapper, "-x-evo-signature-wrapper");
+
+ if (top_signature) {
+ WebKitDOMNode *child;
+
+ child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body));
+
+ if (start_typing_at_bottom (view)) {
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (signature_wrapper),
+ child,
+ NULL);
+ } else {
+ /* When we are using signature on top the caret
+ * should be before the signature */
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (signature_wrapper),
+ child,
+ NULL);
+ }
+ } else {
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (signature_wrapper),
+ NULL);
+ }
+
+ if (is_html && view->priv->html_mode)
+ e_html_editor_view_fix_file_uri_images (view);
+
+ move_caret_after_signature_inserted (view);
+
+ /* Make sure the flag will be unset and won't influence user's choice */
+ *set_signature_from_message = FALSE;
+
+ return NULL;
+}
diff --git a/e-util/e-html-editor-view.h b/e-util/e-html-editor-view.h
index 386574e..4784983 100644
--- a/e-util/e-html-editor-view.h
+++ b/e-util/e-html-editor-view.h
@@ -285,6 +285,11 @@ gboolean e_html_editor_view_is_message_from_edit_as_new
void e_html_editor_view_set_is_message_from_edit_as_new
(EHTMLEditorView *view,
gboolean value);
+gboolean e_html_editor_view_content_is_new_message
+ (EHTMLEditorView *view);
+void e_html_editor_view_set_content_is_new_message
+ (EHTMLEditorView *view,
+ gboolean value);
void e_html_editor_view_insert_quoted_text
(EHTMLEditorView *view,
const gchar *text);
@@ -320,6 +325,14 @@ void e_html_editor_view_remove_input_event_listener_from_body
(EHTMLEditorView *view);
void e_html_editor_view_register_input_event_listener_on_body
(EHTMLEditorView *view);
+gchar * e_html_editor_view_insert_signature
+ (EHTMLEditorView *view,
+ const gchar *content,
+ gboolean is_html,
+ const gchar *id,
+ gboolean *set_signature_from_message,
+ gboolean *check_if_signature_is_changed,
+ gboolean *ignore_next_signature_change);
G_END_DECLS
#endif /* E_HTML_EDITOR_VIEW_H */
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index 936df14..f91ccd5 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -1360,6 +1360,8 @@ em_utils_compose_new_message (EShell *shell,
CamelFolder *folder)
{
EMsgComposer *composer;
+ EHTMLEditor *editor;
+ EHTMLEditorView *view;
g_return_val_if_fail (E_IS_SHELL (shell), NULL);
@@ -1368,7 +1370,11 @@ em_utils_compose_new_message (EShell *shell,
composer = create_new_composer (shell, "", folder);
composer_set_no_change (composer);
- e_msg_composer_is_from_new_message (composer, TRUE);
+
+ editor = e_msg_composer_get_editor (composer);
+ view = e_html_editor_get_view (editor);
+
+ e_html_editor_view_set_content_is_new_message (view, TRUE);
gtk_widget_show (GTK_WIDGET (composer));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]