[evolution/449-support-markdown-in-composer] Composer: Add markdown options to the composer mode
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/449-support-markdown-in-composer] Composer: Add markdown options to the composer mode
- Date: Fri, 4 Feb 2022 12:54:07 +0000 (UTC)
commit cdbe7da269851551a0484813cff2dcf8c4b64fb6
Author: Milan Crha <mcrha redhat com>
Date: Fri Feb 4 13:51:47 2022 +0100
Composer: Add markdown options to the composer mode
Implement stub functions in the EMarkdownEditor for the EContentEditor
interface, to be able to test the changes.
data/evolution.convert | 1 -
data/org.gnome.evolution.mail.gschema.xml.in | 27 +-
src/composer/e-msg-composer.c | 32 +-
src/e-util/e-html-editor-actions.c | 65 ++-
src/e-util/e-html-editor-manager.ui | 3 +
src/e-util/e-html-editor-private.h | 1 +
src/e-util/e-html-editor.c | 63 ++-
src/e-util/e-html-editor.h | 4 +
src/e-util/e-mail-signature-manager.c | 48 +-
src/e-util/e-mail-signature-manager.h | 8 +-
src/e-util/e-markdown-editor.c | 511 ++++++++++++++++++++-
src/e-util/e-util-enums.h | 10 +-
src/mail/e-mail-enums.h | 27 +-
src/mail/e-mail-notes.c | 2 +-
src/mail/em-composer-utils.c | 87 +++-
src/mail/mail-config.ui | 26 +-
.../composer-to-meeting/e-meeting-to-composer.c | 13 +-
src/modules/mail/e-mail-shell-backend.c | 7 +-
src/modules/mail/em-composer-prefs.c | 65 ++-
19 files changed, 899 insertions(+), 101 deletions(-)
---
diff --git a/data/evolution.convert b/data/evolution.convert
index c434d52952..470a6cf56c 100644
--- a/data/evolution.convert
+++ b/data/evolution.convert
@@ -121,7 +121,6 @@ composer-no-signature-delim = /apps/evolution/mail/composer/no_signature_delim
composer-outlook-filenames = /apps/evolution/mail/composer/outlook_filenames
composer-reply-start-bottom = /apps/evolution/mail/composer/reply_start_bottom
composer-request-receipt = /apps/evolution/mail/composer/request_receipt
-composer-send-html = /apps/evolution/mail/composer/send_html
composer-show-bcc = /apps/evolution/mail/composer/show_mail_bcc
composer-show-cc = /apps/evolution/mail/composer/show_mail_cc
composer-show-post-from = /apps/evolution/mail/composer/show_post_from
diff --git a/data/org.gnome.evolution.mail.gschema.xml.in b/data/org.gnome.evolution.mail.gschema.xml.in
index 33e02ee0bb..f97b99f9ce 100644
--- a/data/org.gnome.evolution.mail.gschema.xml.in
+++ b/data/org.gnome.evolution.mail.gschema.xml.in
@@ -44,6 +44,16 @@
<value nick='books' value='2'/>
</enum>
+ <!-- Keep this synchronized with EContentEditorMode. -->
+ <enum id="org.gnome.evolution.mail.ContentEditorMode">
+ <value nick='unknown' value='-1'/>
+ <value nick='plain-text' value='0'/>
+ <value nick='html' value='1'/>
+ <value nick='markdown' value='2'/>
+ <value nick='markdown-plain-text' value='3'/>
+ <value nick='markdown-html' value='4'/>
+ </enum>
+
<schema gettext-domain="evolution" id="org.gnome.evolution.mail" path="/org/gnome/evolution/mail/">
<key name="prompt-check-if-default-mailer" type="b">
<default>true</default>
@@ -57,8 +67,8 @@
</key>
<key name="composer-editor" type="s">
<default>''</default>
- <_summary>Comma-separated names of the editor to prefer in the message composer for which
modes</_summary>
- <_description>If the name doesn’t correspond to any known editor, then the built-in WebKit editor is
used. The mode is optional, in which case the editor is used for all the modes it supports. Modes are “plain”
and “html”. Example values: “webkit” (to use WebKit for plain and html),
“plain:first-editor,html:second-editor” (to use “first-editor” for the “plain” and “second-editor” for
“html”)</_description>
+ <_summary>Comma-separated names of the editor to prefer in the message composer</_summary>
+ <_description>If the name doesn’t correspond to any known editor, then the built-in WebKit editor is
used. The mode is optional, in which case the editor is used for all the modes it supports. Modes are
“plain”, “html”, "markdown-plain", "markdown-html" and "markdown". Example values: “webkit” (to use WebKit
for plain and html), “plain:first-editor,html:second-editor” (to use “first-editor” for the “plain” and
“second-editor” for “html”)</_description>
</key>
<key name="composer-gallery-path" type="s">
<default>''</default>
@@ -115,10 +125,9 @@
<_summary>Always request read receipt</_summary>
<_description>Whether a read receipt request gets added to every message by default.</_description>
</key>
- <key name="composer-send-html" type="b">
- <default>false</default>
- <_summary>Send HTML mail by default</_summary>
- <_description>Send HTML mail by default.</_description>
+ <key name="composer-mode" enum="org.gnome.evolution.mail.ContentEditorMode">
+ <default>'plain-text'</default>
+ <_summary>What mode open the composer with</_summary>
</key>
<key name="composer-spell-languages" type="as">
<default>[]</default>
@@ -800,9 +809,9 @@
<default>'quoted'</default>
<_summary>Alternative reply style</_summary>
</key>
- <key name="alt-reply-html-format" enum="org.gnome.evolution.mail.ThreeState">
- <default>'inconsistent'</default>
- <_summary>Format message in HTML</_summary>
+ <key name="alt-reply-format-mode" enum="org.gnome.evolution.mail.ContentEditorMode">
+ <default>'unknown'</default>
+ <_summary>Composer mode to use.</_summary>
</key>
<key name="alt-reply-start-bottom" enum="org.gnome.evolution.mail.ThreeState">
<default>'inconsistent'</default>
diff --git a/src/composer/e-msg-composer.c b/src/composer/e-msg-composer.c
index 5f22ed0bc4..cea20f8cc1 100644
--- a/src/composer/e-msg-composer.c
+++ b/src/composer/e-msg-composer.c
@@ -1212,12 +1212,24 @@ composer_add_evolution_composer_mode_header (CamelMedium *medium,
editor = e_msg_composer_get_editor (composer);
switch (e_html_editor_get_mode (editor)) {
+ case E_CONTENT_EDITOR_MODE_UNKNOWN:
+ g_warn_if_reached ();
+ break;
case E_CONTENT_EDITOR_MODE_PLAIN_TEXT:
mode = "text/plain";
break;
case E_CONTENT_EDITOR_MODE_HTML:
mode = "text/html";
break;
+ case E_CONTENT_EDITOR_MODE_MARKDOWN:
+ mode = "text/markdown";
+ break;
+ case E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT:
+ mode = "text/markdown-plain";
+ break;
+ case E_CONTENT_EDITOR_MODE_MARKDOWN_HTML:
+ mode = "text/markdown-html";
+ break;
}
camel_medium_add_header (medium, "X-Evolution-Composer-Mode", mode);
@@ -4123,10 +4135,24 @@ e_msg_composer_setup_with_message (EMsgComposer *composer,
for (i = 0; flags[i]; i++) {
if (g_ascii_strcasecmp (flags[i], "text/html") == 0 ||
g_ascii_strcasecmp (flags[i], "text/plain") == 0) {
- gboolean html_mode;
+ EContentEditorMode mode = E_CONTENT_EDITOR_MODE_HTML;
+
+ if (composer_mode) {
+ if (!g_ascii_strcasecmp (composer_mode, "text/plain"))
+ mode = E_CONTENT_EDITOR_MODE_PLAIN_TEXT;
+ else if (!g_ascii_strcasecmp (composer_mode, "text/html"))
+ mode = E_CONTENT_EDITOR_MODE_HTML;
+ else if (!g_ascii_strcasecmp (composer_mode, "text/markdown"))
+ mode = E_CONTENT_EDITOR_MODE_MARKDOWN;
+ else if (!g_ascii_strcasecmp (composer_mode, "text/markdown-plain"))
+ mode = E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT;
+ else if (!g_ascii_strcasecmp (composer_mode, "text/markdown-html"))
+ mode = E_CONTENT_EDITOR_MODE_MARKDOWN_HTML;
+ } else if (!g_ascii_strcasecmp (flags[i], "text/plain")) {
+ mode = E_CONTENT_EDITOR_MODE_PLAIN_TEXT;
+ }
- html_mode = composer_mode && !g_ascii_strcasecmp (composer_mode, "text/html");
- e_html_editor_set_mode (editor, html_mode ? E_CONTENT_EDITOR_MODE_HTML :
E_CONTENT_EDITOR_MODE_PLAIN_TEXT);
+ e_html_editor_set_mode (editor, mode);
} else if (g_ascii_strcasecmp (flags[i], "pgp-sign") == 0) {
action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN));
gtk_toggle_action_set_active (action, TRUE);
diff --git a/src/e-util/e-html-editor-actions.c b/src/e-util/e-html-editor-actions.c
index 05e1802cad..226e85edba 100644
--- a/src/e-util/e-html-editor-actions.c
+++ b/src/e-util/e-html-editor-actions.c
@@ -1314,14 +1314,35 @@ static GtkRadioActionEntry core_mode_entries[] = {
N_("_HTML"),
NULL,
N_("HTML editing mode"),
- E_CONTENT_EDITOR_MODE_HTML }, /* e_html_editor_set_mode */
+ E_CONTENT_EDITOR_MODE_HTML },
{ "mode-plain",
NULL,
N_("Plain _Text"),
NULL,
N_("Plain text editing mode"),
- E_CONTENT_EDITOR_MODE_PLAIN_TEXT } /* e_html_editor_set_mode */
+ E_CONTENT_EDITOR_MODE_PLAIN_TEXT },
+
+ { "mode-markdown",
+ NULL,
+ N_("_Markdown"),
+ NULL,
+ N_("Markdown editing mode"),
+ E_CONTENT_EDITOR_MODE_MARKDOWN },
+
+ { "mode-markdown-plain",
+ NULL,
+ N_("Ma_rkdown as Plain Text"),
+ NULL,
+ N_("Markdown editing mode, exported as Plain Text"),
+ E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT },
+
+ { "mode-markdown-html",
+ NULL,
+ N_("Mar_kdown as HTML"),
+ NULL,
+ N_("Markdown editing mode, exported as HTML"),
+ E_CONTENT_EDITOR_MODE_MARKDOWN_HTML }
};
static GtkRadioActionEntry core_style_entries[] = {
@@ -2159,7 +2180,7 @@ e_html_editor_actions_init (EHTMLEditor *editor)
gtk_action_group_add_radio_actions (
action_group, core_mode_entries,
G_N_ELEMENTS (core_mode_entries),
- TRUE,
+ E_CONTENT_EDITOR_MODE_HTML,
G_CALLBACK (action_mode_cb), editor);
gtk_action_group_add_radio_actions (
action_group, core_style_entries,
@@ -2297,6 +2318,44 @@ e_html_editor_indent_level_to_bool_unindent_cb (GBinding *binding,
return TRUE;
}
+/**
+ * e_html_editor_util_new_mode_combobox:
+ *
+ * Creates a new combo box containing all composer modes.
+ *
+ * It's a descendant of #EActionComboBox, thus use e_action_combo_box_get_current_value()
+ * and e_action_combo_box_set_current_value() to get the currently selected mode.
+ *
+ * Returns: (transfer full): a new #EActionComboBox with composer modes
+ *
+ * Since: 3.44
+ **/
+EActionComboBox *
+e_html_editor_util_new_mode_combobox (void)
+{
+ GtkActionGroup *action_group;
+ GtkAction *action;
+ GtkWidget *widget;
+
+ action_group = gtk_action_group_new ("core-mode-entries");
+
+ gtk_action_group_add_radio_actions (
+ action_group, core_mode_entries,
+ G_N_ELEMENTS (core_mode_entries),
+ E_CONTENT_EDITOR_MODE_HTML,
+ NULL, NULL);
+
+ action = gtk_action_group_get_action (action_group, "mode-html");
+
+ widget = e_action_combo_box_new_with_action (GTK_RADIO_ACTION (action));
+ gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE);
+ gtk_widget_set_tooltip_text (widget, _("Editing Mode"));
+
+ g_object_set_data_full (G_OBJECT (widget), "core-mode-entries-action-group", action_group,
g_object_unref);
+
+ return E_ACTION_COMBO_BOX (widget);
+}
+
void
e_html_editor_actions_bind (EHTMLEditor *editor)
{
diff --git a/src/e-util/e-html-editor-manager.ui b/src/e-util/e-html-editor-manager.ui
index 3f7468d4de..885108bde2 100644
--- a/src/e-util/e-html-editor-manager.ui
+++ b/src/e-util/e-html-editor-manager.ui
@@ -51,6 +51,9 @@
<placeholder name='format-menu-top'/>
<menuitem action='mode-html'/>
<menuitem action='mode-plain'/>
+ <menuitem action='mode-markdown-plain'/>
+ <menuitem action='mode-markdown-html'/>
+ <menuitem action='mode-markdown'/>
<separator/>
<menu action='font-style-menu'>
<menuitem action='bold'/>
diff --git a/src/e-util/e-html-editor-private.h b/src/e-util/e-html-editor-private.h
index 87ec2ca847..23a4dc435d 100644
--- a/src/e-util/e-html-editor-private.h
+++ b/src/e-util/e-html-editor-private.h
@@ -69,6 +69,7 @@ struct _EHTMLEditorPrivate {
GtkWidget *activity_bar;
GtkWidget *alert_bar;
GtkWidget *edit_area;
+ GtkWidget *markdown_editor;
GtkWidget *find_dialog;
GtkWidget *replace_dialog;
diff --git a/src/e-util/e-html-editor.c b/src/e-util/e-html-editor.c
index d1db3e3f69..8a74a8bdcf 100644
--- a/src/e-util/e-html-editor.c
+++ b/src/e-util/e-html-editor.c
@@ -34,10 +34,13 @@
#include "e-alert-sink.h"
#include "e-html-editor-private.h"
#include "e-content-editor.h"
+#include "e-markdown-editor.h"
#include "e-misc-utils.h"
#include "e-simple-async-result.h"
#include "e-util-enumtypes.h"
+#define MARKDOWN_EDITOR_NAME "markdown"
+
#define E_HTML_EDITOR_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_HTML_EDITOR, EHTMLEditorPrivate))
@@ -836,6 +839,10 @@ html_editor_constructed (GObject *object)
e_extensible_load_extensions (E_EXTENSIBLE (object));
+ /* Register the markdown editor */
+ priv->markdown_editor = g_object_ref_sink (e_markdown_editor_new ());
+ e_html_editor_register_content_editor (editor, MARKDOWN_EDITOR_NAME, E_CONTENT_EDITOR
(priv->markdown_editor));
+
/* Construct the main editing area. */
widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
g_object_set (G_OBJECT (widget),
@@ -998,6 +1005,7 @@ html_editor_dispose (GObject *object)
g_clear_object (&priv->activity_bar);
g_clear_object (&priv->alert_bar);
g_clear_object (&priv->edit_area);
+ g_clear_object (&priv->markdown_editor);
g_clear_object (&priv->fg_color_combo_box);
g_clear_object (&priv->bg_color_combo_box);
@@ -1300,16 +1308,26 @@ e_html_editor_get_content_editor_for_mode (EHTMLEditor *editor,
return cnt_editor;
switch (mode) {
+ case E_CONTENT_EDITOR_MODE_UNKNOWN:
+ g_warn_if_reached ();
+ break;
case E_CONTENT_EDITOR_MODE_PLAIN_TEXT:
mode_name = "plain";
break;
case E_CONTENT_EDITOR_MODE_HTML:
mode_name = "html";
break;
+ case E_CONTENT_EDITOR_MODE_MARKDOWN:
+ mode_name = "markdown";
+ break;
+ case E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT:
+ mode_name = "markdown-plain";
+ break;
+ case E_CONTENT_EDITOR_MODE_MARKDOWN_HTML:
+ mode_name = "markdown-html";
+ break;
}
- g_warn_if_fail (mode_name != NULL);
-
settings = e_util_ref_settings ("org.gnome.evolution.mail");
name = g_settings_get_string (settings, "composer-editor");
g_clear_object (&settings);
@@ -1348,8 +1366,17 @@ e_html_editor_get_content_editor_for_mode (EHTMLEditor *editor,
g_free (name);
- if (!cnt_editor)
- cnt_editor = g_hash_table_lookup (editor->priv->content_editors, DEFAULT_CONTENT_EDITOR_NAME);
+ if (!cnt_editor) {
+ if (mode == E_CONTENT_EDITOR_MODE_MARKDOWN ||
+ mode == E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT ||
+ mode == E_CONTENT_EDITOR_MODE_MARKDOWN_HTML)
+ cnt_editor = g_hash_table_lookup (editor->priv->content_editors,
MARKDOWN_EDITOR_NAME);
+ else
+ cnt_editor = g_hash_table_lookup (editor->priv->content_editors,
DEFAULT_CONTENT_EDITOR_NAME);
+
+ if (cnt_editor && !e_content_editor_supports_mode (cnt_editor, mode))
+ cnt_editor = NULL;
+ }
if (!cnt_editor) {
GHashTableIter iter;
@@ -1357,7 +1384,7 @@ e_html_editor_get_content_editor_for_mode (EHTMLEditor *editor,
g_hash_table_iter_init (&iter, editor->priv->content_editors);
while (g_hash_table_iter_next (&iter, NULL, &value)) {
- if (e_content_editor_supports_mode (value, editor->priv->mode)) {
+ if (e_content_editor_supports_mode (value, mode)) {
cnt_editor = value;
break;
}
@@ -1529,34 +1556,32 @@ void
e_html_editor_set_mode (EHTMLEditor *editor,
EContentEditorMode mode)
{
- EContentEditor *cnt_editor, *old_cnt_editor;
+ EContentEditor *cnt_editor;
g_return_if_fail (E_IS_HTML_EDITOR (editor));
+ if (mode == E_CONTENT_EDITOR_MODE_UNKNOWN)
+ mode = E_CONTENT_EDITOR_MODE_PLAIN_TEXT;
+
if (editor->priv->mode == mode)
return;
- old_cnt_editor = editor->priv->use_content_editor;
- editor->priv->use_content_editor = NULL;
-
- cnt_editor = e_html_editor_get_content_editor (editor);
+ cnt_editor = e_html_editor_get_content_editor_for_mode (editor, mode);
if (cnt_editor) {
- editor->priv->mode = mode;
-
- g_object_set (G_OBJECT (cnt_editor), "mode", mode, NULL);
-
- if (cnt_editor != old_cnt_editor) {
- if (old_cnt_editor)
- gtk_widget_hide (GTK_WIDGET (old_cnt_editor));
+ if (cnt_editor != editor->priv->use_content_editor) {
+ if (editor->priv->use_content_editor)
+ gtk_widget_hide (GTK_WIDGET (editor->priv->use_content_editor));
if (cnt_editor)
gtk_widget_show (GTK_WIDGET (cnt_editor));
}
+ editor->priv->mode = mode;
+ editor->priv->use_content_editor = cnt_editor;
+
+ g_object_set (G_OBJECT (cnt_editor), "mode", mode, NULL);
g_object_notify (G_OBJECT (editor), "mode");
- } else {
- editor->priv->use_content_editor = old_cnt_editor;
}
}
diff --git a/src/e-util/e-html-editor.h b/src/e-util/e-html-editor.h
index e79b1fb8e7..fba394b6db 100644
--- a/src/e-util/e-html-editor.h
+++ b/src/e-util/e-html-editor.h
@@ -26,6 +26,7 @@
#define E_HTML_EDITOR_H
#include <gtk/gtk.h>
+#include <e-util/e-action-combo-box.h>
#include <e-util/e-activity.h>
#include <e-util/e-activity-bar.h>
#include <e-util/e-content-editor.h>
@@ -134,6 +135,9 @@ void e_html_editor_remove_all_cid_parts
CamelMimePart * e_html_editor_ref_cid_part (EHTMLEditor *editor,
const gchar *cid_uri);
+EActionComboBox *
+ e_html_editor_util_new_mode_combobox
+ (void);
G_END_DECLS
#endif /* E_HTML_EDITOR_H */
diff --git a/src/e-util/e-mail-signature-manager.c b/src/e-util/e-mail-signature-manager.c
index 97b0df43a8..e1d7cca68d 100644
--- a/src/e-util/e-mail-signature-manager.c
+++ b/src/e-util/e-mail-signature-manager.c
@@ -46,12 +46,12 @@ struct _EMailSignatureManagerPrivate {
GtkWidget *preview; /* not referenced */
GtkWidget *preview_frame; /* not referenced */
- gboolean prefer_html;
+ EContentEditorMode prefer_mode;
};
enum {
PROP_0,
- PROP_PREFER_HTML,
+ PROP_PREFER_MODE,
PROP_REGISTRY
};
@@ -188,10 +188,10 @@ mail_signature_manager_set_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
- case PROP_PREFER_HTML:
- e_mail_signature_manager_set_prefer_html (
+ case PROP_PREFER_MODE:
+ e_mail_signature_manager_set_prefer_mode (
E_MAIL_SIGNATURE_MANAGER (object),
- g_value_get_boolean (value));
+ g_value_get_enum (value));
return;
case PROP_REGISTRY:
@@ -211,10 +211,10 @@ mail_signature_manager_get_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
- case PROP_PREFER_HTML:
- g_value_set_boolean (
+ case PROP_PREFER_MODE:
+ g_value_set_enum (
value,
- e_mail_signature_manager_get_prefer_html (
+ e_mail_signature_manager_get_prefer_mode (
E_MAIL_SIGNATURE_MANAGER (object)));
return;
@@ -410,7 +410,7 @@ mail_signature_manager_editor_created_add_signature_cb (GObject *source_object,
}
editor = e_mail_signature_editor_get_editor (E_MAIL_SIGNATURE_EDITOR (widget));
- e_html_editor_set_mode (editor, manager->priv->prefer_html ? E_CONTENT_EDITOR_MODE_HTML :
E_CONTENT_EDITOR_MODE_PLAIN_TEXT);
+ e_html_editor_set_mode (editor, manager->priv->prefer_mode);
mail_signature_manager_emit_editor_created (manager, widget);
@@ -599,12 +599,13 @@ e_mail_signature_manager_class_init (EMailSignatureManagerClass *class)
g_object_class_install_property (
object_class,
- PROP_PREFER_HTML,
- g_param_spec_boolean (
- "prefer-html",
- "Prefer HTML",
+ PROP_PREFER_MODE,
+ g_param_spec_enum (
+ "prefer-mode",
+ "Prefer editor mode",
NULL,
- TRUE,
+ E_TYPE_CONTENT_EDITOR_MODE,
+ E_CONTENT_EDITOR_MODE_HTML,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
@@ -717,26 +718,29 @@ e_mail_signature_manager_remove_signature (EMailSignatureManager *manager)
g_signal_emit (manager, signals[REMOVE_SIGNATURE], 0);
}
-gboolean
-e_mail_signature_manager_get_prefer_html (EMailSignatureManager *manager)
+EContentEditorMode
+e_mail_signature_manager_get_prefer_mode (EMailSignatureManager *manager)
{
g_return_val_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager), FALSE);
- return manager->priv->prefer_html;
+ return manager->priv->prefer_mode;
}
void
-e_mail_signature_manager_set_prefer_html (EMailSignatureManager *manager,
- gboolean prefer_html)
+e_mail_signature_manager_set_prefer_mode (EMailSignatureManager *manager,
+ EContentEditorMode prefer_mode)
{
g_return_if_fail (E_IS_MAIL_SIGNATURE_MANAGER (manager));
- if (manager->priv->prefer_html == prefer_html)
+ if (prefer_mode == E_CONTENT_EDITOR_MODE_UNKNOWN)
+ prefer_mode = E_CONTENT_EDITOR_MODE_PLAIN_TEXT;
+
+ if (manager->priv->prefer_mode == prefer_mode)
return;
- manager->priv->prefer_html = prefer_html;
+ manager->priv->prefer_mode = prefer_mode;
- g_object_notify (G_OBJECT (manager), "prefer-html");
+ g_object_notify (G_OBJECT (manager), "prefer-mode");
}
ESourceRegistry *
diff --git a/src/e-util/e-mail-signature-manager.h b/src/e-util/e-mail-signature-manager.h
index b67b3df9d7..c6d986d0ba 100644
--- a/src/e-util/e-mail-signature-manager.h
+++ b/src/e-util/e-mail-signature-manager.h
@@ -24,6 +24,7 @@
#include <gtk/gtk.h>
+#include <e-util/e-util-enumtypes.h>
#include <e-util/e-mail-signature-editor.h>
#include <e-util/e-mail-signature-tree-view.h>
@@ -80,11 +81,12 @@ void e_mail_signature_manager_edit_signature
(EMailSignatureManager *manager);
void e_mail_signature_manager_remove_signature
(EMailSignatureManager *manager);
-gboolean e_mail_signature_manager_get_prefer_html
+EContentEditorMode
+ e_mail_signature_manager_get_prefer_mode
(EMailSignatureManager *manager);
-void e_mail_signature_manager_set_prefer_html
+void e_mail_signature_manager_set_prefer_mode
(EMailSignatureManager *manager,
- gboolean prefer_html);
+ EContentEditorMode prefer_mode);
ESourceRegistry *
e_mail_signature_manager_get_registry
(EMailSignatureManager *manager);
diff --git a/src/e-util/e-markdown-editor.c b/src/e-util/e-markdown-editor.c
index 08d4db5bee..e0909add2a 100644
--- a/src/e-util/e-markdown-editor.c
+++ b/src/e-util/e-markdown-editor.c
@@ -15,6 +15,7 @@
#include <libedataserverui/libedataserverui.h>
+#include "e-content-editor.h"
#include "e-misc-utils.h"
#include "e-spell-text-view.h"
#include "e-web-view.h"
@@ -26,9 +27,60 @@ struct _EMarkdownEditorPrivate {
EWebView *web_view;
GtkToolbar *action_toolbar;
gboolean is_dark_theme;
+
+ /* EContentEditor properties */
+ gboolean can_copy;
+ gboolean can_cut;
+ gboolean can_paste;
+ gboolean can_redo;
+ gboolean can_undo;
+ gboolean changed;
+ EContentEditorMode mode;
+ gboolean spell_check_enabled;
+ ESpellChecker *spell_check;
+ EThreeState start_bottom;
+ EThreeState top_signature;
};
-G_DEFINE_TYPE_WITH_PRIVATE (EMarkdownEditor, e_markdown_editor, GTK_TYPE_BOX)
+static void e_markdown_editor_content_editor_init (EContentEditorInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EMarkdownEditor, e_markdown_editor, GTK_TYPE_BOX,
+ G_ADD_PRIVATE (EMarkdownEditor)
+ G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL)
+ G_IMPLEMENT_INTERFACE (E_TYPE_CONTENT_EDITOR, e_markdown_editor_content_editor_init))
+
+enum {
+ PROP_0,
+ PROP_IS_MALFUNCTION,
+ PROP_CAN_COPY,
+ PROP_CAN_CUT,
+ PROP_CAN_PASTE,
+ PROP_CAN_REDO,
+ PROP_CAN_UNDO,
+ PROP_CHANGED,
+ PROP_EDITABLE,
+ PROP_MODE,
+ PROP_SPELL_CHECK_ENABLED,
+ PROP_SPELL_CHECKER,
+ PROP_START_BOTTOM,
+ PROP_TOP_SIGNATURE,
+ PROP_VISUALLY_WRAP_LONG_LINES,
+ PROP_LAST_ERROR,
+
+ PROP_ALIGNMENT,
+ PROP_BACKGROUND_COLOR,
+ PROP_BLOCK_FORMAT,
+ PROP_BOLD,
+ PROP_FONT_COLOR,
+ PROP_FONT_NAME,
+ PROP_FONT_SIZE,
+ PROP_INDENT_LEVEL,
+ PROP_ITALIC,
+ PROP_STRIKETHROUGH,
+ PROP_SUBSCRIPT,
+ PROP_SUPERSCRIPT,
+ PROP_UNDERLINE
+};
enum {
CHANGED,
@@ -37,6 +89,196 @@ enum {
static guint signals[LAST_SIGNAL];
+static gboolean
+e_markdown_editor_supports_mode (EContentEditor *cnt_editor,
+ EContentEditorMode mode)
+{
+ return mode == E_CONTENT_EDITOR_MODE_MARKDOWN ||
+ #ifdef HAVE_MARKDOWN
+ mode == E_CONTENT_EDITOR_MODE_MARKDOWN_HTML ||
+ #endif
+ mode == E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT;
+}
+
+static void
+e_markdown_editor_initialize (EContentEditor *cnt_editor,
+ EContentEditorInitializedCallback callback,
+ gpointer user_data)
+{
+}
+
+static gboolean
+e_markdown_editor_is_ready (EContentEditor *cnt_editor)
+{
+ return TRUE;
+}
+
+static void
+e_markdown_editor_update_styles (EContentEditor *cnt_editor)
+{
+}
+
+static void
+e_markdown_editor_insert_content (EContentEditor *cnt_editor,
+ const gchar *content,
+ EContentEditorInsertContentFlags flags)
+{
+}
+
+static void
+e_markdown_editor_get_content (EContentEditor *cnt_editor,
+ guint32 flags, /* bit-or of EContentEditorGetContentFlags */
+ const gchar *inline_images_from_domain,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+}
+
+static EContentEditorContentHash *
+e_markdown_editor_get_content_finish (EContentEditor *cnt_editor,
+ GAsyncResult *result,
+ GError **error)
+{
+ return NULL;
+}
+
+static gboolean
+e_markdown_editor_can_copy (EMarkdownEditor *self)
+{
+ return self->priv->can_copy;
+}
+
+static gboolean
+e_markdown_editor_can_cut (EMarkdownEditor *self)
+{
+ return self->priv->can_cut;
+}
+
+static gboolean
+e_markdown_editor_can_paste (EMarkdownEditor *self)
+{
+ return self->priv->can_paste;
+}
+
+static gboolean
+e_markdown_editor_can_redo (EMarkdownEditor *self)
+{
+ return self->priv->can_redo;
+}
+
+static gboolean
+e_markdown_editor_can_undo (EMarkdownEditor *self)
+{
+ return self->priv->can_undo;
+}
+
+static gboolean
+e_markdown_editor_get_changed (EMarkdownEditor *self)
+{
+ return self->priv->changed;
+}
+
+static void
+e_markdown_editor_set_changed (EMarkdownEditor *self,
+ gboolean value)
+{
+ if ((self->priv->changed ? 1 : 0) != (value ? 1 : 0)) {
+ self->priv->changed = value;
+ g_object_notify (G_OBJECT (self), "changed");
+ }
+}
+
+static gboolean
+e_markdown_editor_is_editable (EMarkdownEditor *self)
+{
+ return gtk_text_view_get_editable (self->priv->text_view);
+}
+
+static void
+e_markdown_editor_set_editable (EMarkdownEditor *self,
+ gboolean value)
+{
+ if ((gtk_text_view_get_editable (self->priv->text_view) ? 1 : 0) != (value ? 1 : 0)) {
+ gtk_text_view_set_editable (self->priv->text_view, value);
+ g_object_notify (G_OBJECT (self), "editable");
+ }
+}
+
+static EContentEditorMode
+e_markdown_editor_get_mode (EMarkdownEditor *self)
+{
+ return self->priv->mode;
+}
+
+static void
+e_markdown_editor_set_mode (EMarkdownEditor *self,
+ EContentEditorMode mode)
+{
+ g_return_if_fail (mode == E_CONTENT_EDITOR_MODE_MARKDOWN ||
+ mode == E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT ||
+ mode == E_CONTENT_EDITOR_MODE_MARKDOWN_HTML);
+
+ if (self->priv->mode != mode) {
+ self->priv->mode = mode;
+ g_object_notify (G_OBJECT (self), "mode");
+ }
+}
+
+static gboolean
+e_markdown_editor_get_spell_check_enabled (EMarkdownEditor *self)
+{
+ return self->priv->spell_check_enabled;
+}
+
+static void
+e_markdown_editor_set_spell_check_enabled (EMarkdownEditor *self,
+ gboolean value)
+{
+ if ((self->priv->spell_check_enabled ? 1 : 0) != (value ? 1 : 0)) {
+ self->priv->spell_check_enabled = value;
+ g_object_notify (G_OBJECT (self), "spell-check-enabled");
+ }
+}
+
+static ESpellChecker *
+e_markdown_editor_get_spell_checker (EMarkdownEditor *self)
+{
+ return self->priv->spell_check;
+}
+
+static EThreeState
+e_markdown_editor_get_start_bottom (EMarkdownEditor *self)
+{
+ return self->priv->start_bottom;
+}
+
+static void
+e_markdown_editor_set_start_bottom (EMarkdownEditor *self,
+ EThreeState value)
+{
+ if (self->priv->start_bottom != value) {
+ self->priv->start_bottom = value;
+ g_object_notify (G_OBJECT (self), "start-bottom");
+ }
+}
+
+static EThreeState
+e_markdown_editor_get_top_signature (EMarkdownEditor *self)
+{
+ return self->priv->top_signature;
+}
+
+static void
+e_markdown_editor_set_top_signature (EMarkdownEditor *self,
+ EThreeState value)
+{
+ if (self->priv->top_signature != value) {
+ self->priv->top_signature = value;
+ g_object_notify (G_OBJECT (self), "top-signature");
+ }
+}
+
static void
e_markdown_editor_get_selection (EMarkdownEditor *self,
GtkTextIter *out_start,
@@ -478,7 +720,210 @@ e_markdown_editor_text_view_changed_cb (GtkTextView *text_view,
g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+ self->priv->changed = TRUE;
+
g_signal_emit (self, signals[CHANGED], 0, NULL);
+ g_object_notify (G_OBJECT (self), "changed");
+}
+
+static void
+e_markdown_editor_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CHANGED:
+ e_markdown_editor_set_changed (
+ E_MARKDOWN_EDITOR (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_EDITABLE:
+ e_markdown_editor_set_editable (
+ E_MARKDOWN_EDITOR (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_MODE:
+ e_markdown_editor_set_mode (
+ E_MARKDOWN_EDITOR (object),
+ g_value_get_enum (value));
+ return;
+
+ case PROP_SPELL_CHECK_ENABLED:
+ e_markdown_editor_set_spell_check_enabled (
+ E_MARKDOWN_EDITOR (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_START_BOTTOM:
+ e_markdown_editor_set_start_bottom (
+ E_MARKDOWN_EDITOR (object),
+ g_value_get_enum (value));
+ return;
+
+ case PROP_TOP_SIGNATURE:
+ e_markdown_editor_set_top_signature (
+ E_MARKDOWN_EDITOR (object),
+ g_value_get_enum (value));
+ return;
+
+ case PROP_VISUALLY_WRAP_LONG_LINES:
+ case PROP_LAST_ERROR:
+ case PROP_ALIGNMENT:
+ case PROP_BACKGROUND_COLOR:
+ case PROP_BLOCK_FORMAT:
+ case PROP_BOLD:
+ case PROP_FONT_COLOR:
+ case PROP_FONT_NAME:
+ case PROP_FONT_SIZE:
+ case PROP_INDENT_LEVEL:
+ case PROP_ITALIC:
+ case PROP_STRIKETHROUGH:
+ case PROP_SUBSCRIPT:
+ case PROP_SUPERSCRIPT:
+ case PROP_UNDERLINE:
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_markdown_editor_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_IS_MALFUNCTION:
+ g_value_set_boolean (value, FALSE);
+ return;
+
+ case PROP_CAN_COPY:
+ g_value_set_boolean (
+ value, e_markdown_editor_can_copy (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_CAN_CUT:
+ g_value_set_boolean (
+ value, e_markdown_editor_can_cut (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_CAN_PASTE:
+ g_value_set_boolean (
+ value, e_markdown_editor_can_paste (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_CAN_REDO:
+ g_value_set_boolean (
+ value, e_markdown_editor_can_redo (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_CAN_UNDO:
+ g_value_set_boolean (
+ value, e_markdown_editor_can_undo (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_CHANGED:
+ g_value_set_boolean (
+ value, e_markdown_editor_get_changed (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_EDITABLE:
+ g_value_set_boolean (
+ value, e_markdown_editor_is_editable (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_MODE:
+ g_value_set_enum (
+ value, e_markdown_editor_get_mode (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_SPELL_CHECK_ENABLED:
+ g_value_set_boolean (
+ value,
+ e_markdown_editor_get_spell_check_enabled (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_SPELL_CHECKER:
+ g_value_set_object (
+ value,
+ e_markdown_editor_get_spell_checker (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_START_BOTTOM:
+ g_value_set_enum (
+ value,
+ e_markdown_editor_get_start_bottom (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_TOP_SIGNATURE:
+ g_value_set_enum (
+ value,
+ e_markdown_editor_get_top_signature (
+ E_MARKDOWN_EDITOR (object)));
+ return;
+
+ case PROP_VISUALLY_WRAP_LONG_LINES:
+ g_value_set_boolean (value, FALSE);
+ return;
+
+ case PROP_LAST_ERROR:
+ g_value_set_boxed (value, NULL);
+ return;
+
+ case PROP_ALIGNMENT:
+ g_value_set_enum (value, E_CONTENT_EDITOR_ALIGNMENT_LEFT);
+ return;
+
+ case PROP_BACKGROUND_COLOR:
+ g_value_set_boxed (value, NULL);
+ return;
+
+ case PROP_BLOCK_FORMAT:
+ g_value_set_enum (value, E_CONTENT_EDITOR_BLOCK_FORMAT_PRE);
+ return;
+
+ case PROP_FONT_COLOR:
+ g_value_set_boxed (value, NULL);
+ return;
+
+ case PROP_FONT_NAME:
+ g_value_set_string (value, NULL);
+ return;
+
+ case PROP_FONT_SIZE:
+ g_value_set_int (value, 0);
+ return;
+
+ case PROP_INDENT_LEVEL:
+ g_value_set_int (value, 0);
+ return;
+
+ case PROP_BOLD:
+ case PROP_ITALIC:
+ case PROP_STRIKETHROUGH:
+ case PROP_SUBSCRIPT:
+ case PROP_SUPERSCRIPT:
+ case PROP_UNDERLINE:
+ g_value_set_boolean (value, FALSE);
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
static void
@@ -618,6 +1063,37 @@ e_markdown_editor_class_init (EMarkdownEditorClass *klass)
object_class = G_OBJECT_CLASS (klass);
object_class->constructed = e_markdown_editor_constructed;
+ object_class->get_property = e_markdown_editor_get_property;
+ object_class->set_property = e_markdown_editor_set_property;
+
+ g_object_class_override_property (object_class, PROP_IS_MALFUNCTION, "is-malfunction");
+ g_object_class_override_property (object_class, PROP_CAN_COPY, "can-copy");
+ g_object_class_override_property (object_class, PROP_CAN_CUT, "can-cut");
+ g_object_class_override_property (object_class, PROP_CAN_PASTE, "can-paste");
+ g_object_class_override_property (object_class, PROP_CAN_REDO, "can-redo");
+ g_object_class_override_property (object_class, PROP_CAN_UNDO, "can-undo");
+ g_object_class_override_property (object_class, PROP_CHANGED, "changed");
+ g_object_class_override_property (object_class, PROP_MODE, "mode");
+ g_object_class_override_property (object_class, PROP_EDITABLE, "editable");
+ g_object_class_override_property (object_class, PROP_ALIGNMENT, "alignment");
+ g_object_class_override_property (object_class, PROP_BACKGROUND_COLOR, "background-color");
+ g_object_class_override_property (object_class, PROP_BLOCK_FORMAT, "block-format");
+ g_object_class_override_property (object_class, PROP_BOLD, "bold");
+ g_object_class_override_property (object_class, PROP_FONT_COLOR, "font-color");
+ g_object_class_override_property (object_class, PROP_FONT_NAME, "font-name");
+ g_object_class_override_property (object_class, PROP_FONT_SIZE, "font-size");
+ g_object_class_override_property (object_class, PROP_INDENT_LEVEL, "indent-level");
+ g_object_class_override_property (object_class, PROP_ITALIC, "italic");
+ g_object_class_override_property (object_class, PROP_STRIKETHROUGH, "strikethrough");
+ g_object_class_override_property (object_class, PROP_SUBSCRIPT, "subscript");
+ g_object_class_override_property (object_class, PROP_SUPERSCRIPT, "superscript");
+ g_object_class_override_property (object_class, PROP_UNDERLINE, "underline");
+ g_object_class_override_property (object_class, PROP_START_BOTTOM, "start-bottom");
+ g_object_class_override_property (object_class, PROP_TOP_SIGNATURE, "top-signature");
+ g_object_class_override_property (object_class, PROP_SPELL_CHECK_ENABLED, "spell-check-enabled");
+ g_object_class_override_property (object_class, PROP_VISUALLY_WRAP_LONG_LINES,
"visually-wrap-long-lines");
+ g_object_class_override_property (object_class, PROP_LAST_ERROR, "last-error");
+ g_object_class_override_property (object_class, PROP_SPELL_CHECKER, "spell-checker");
/**
* EMarkdownEditor::changed:
@@ -637,10 +1113,43 @@ e_markdown_editor_class_init (EMarkdownEditorClass *klass)
G_TYPE_NONE);
}
+static void
+e_markdown_editor_content_editor_init (EContentEditorInterface *iface)
+{
+ iface->supports_mode = e_markdown_editor_supports_mode;
+ iface->initialize = e_markdown_editor_initialize;
+ iface->is_ready = e_markdown_editor_is_ready;
+ iface->update_styles = e_markdown_editor_update_styles;
+ iface->insert_content = e_markdown_editor_insert_content;
+ iface->get_content = e_markdown_editor_get_content;
+ iface->get_content_finish = e_markdown_editor_get_content_finish;
+ /*iface->move_caret_on_coordinates = e_markdown_editor_move_caret_on_coordinates;
+ iface->cut = e_markdown_editor_cut;
+ iface->copy = e_markdown_editor_copy;
+ iface->paste = e_markdown_editor_paste;
+ iface->paste_primary = e_markdown_editor_paste_primary;
+ iface->undo = e_markdown_editor_undo;
+ iface->redo = e_markdown_editor_redo;
+ iface->clear_undo_redo_history = e_markdown_editor_clear_undo_redo_history;
+ iface->set_spell_checking_languages = e_markdown_editor_set_spell_checking_languages;
+ iface->get_caret_word = e_markdown_editor_get_caret_word;
+ iface->replace_caret_word = e_markdown_editor_replace_caret_word;
+ iface->select_all = e_markdown_editor_select_all;
+ iface->find = e_markdown_editor_find;
+ iface->replace = e_markdown_editor_replace;
+ iface->replace_all = e_markdown_editor_replace_all;
+ iface->get_current_signature_uid = e_markdown_editor_get_current_signature_uid;
+ iface->insert_signature = e_markdown_editor_insert_signature;*/
+}
+
static void
e_markdown_editor_init (EMarkdownEditor *self)
{
self->priv = e_markdown_editor_get_instance_private (self);
+
+ self->priv->mode = E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT;
+ self->priv->start_bottom = E_THREE_STATE_INCONSISTENT;
+ self->priv->top_signature = E_THREE_STATE_INCONSISTENT;
}
/**
diff --git a/src/e-util/e-util-enums.h b/src/e-util/e-util-enums.h
index c30cb51a52..bd2f2ca7f3 100644
--- a/src/e-util/e-util-enums.h
+++ b/src/e-util/e-util-enums.h
@@ -527,16 +527,24 @@ typedef enum {
/**
* EContentEditorMode:
+ * @E_CONTENT_EDITOR_MODE_UNKNOWN: unknown mode
* @E_CONTENT_EDITOR_MODE_PLAIN_TEXT: plain text, expects export as text/plain
* @E_CONTENT_EDITOR_MODE_HTML: HTML, expects export as text/html
+ * @E_CONTENT_EDITOR_MODE_MARKDOWN: markdown, expects export as text/markdown
+ * @E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT: markdown, expects export as text/plain
+ * @E_CONTENT_EDITOR_MODE_MARKDOWN_HTML: markdown, expects export as text/html
*
* Editing mode of a content editor.
*
* Since: 3.44
**/
typedef enum {
+ E_CONTENT_EDITOR_MODE_UNKNOWN = -1,
E_CONTENT_EDITOR_MODE_PLAIN_TEXT,
- E_CONTENT_EDITOR_MODE_HTML
+ E_CONTENT_EDITOR_MODE_HTML,
+ E_CONTENT_EDITOR_MODE_MARKDOWN,
+ E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT,
+ E_CONTENT_EDITOR_MODE_MARKDOWN_HTML
} EContentEditorMode;
/**
diff --git a/src/mail/e-mail-enums.h b/src/mail/e-mail-enums.h
index 9ae17d76bf..4702bc1997 100644
--- a/src/mail/e-mail-enums.h
+++ b/src/mail/e-mail-enums.h
@@ -50,11 +50,25 @@ typedef enum {
* @E_MAIL_REPLY_FLAG_FORCE_STYLE: Force use of the passed-in reply style; if not set,
* then also checks reply style setting for the used mail account.
* @E_MAIL_REPLY_FLAG_FORMAT_PLAIN: Force compose in Plain Text format; cannot be used together
- * with @E_MAIL_REPLY_FLAG_FORMAT_HTML. If none of these is set, then uses
- * global setting.
+ * with @E_MAIL_REPLY_FLAG_FORMAT_HTML, @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN,
+ * @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_PLAIN nor @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_HTML.
+ * If none of these is set, then uses global setting.
* @E_MAIL_REPLY_FLAG_FORMAT_HTML: Force compose in HTML format; cannot be used together
- * with @E_MAIL_REPLY_FLAG_FORMAT_PLAIN. If none of these is set, then uses
- * global setting.
+ * with @E_MAIL_REPLY_FLAG_FORMAT_PLAIN, @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN,
+ * @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_PLAIN nor @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_HTML.
+ * If none of these is set, then uses global setting.
+ * @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN: Force compose in Markdown format; cannot be used together
+ * with @E_MAIL_REPLY_FLAG_FORMAT_PLAIN, @E_MAIL_REPLY_FLAG_FORMAT_HTML,
+ * @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_PLAIN nor @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_HTML.
+ * If none of these is set, then uses global setting. (Since: 3.44)
+ * @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_PLAIN: Force compose in Markdown as Plain Text format; cannot be used
together
+ * with @E_MAIL_REPLY_FLAG_FORMAT_PLAIN, @E_MAIL_REPLY_FLAG_FORMAT_HTML,
+ * @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN nor @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_HTML.
+ * If none of these is set, then uses global setting. (Since: 3.44)
+ * @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_HTML: Force compose in Markdown as HTML format; cannot be used together
+ * with @E_MAIL_REPLY_FLAG_FORMAT_PLAIN, @E_MAIL_REPLY_FLAG_FORMAT_HTML,
+ * @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN nor @E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_PLAIN.
+ * If none of these is set, then uses global setting. (Since: 3.44)
* @E_MAIL_REPLY_FLAG_TOP_POSTING: Force top posting; cannot be used together
* with @E_MAIL_REPLY_FLAG_BOTTOM_POSTING. If none is set, then uses global settings.
* @E_MAIL_REPLY_FLAG_BOTTOM_POSTING: Force bottom posting; cannot be used together
@@ -79,7 +93,10 @@ typedef enum { /*< flags >*/
E_MAIL_REPLY_FLAG_BOTTOM_POSTING = 1 << 4,
E_MAIL_REPLY_FLAG_TOP_SIGNATURE = 1 << 5,
E_MAIL_REPLY_FLAG_BOTTOM_SIGNATURE = 1 << 6,
- E_MAIL_REPLY_FLAG_FORCE_SENDER_REPLY = 1 << 7
+ E_MAIL_REPLY_FLAG_FORCE_SENDER_REPLY = 1 << 7,
+ E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN = 1 << 8,
+ E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_PLAIN = 1 << 9,
+ E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_HTML = 1 << 10
} EMailReplyFlags;
G_END_DECLS
diff --git a/src/mail/e-mail-notes.c b/src/mail/e-mail-notes.c
index e7b7a9780c..ccdad4243d 100644
--- a/src/mail/e-mail-notes.c
+++ b/src/mail/e-mail-notes.c
@@ -1142,7 +1142,7 @@ e_mail_notes_editor_new_with_editor (EHTMLEditor *html_editor,
gtk_widget_grab_focus (GTK_WIDGET (cnt_editor));
settings = e_util_ref_settings ("org.gnome.evolution.mail");
- e_html_editor_set_mode (html_editor, g_settings_get_boolean (settings, "composer-send-html") ?
E_CONTENT_EDITOR_MODE_HTML : E_CONTENT_EDITOR_MODE_PLAIN_TEXT);
+ e_html_editor_set_mode (html_editor, g_settings_get_enum (settings, "composer-mode"));
if (g_settings_get_boolean (settings, "composer-plain-text-starts-preformatted")) {
g_signal_connect_object (cnt_editor, "load-finished",
G_CALLBACK (set_preformatted_block_format_on_load_finished_cb), html_editor, 0);
diff --git a/src/mail/em-composer-utils.c b/src/mail/em-composer-utils.c
index cf55c3c955..ebd6df7a26 100644
--- a/src/mail/em-composer-utils.c
+++ b/src/mail/em-composer-utils.c
@@ -553,6 +553,7 @@ composer_presend_check_unwanted_html (EMsgComposer *composer,
EDestination **recipients;
EHTMLEditor *editor;
EComposerHeaderTable *table;
+ EContentEditorMode mode;
GSettings *settings;
gboolean check_passed = TRUE;
gboolean html_mode;
@@ -563,12 +564,14 @@ composer_presend_check_unwanted_html (EMsgComposer *composer,
settings = e_util_ref_settings ("org.gnome.evolution.mail");
editor = e_msg_composer_get_editor (composer);
- html_mode = e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_HTML;
+ mode = e_html_editor_get_mode (editor);
+ html_mode = mode == E_CONTENT_EDITOR_MODE_HTML || mode == E_CONTENT_EDITOR_MODE_MARKDOWN_HTML;
table = e_msg_composer_get_header_table (composer);
recipients = e_composer_header_table_get_destinations (table);
- send_html = g_settings_get_boolean (settings, "composer-send-html");
+ mode = g_settings_get_enum (settings, "composer-mode");
+ send_html = mode == E_CONTENT_EDITOR_MODE_HTML || mode == E_CONTENT_EDITOR_MODE_MARKDOWN_HTML;
confirm_html = g_settings_get_boolean (settings, "prompt-on-unwanted-html");
/* Only show this warning if our default is to send html. If it
@@ -4108,7 +4111,8 @@ em_utils_reply_alternative (GtkWindow *parent,
GtkRadioButton *recip_sender, *recip_list, *recip_all;
GtkLabel *sender_label, *list_label, *all_label;
GtkRadioButton *style_default, *style_attach, *style_inline, *style_quote, *style_no_quote;
- GtkToggleButton *html_format;
+ EActionComboBox *mode_combo;
+ GtkRadioAction *radio_action, *html_mode_radio_action;
GtkToggleButton *bottom_posting;
GtkToggleButton *top_signature;
GtkCheckButton *apply_template;
@@ -4224,8 +4228,21 @@ em_utils_reply_alternative (GtkWindow *parent,
widget = gtk_label_new (" ");
gtk_box_pack_start (vbox, widget, FALSE, FALSE, 0);
- html_format = GTK_TOGGLE_BUTTON (gtk_check_button_new_with_mnemonic (_("_Format message in HTML")));
- gtk_box_pack_start (vbox, GTK_WIDGET (html_format), FALSE, FALSE, 0);
+ hbox = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6));
+ gtk_box_pack_start (vbox, GTK_WIDGET (hbox), FALSE, FALSE, 0);
+
+ /* Translators: The text is followed by the format combo with values like 'Plain Text', 'HTML' and so
on */
+ widget = gtk_label_new_with_mnemonic (_("_Format message in"));
+ gtk_box_pack_start (hbox, widget, FALSE, FALSE, 0);
+
+ mode_combo = e_html_editor_util_new_mode_combobox ();
+ gtk_label_set_mnemonic_widget (GTK_LABEL (widget), GTK_WIDGET (mode_combo));
+ gtk_box_pack_start (hbox, GTK_WIDGET (mode_combo), FALSE, FALSE, 0);
+
+ html_mode_radio_action = e_action_combo_box_get_action (mode_combo);
+ radio_action = gtk_radio_action_new ("unknown", _("Use global setting"), NULL, NULL,
E_CONTENT_EDITOR_MODE_UNKNOWN);
+ gtk_radio_action_join_group (radio_action, html_mode_radio_action);
+ e_action_combo_box_update_model (mode_combo);
bottom_posting = GTK_TOGGLE_BUTTON (gtk_check_button_new_with_mnemonic (_("Start _typing at the
bottom")));
gtk_box_pack_start (vbox, GTK_WIDGET (bottom_posting), FALSE, FALSE, 0);
@@ -4364,7 +4381,7 @@ em_utils_reply_alternative (GtkWindow *parent,
break;
}
- emcu_three_state_set_value (html_format, g_settings_get_enum (settings, "alt-reply-html-format"));
+ e_action_combo_box_set_current_value (mode_combo, g_settings_get_enum (settings,
"alt-reply-format-mode"));
emcu_three_state_set_value (bottom_posting, g_settings_get_enum (settings, "alt-reply-start-bottom"));
emcu_three_state_set_value (top_signature, g_settings_get_enum (settings, "alt-reply-top-signature"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (apply_template), g_settings_get_boolean (settings,
"alt-reply-template-apply"));
@@ -4373,7 +4390,6 @@ em_utils_reply_alternative (GtkWindow *parent,
if (!gtk_widget_get_sensitive (GTK_WIDGET (templates)))
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (apply_template), FALSE);
- emcu_connect_three_state_changer (html_format);
emcu_connect_three_state_changer (bottom_posting);
emcu_connect_three_state_changer (top_signature);
@@ -4432,6 +4448,7 @@ em_utils_reply_alternative (GtkWindow *parent,
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
GtkTreeIter iter;
AltReplyContext *context;
+ EContentEditorMode mode;
EThreeState three_state;
CamelFolder *template_folder = NULL;
gchar *template_message_uid = NULL;
@@ -4459,13 +4476,28 @@ em_utils_reply_alternative (GtkWindow *parent,
else
context->flags = context->flags & (~E_MAIL_REPLY_FLAG_FORCE_STYLE);
- three_state = emcu_three_state_get_value (html_format);
- g_settings_set_enum (settings, "alt-reply-html-format", three_state);
+ mode = e_action_combo_box_get_current_value (mode_combo);
+ g_settings_set_enum (settings, "alt-reply-format-mode", mode);
- if (three_state == E_THREE_STATE_ON)
- context->flags |= E_MAIL_REPLY_FLAG_FORMAT_HTML;
- else if (three_state == E_THREE_STATE_OFF)
+ switch (mode) {
+ case E_CONTENT_EDITOR_MODE_UNKNOWN:
+ break;
+ case E_CONTENT_EDITOR_MODE_PLAIN_TEXT:
context->flags |= E_MAIL_REPLY_FLAG_FORMAT_PLAIN;
+ break;
+ case E_CONTENT_EDITOR_MODE_HTML:
+ context->flags |= E_MAIL_REPLY_FLAG_FORMAT_HTML;
+ break;
+ case E_CONTENT_EDITOR_MODE_MARKDOWN:
+ context->flags |= E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN;
+ break;
+ case E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT:
+ context->flags |= E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_PLAIN;
+ break;
+ case E_CONTENT_EDITOR_MODE_MARKDOWN_HTML:
+ context->flags |= E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_HTML;
+ break;
+ }
three_state = emcu_three_state_get_value (bottom_posting);
g_settings_set_enum (settings, "alt-reply-start-bottom", three_state);
@@ -4595,9 +4627,34 @@ em_utils_reply_to_message (EMsgComposer *composer,
cnt_editor = e_html_editor_get_content_editor (e_msg_composer_get_editor (composer));
- if ((reply_flags & (E_MAIL_REPLY_FLAG_FORMAT_PLAIN | E_MAIL_REPLY_FLAG_FORMAT_HTML)) != 0) {
- e_html_editor_set_mode (e_msg_composer_get_editor (composer),
- (reply_flags & E_MAIL_REPLY_FLAG_FORMAT_HTML) != 0 ? E_CONTENT_EDITOR_MODE_HTML :
E_CONTENT_EDITOR_MODE_PLAIN_TEXT);
+ flags = reply_flags & (E_MAIL_REPLY_FLAG_FORMAT_PLAIN |
+ E_MAIL_REPLY_FLAG_FORMAT_HTML |
+ E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN |
+ E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_PLAIN |
+ E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_HTML);
+ if (flags != 0) {
+ EContentEditorMode mode = E_CONTENT_EDITOR_MODE_UNKNOWN;
+
+ switch (flags) {
+ case E_MAIL_REPLY_FLAG_FORMAT_PLAIN:
+ mode = E_CONTENT_EDITOR_MODE_PLAIN_TEXT;
+ break;
+ case E_MAIL_REPLY_FLAG_FORMAT_HTML:
+ mode = E_CONTENT_EDITOR_MODE_HTML;
+ break;
+ case E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN:
+ mode = E_CONTENT_EDITOR_MODE_MARKDOWN;
+ break;
+ case E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_PLAIN:
+ mode = E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT;
+ break;
+ case E_MAIL_REPLY_FLAG_FORMAT_MARKDOWN_HTML:
+ mode = E_CONTENT_EDITOR_MODE_MARKDOWN_HTML;
+ break;
+ }
+
+ if (mode != E_CONTENT_EDITOR_MODE_UNKNOWN)
+ e_html_editor_set_mode (e_msg_composer_get_editor (composer), mode);
}
em_utils_update_by_reply_flags (cnt_editor, reply_flags);
diff --git a/src/mail/mail-config.ui b/src/mail/mail-config.ui
index 890837162a..646909865b 100644
--- a/src/mail/mail-config.ui
+++ b/src/mail/mail-config.ui
@@ -211,14 +211,26 @@
<property name="can_focus">False</property>
<property name="spacing">8</property>
<child>
- <object class="GtkCheckButton" id="chkSendHTML">
- <property name="label" translatable="yes">For_mat messages in HTML</property>
+ <object class="GtkBox" id="hboxSendMode">
+ <property name="orientation">horizontal</property>
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="xalign">0.5</property>
- <property name="draw_indicator">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="lblSendMode">
+ <property name="label" translatable="yes" comments="Translators: The text is
followed by the format combo with values like 'Plain Text', 'HTML' and so on">For_mat messages in</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="use_underline">True</property>
+ <property name="justify">center</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>
diff --git a/src/modules/composer-to-meeting/e-meeting-to-composer.c
b/src/modules/composer-to-meeting/e-meeting-to-composer.c
index 4c8a1e363d..63437521d7 100644
--- a/src/modules/composer-to-meeting/e-meeting-to-composer.c
+++ b/src/modules/composer-to-meeting/e-meeting-to-composer.c
@@ -298,11 +298,22 @@ meeting_to_composer_composer_created_cb (GObject *source_object,
if (text && *text) {
EHTMLEditor *html_editor;
EContentEditor *cnt_editor;
+ EContentEditorMode mode;
+ GSettings *settings;
+
+ settings = e_util_ref_settings ("org.gnome.evolution.mail");
+ mode = g_settings_get_enum (settings, "composer-mode");
+ g_clear_object (&settings);
+
+ /* Let the markdown be allowed, otherwise use the plain text mode */
+ if (mode != E_CONTENT_EDITOR_MODE_MARKDOWN &&
+ mode != E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT)
+ mode = E_CONTENT_EDITOR_MODE_PLAIN_TEXT;
html_editor = e_msg_composer_get_editor (composer);
cnt_editor = e_html_editor_get_content_editor (html_editor);
- e_html_editor_set_mode (html_editor, E_CONTENT_EDITOR_MODE_PLAIN_TEXT);
+ e_html_editor_set_mode (html_editor, mode);
e_content_editor_insert_content (cnt_editor, text,
E_CONTENT_EDITOR_INSERT_REPLACE_ALL | E_CONTENT_EDITOR_INSERT_TEXT_PLAIN);
}
diff --git a/src/modules/mail/e-mail-shell-backend.c b/src/modules/mail/e-mail-shell-backend.c
index 049a6fd536..2e393baa2e 100644
--- a/src/modules/mail/e-mail-shell-backend.c
+++ b/src/modules/mail/e-mail-shell-backend.c
@@ -759,19 +759,20 @@ mail_shell_backend_window_added_cb (GtkApplication *application,
/* This applies to both the composer and signature editor. */
if (editor != NULL) {
EContentEditor *cnt_editor;
+ EContentEditorMode mode;
GSettings *settings;
- gboolean use_html, use_preformatted;
+ gboolean use_preformatted;
cnt_editor = e_html_editor_get_content_editor (editor);
settings = e_util_ref_settings ("org.gnome.evolution.mail");
- use_html = g_settings_get_boolean (settings, "composer-send-html");
+ mode = g_settings_get_enum (settings, "composer-mode");
use_preformatted = g_settings_get_boolean (settings,
"composer-plain-text-starts-preformatted");
g_object_unref (settings);
- e_html_editor_set_mode (editor, use_html ? E_CONTENT_EDITOR_MODE_HTML :
E_CONTENT_EDITOR_MODE_PLAIN_TEXT);
+ e_html_editor_set_mode (editor, mode);
if (use_preformatted) {
g_signal_connect_object (cnt_editor, "load-finished",
diff --git a/src/modules/mail/em-composer-prefs.c b/src/modules/mail/em-composer-prefs.c
index 721c07e6e2..24b6734a80 100644
--- a/src/modules/mail/em-composer-prefs.c
+++ b/src/modules/mail/em-composer-prefs.c
@@ -1056,6 +1056,45 @@ emcp_free (EConfig *ec,
g_slist_free (items);
}
+static gboolean
+emcp_composer_mode_to_current_value_cb (GValue *value,
+ GVariant *variant,
+ gpointer user_data)
+{
+ const gchar *str;
+ gint mode = E_CONTENT_EDITOR_MODE_UNKNOWN;
+
+ str = g_variant_get_string (variant, NULL);
+
+ if (!e_enum_from_string (E_TYPE_CONTENT_EDITOR_MODE, str, &mode))
+ mode = E_CONTENT_EDITOR_MODE_UNKNOWN;
+
+ if (mode == E_CONTENT_EDITOR_MODE_UNKNOWN)
+ mode = E_CONTENT_EDITOR_MODE_PLAIN_TEXT;
+
+ g_value_set_int (value, mode);
+
+ return TRUE;
+}
+
+static GVariant *
+emcp_current_value_to_composer_mode_cb (const GValue *value,
+ const GVariantType *expected_type,
+ gpointer user_data)
+{
+ const gchar *str;
+ gint mode;
+
+ mode = g_value_get_int (value);
+
+ str = e_enum_to_string (E_TYPE_CONTENT_EDITOR_MODE, mode);
+
+ if (!str)
+ str = e_enum_to_string (E_TYPE_CONTENT_EDITOR_MODE, E_CONTENT_EDITOR_MODE_PLAIN_TEXT);
+
+ return g_variant_new_string (str);
+}
+
static void
em_composer_prefs_construct (EMComposerPrefs *prefs,
EShell *shell)
@@ -1063,7 +1102,9 @@ em_composer_prefs_construct (EMComposerPrefs *prefs,
GtkWidget *toplevel, *widget, *info_pixmap;
GtkWidget *container;
GSettings *settings;
+ EActionComboBox *action_combo_box;
ESourceRegistry *registry;
+ GtkRadioAction *radio_action;
GtkTreeView *view;
GtkListStore *store;
GtkTreeSelection *selection;
@@ -1106,11 +1147,21 @@ em_composer_prefs_construct (EMComposerPrefs *prefs,
/* Default Behavior */
- widget = e_builder_get_widget (prefs->builder, "chkSendHTML");
- g_settings_bind (
- settings, "composer-send-html",
- widget, "active",
- G_SETTINGS_BIND_DEFAULT);
+ container = e_builder_get_widget (prefs->builder, "hboxSendMode");
+ action_combo_box = e_html_editor_util_new_mode_combobox ();
+ widget = GTK_WIDGET (action_combo_box);
+ gtk_widget_show (widget);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ widget = e_builder_get_widget (prefs->builder, "lblSendMode");
+ gtk_label_set_mnemonic_widget (GTK_LABEL (widget), GTK_WIDGET (action_combo_box));
+ radio_action = e_action_combo_box_get_action (action_combo_box);
+ g_settings_bind_with_mapping (
+ settings, "composer-mode",
+ radio_action, "current-value",
+ G_SETTINGS_BIND_DEFAULT,
+ emcp_composer_mode_to_current_value_cb,
+ emcp_current_value_to_composer_mode_cb,
+ NULL, NULL);
widget = e_builder_get_widget (prefs->builder, "chkInheritThemeColors");
g_settings_bind (
@@ -1359,8 +1410,8 @@ em_composer_prefs_construct (EMComposerPrefs *prefs,
G_CALLBACK (gtk_application_add_window), shell);
g_settings_bind (
- settings, "composer-send-html",
- widget, "prefer-html",
+ settings, "composer-mode",
+ widget, "prefer-mode",
G_SETTINGS_BIND_GET);
/* Send Account override */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]