[evolution/449-support-markdown-in-composer] Composer: Read/write markdown format



commit 03c370dadbafb9a4dffe2a9d7557ba79dad0476c
Author: Milan Crha <mcrha redhat com>
Date:   Tue Feb 8 17:32:53 2022 +0100

    Composer: Read/write markdown format

 src/composer/e-msg-composer.c  | 255 ++++++++++++++++++++++++++++++-----------
 src/e-util/e-html-editor.c     |  20 +++-
 src/e-util/e-markdown-editor.c |  55 ++++++++-
 src/e-util/e-markdown-editor.h |   3 +
 4 files changed, 253 insertions(+), 80 deletions(-)
---
diff --git a/src/composer/e-msg-composer.c b/src/composer/e-msg-composer.c
index 97cbdfd933..b8ba281d1e 100644
--- a/src/composer/e-msg-composer.c
+++ b/src/composer/e-msg-composer.c
@@ -86,8 +86,7 @@ typedef enum {
        COMPOSER_FLAG_PGP_ENCRYPT               = 1 << 5,
        COMPOSER_FLAG_SMIME_SIGN                = 1 << 6,
        COMPOSER_FLAG_SMIME_ENCRYPT             = 1 << 7,
-       COMPOSER_FLAG_HTML_MODE                 = 1 << 8,
-       COMPOSER_FLAG_SAVE_DRAFT                = 1 << 9
+       COMPOSER_FLAG_SAVE_DRAFT                = 1 << 8
 } ComposerFlags;
 
 enum {
@@ -217,7 +216,7 @@ e_msg_composer_dec_soft_busy (EMsgComposer *composer)
                g_object_notify (G_OBJECT (composer), "soft-busy");
 }
 
-/**
+/*
  * emcu_part_to_html:
  * @part:
  *
@@ -227,7 +226,7 @@ e_msg_composer_dec_soft_busy (EMsgComposer *composer)
  * will be performed.
  *
  * Return Value: The part in displayable html format.
- **/
+ */
 static gchar *
 emcu_part_to_html (EMsgComposer *composer,
                    CamelMimePart *part,
@@ -306,6 +305,45 @@ emcu_part_to_html (EMsgComposer *composer,
        return text;
 }
 
+static gchar *
+emcu_part_as_text (EMsgComposer *composer,
+                   CamelMimePart *part,
+                   gssize *out_len,
+                   GCancellable *cancellable)
+{
+       CamelDataWrapper *dw;
+       gchar *text;
+       gssize length;
+
+       dw = camel_medium_get_content (CAMEL_MEDIUM (part));
+       if (dw) {
+               CamelStream *mem = camel_stream_mem_new ();
+               GByteArray *bytes;
+
+               camel_data_wrapper_decode_to_stream_sync (dw, mem, cancellable, NULL);
+               camel_stream_close (mem, cancellable, NULL);
+
+               bytes = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (mem));
+               if (bytes && bytes->len) {
+                       text = g_strndup ((const gchar *) bytes->data, bytes->len);
+                       length = bytes->len;
+               } else {
+                       text = g_strdup ("");
+                       length = 0;
+               }
+
+               g_object_unref (mem);
+       } else {
+               text = g_strdup ("");
+               length = 0;
+       }
+
+       if (out_len)
+               *out_len = length;
+
+       return text;
+}
+
 static EDestination **
 destination_list_to_vector_sized (GList *list,
                                   gint n)
@@ -1203,41 +1241,45 @@ composer_build_message_thread (GSimpleAsyncResult *simple,
 #endif /* ENABLE_SMIME */
 }
 
-static void
-composer_add_evolution_composer_mode_header (CamelMedium *medium,
-                                             EMsgComposer *composer)
+static const gchar *
+composer_get_editor_mode_format_text (EContentEditorMode mode)
 {
-       EHTMLEditor *editor;
-       const gchar *mode = "text/plain";
-
-       editor = e_msg_composer_get_editor (composer);
-       switch (e_html_editor_get_mode (editor)) {
+       switch (mode) {
        case E_CONTENT_EDITOR_MODE_UNKNOWN:
                g_warn_if_reached ();
                break;
        case E_CONTENT_EDITOR_MODE_PLAIN_TEXT:
-               mode = "text/plain";
-               break;
+               return "text/plain";
        case E_CONTENT_EDITOR_MODE_HTML:
-               mode = "text/html";
-               break;
+               return "text/html";
        case E_CONTENT_EDITOR_MODE_MARKDOWN:
-               mode = "text/markdown";
-               break;
+               return "text/markdown";
        case E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT:
-               mode = "text/markdown-plain";
-               break;
+               return "text/markdown-plain";
        case E_CONTENT_EDITOR_MODE_MARKDOWN_HTML:
-               mode = "text/markdown-html";
-               break;
+               return "text/markdown-html";
        }
 
+       return "text/plain";
+}
+
+static void
+composer_add_evolution_composer_mode_header (CamelMedium *medium,
+                                             EMsgComposer *composer)
+{
+       EHTMLEditor *editor;
+       const gchar *mode;
+
+       editor = e_msg_composer_get_editor (composer);
+       mode = composer_get_editor_mode_format_text (e_html_editor_get_mode (editor));
+
        camel_medium_add_header (medium, "X-Evolution-Composer-Mode", mode);
 }
 
 static void
 composer_add_evolution_format_header (CamelMedium *medium,
-                                      ComposerFlags flags)
+                                     ComposerFlags flags,
+                                     EContentEditorMode mode)
 {
        GString *string;
 
@@ -1474,7 +1516,10 @@ composer_build_message (EMsgComposer *composer,
                if (!g_str_has_suffix (text, "\r\n") && !g_str_has_suffix (text, "\n"))
                        g_byte_array_append (data, (const guint8 *) "\r\n", 2);
 
-               type = camel_content_type_new ("text", "plain");
+               if (e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_MARKDOWN)
+                       type = camel_content_type_new ("text", "markdown");
+               else
+                       type = camel_content_type_new ("text", "plain");
                charset = best_charset (
                        data, priv->charset, &context->plain_encoding);
                if (charset != NULL) {
@@ -1482,6 +1527,12 @@ composer_build_message (EMsgComposer *composer,
                        iconv_charset = camel_iconv_charset_name (charset);
                        g_free (charset);
                }
+
+               if ((flags & COMPOSER_FLAG_SAVE_DRAFT) == 0 && (
+                   e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_MARKDOWN ||
+                   e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT ||
+                   e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_MARKDOWN_HTML))
+                       composer_add_evolution_composer_mode_header (CAMEL_MEDIUM (context->message), 
composer);
        }
 
        mem_stream = camel_stream_mem_new_with_byte_array (data);
@@ -1541,7 +1592,7 @@ composer_build_message (EMsgComposer *composer,
                if ((flags & COMPOSER_FLAG_SAVE_DRAFT) != 0) {
                        /* X-Evolution-Format */
                        composer_add_evolution_format_header (
-                               CAMEL_MEDIUM (context->message), flags);
+                               CAMEL_MEDIUM (context->message), flags, e_html_editor_get_mode 
(composer->priv->editor));
 
                        /* X-Evolution-Composer-Mode */
                        composer_add_evolution_composer_mode_header (
@@ -2730,7 +2781,7 @@ msg_composer_map (GtkWidget *widget)
 
        /* Jump to the editor as a last resort. */
        cnt_editor = e_html_editor_get_content_editor (editor);
-       gtk_widget_grab_focus (GTK_WIDGET (cnt_editor));
+       e_content_editor_grab_focus (cnt_editor);
 }
 
 static gboolean
@@ -3426,6 +3477,23 @@ e_msg_composer_check_inline_attachments (EMsgComposer *composer)
        }
 }
 
+static gboolean
+emcu_format_as_plain_text (EMsgComposer *composer,
+                          CamelContentType *content_type)
+{
+       EContentEditorMode mode;
+
+       if (!camel_content_type_is (content_type, "text", "plain") &&
+           !camel_content_type_is (content_type, "text", "markdown"))
+               return FALSE;
+
+       mode = e_html_editor_get_mode (e_msg_composer_get_editor (composer));
+
+       return mode == E_CONTENT_EDITOR_MODE_MARKDOWN ||
+               mode == E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT ||
+               mode == E_CONTENT_EDITOR_MODE_MARKDOWN_HTML;
+}
+
 static void
 handle_multipart_signed (EMsgComposer *composer,
                          CamelMultipart *multipart,
@@ -3502,7 +3570,14 @@ handle_multipart_signed (EMsgComposer *composer,
                        handle_multipart (
                                composer, multipart, parent_part, keep_signature, cancellable, depth);
                }
+       } else if (camel_content_type_is (content_type, "text", "markdown") ||
+                  emcu_format_as_plain_text (composer, content_type)) {
+               gchar *text;
+               gssize length;
 
+               text = emcu_part_as_text (composer, mime_part, &length, cancellable);
+               if (text)
+                       e_msg_composer_set_pending_body (composer, text, length, FALSE);
        } else if (camel_content_type_is (content_type, "text", "*")) {
                gchar *html;
                gssize length;
@@ -3605,6 +3680,14 @@ handle_multipart_encrypted (EMsgComposer *composer,
                                composer, content_multipart, multipart, keep_signature, cancellable, depth);
                }
 
+       } else if (camel_content_type_is (content_type, "text", "markdown") ||
+                  emcu_format_as_plain_text (composer, content_type)) {
+               gchar *text;
+               gssize length;
+
+               text = emcu_part_as_text (composer, mime_part, &length, cancellable);
+               if (text)
+                       e_msg_composer_set_pending_body (composer, text, length, FALSE);
        } else if (camel_content_type_is (content_type, "text", "*")) {
                gchar *html;
                gssize length;
@@ -3677,6 +3760,17 @@ handle_multipart_alternative (EMsgComposer *composer,
                        /* text/html is preferable, so once we find it we're done... */
                        text_part = mime_part;
                        break;
+               } else if (camel_content_type_is (content_type, "text", "markdown") ||
+                          emcu_format_as_plain_text (composer, content_type)) {
+                       gchar *text;
+                       gssize length;
+
+                       text = emcu_part_as_text (composer, mime_part, &length, cancellable);
+                       if (text) {
+                               e_msg_composer_set_pending_body (composer, text, length, FALSE);
+                               text_part = NULL;
+                               break;
+                       }
                } else if (camel_content_type_is (content_type, "text", "*")) {
                        /* anyt text part not text/html is second rate so the first
                         * text part we find isn't necessarily the one we'll use. */
@@ -3696,11 +3790,33 @@ handle_multipart_alternative (EMsgComposer *composer,
                gchar *html;
                gssize length;
 
-               html = emcu_part_to_html (
-                       composer, text_part, &length, keep_signature, cancellable);
-               if (!html && fallback_text_part)
-                       html = emcu_part_to_html (
-                               composer, fallback_text_part, &length, keep_signature, cancellable);
+               if (emcu_format_as_plain_text (composer, camel_mime_part_get_content_type (text_part))) {
+                       gchar *text;
+                       gssize length;
+
+                       text = emcu_part_as_text (composer, text_part, &length, cancellable);
+                       if (text) {
+                               e_msg_composer_set_pending_body (composer, text, length, FALSE);
+                               return;
+                       }
+               }
+
+               html = emcu_part_to_html (composer, text_part, &length, keep_signature, cancellable);
+               if (!html && fallback_text_part) {
+                       if (emcu_format_as_plain_text (composer, camel_mime_part_get_content_type 
(fallback_text_part))) {
+                               gchar *text;
+                               gssize length;
+
+                               text = emcu_part_as_text (composer, fallback_text_part, &length, cancellable);
+                               if (text) {
+                                       e_msg_composer_set_pending_body (composer, text, length, FALSE);
+                                       return;
+                               }
+                       }
+
+                       html = emcu_part_to_html (composer, fallback_text_part, &length, keep_signature, 
cancellable);
+               }
+
                if (html)
                        e_msg_composer_set_pending_body (composer, html, length, TRUE);
        }
@@ -3762,15 +3878,26 @@ handle_multipart (EMsgComposer *composer,
                        }
 
                } else if (depth == 0 && i == 0) {
-                       gchar *html = NULL;
-                       gssize length = 0;
-
                        /* Since the first part is not multipart/alternative,
                         * this must be the body. */
-                       html = emcu_part_to_html (
-                               composer, mime_part, &length, keep_signature, cancellable);
 
-                       e_msg_composer_set_pending_body (composer, html, length, TRUE);
+                       if (camel_content_type_is (content_type, "text", "markdown") ||
+                           emcu_format_as_plain_text (composer, content_type)) {
+                               gchar *text;
+                               gssize length;
+
+                               text = emcu_part_as_text (composer, mime_part, &length, cancellable);
+                               if (text)
+                                       e_msg_composer_set_pending_body (composer, text, length, FALSE);
+                       } else {
+                               gchar *html = NULL;
+                               gssize length = 0;
+
+                               html = emcu_part_to_html (
+                                       composer, mime_part, &length, keep_signature, cancellable);
+
+                               e_msg_composer_set_pending_body (composer, html, length, TRUE);
+                       }
 
                } else if (camel_content_type_is (content_type, "image", "*") && (
                           camel_mime_part_get_content_id (mime_part) ||
@@ -4122,7 +4249,7 @@ e_msg_composer_setup_with_message (EMsgComposer *composer,
        composer_mode = camel_medium_get_header (
                CAMEL_MEDIUM (message), "X-Evolution-Composer-Mode");
 
-       if (composer_mode && *composer_mode)
+       if (format && *format && composer_mode && *composer_mode)
                is_message_from_draft = TRUE;
 
        if (format != NULL) {
@@ -4168,6 +4295,21 @@ e_msg_composer_setup_with_message (EMsgComposer *composer,
                        }
                }
                g_strfreev (flags);
+       } else if (composer_mode != NULL) {
+               EContentEditorMode mode = E_CONTENT_EDITOR_MODE_HTML;
+
+               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;
+
+               e_html_editor_set_mode (editor, mode);
        }
 
        if (is_message_from_draft || (
@@ -4278,7 +4420,6 @@ e_msg_composer_setup_with_message (EMsgComposer *composer,
                /* If we are opening message from Drafts */
                if (is_message_from_draft) {
                        /* Extract the body */
-                       CamelDataWrapper *dw;
 
                        #ifdef ENABLE_SMIME
                        if (is_smime_encrypted) {
@@ -4307,28 +4448,11 @@ e_msg_composer_setup_with_message (EMsgComposer *composer,
                        }
                        #endif
 
-                       dw = camel_medium_get_content ((CamelMedium *) mime_part);
-                       if (dw) {
-                               CamelStream *mem = camel_stream_mem_new ();
-                               GByteArray *bytes;
-
-                               camel_data_wrapper_decode_to_stream_sync (dw, mem, cancellable, NULL);
-                               camel_stream_close (mem, cancellable, NULL);
-
-                               bytes = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (mem));
-                               if (bytes && bytes->len) {
-                                       html = g_strndup ((const gchar *) bytes->data, bytes->len);
-                                       length = bytes->len;
-                               } else {
-                                       html = g_strdup ("");
-                                       length = 0;
-                               }
-
-                               g_object_unref (mem);
-                       } else {
-                               html = g_strdup ("");
-                               length = 0;
-                       }
+                       html = emcu_part_as_text (composer, mime_part, &length, cancellable);
+               } else if (camel_content_type_is (content_type, "text", "markdown") ||
+                          emcu_format_as_plain_text (composer, content_type)) {
+                       is_html = FALSE;
+                       html = emcu_part_as_text (composer, CAMEL_MIME_PART (message), &length, cancellable);
                } else {
                        is_html = TRUE;
                        html = emcu_part_to_html (
@@ -5911,7 +6035,8 @@ e_msg_composer_get_message (EMsgComposer *composer,
 
        g_simple_async_result_set_check_cancellable (simple, cancellable);
 
-       if (e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_HTML)
+       if (e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_HTML ||
+           e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_MARKDOWN_HTML)
                flags |= COMPOSER_FLAG_HTML_CONTENT;
 
        action = ACTION (PRIORITIZE_MESSAGE);
@@ -6022,7 +6147,6 @@ e_msg_composer_get_message_draft (EMsgComposer *composer,
                                   GAsyncReadyCallback callback,
                                   gpointer user_data)
 {
-       EHTMLEditor *editor;
        GSimpleAsyncResult *simple;
        ComposerFlags flags = COMPOSER_FLAG_SAVE_DRAFT;
        GtkAction *action;
@@ -6035,11 +6159,6 @@ e_msg_composer_get_message_draft (EMsgComposer *composer,
 
        g_simple_async_result_set_check_cancellable (simple, cancellable);
 
-       editor = e_msg_composer_get_editor (composer);
-
-       /* We need to remember composer mode */
-       if (e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_HTML)
-               flags |= COMPOSER_FLAG_HTML_MODE;
        /* We want to save HTML content everytime when we save as draft */
        flags |= COMPOSER_FLAG_SAVE_DRAFT;
 
diff --git a/src/e-util/e-html-editor.c b/src/e-util/e-html-editor.c
index 7ce754f2df..fa10bc9eba 100644
--- a/src/e-util/e-html-editor.c
+++ b/src/e-util/e-html-editor.c
@@ -1718,18 +1718,26 @@ e_html_editor_set_mode (EHTMLEditor *editor,
                        if (editor->priv->use_content_editor) {
                                is_focused = e_content_editor_is_focus (editor->priv->use_content_editor);
 
-                               e_content_editor_get_content (editor->priv->use_content_editor,
-                                       E_CONTENT_EDITOR_GET_TO_SEND_HTML | 
E_CONTENT_EDITOR_GET_TO_SEND_PLAIN,
-                                       "localhost", NULL,
-                                       e_html_editor_update_content_on_mode_change_cb,
-                                       e_weak_ref_new (editor));
+                               if (gtk_widget_get_realized (GTK_WIDGET (editor->priv->use_content_editor))) {
+                                       /* Transfer also the content between editors */
+                                       e_content_editor_get_content (editor->priv->use_content_editor,
+                                               E_CONTENT_EDITOR_GET_TO_SEND_HTML | 
E_CONTENT_EDITOR_GET_TO_SEND_PLAIN,
+                                               "localhost", NULL,
+                                               e_html_editor_update_content_on_mode_change_cb,
+                                               e_weak_ref_new (editor));
+                               }
 
                                gtk_widget_hide (GTK_WIDGET (editor->priv->use_content_editor));
 
                                if (E_IS_MARKDOWN_EDITOR (editor->priv->use_content_editor)) {
+                                       EMarkdownEditor *markdown_editor;
                                        GtkToolbar *toolbar;
 
-                                       toolbar = e_markdown_editor_get_action_toolbar (E_MARKDOWN_EDITOR 
(editor->priv->use_content_editor));
+                                       markdown_editor = E_MARKDOWN_EDITOR 
(editor->priv->use_content_editor);
+
+                                       e_markdown_editor_set_preview_mode (markdown_editor, FALSE);
+
+                                       toolbar = e_markdown_editor_get_action_toolbar (markdown_editor);
                                        gtk_container_remove (GTK_CONTAINER (toolbar), GTK_WIDGET 
(editor->priv->mode_tool_item));
 
                                        toolbar = GTK_TOOLBAR (editor->priv->edit_toolbar);
diff --git a/src/e-util/e-markdown-editor.c b/src/e-util/e-markdown-editor.c
index 4126000bb0..29a2b80718 100644
--- a/src/e-util/e-markdown-editor.c
+++ b/src/e-util/e-markdown-editor.c
@@ -21,6 +21,7 @@
 #include "e-markdown-editor.h"
 
 struct _EMarkdownEditorPrivate {
+       GtkNotebook *notebook;
        GtkTextView *text_view;
        EWebView *web_view;
        GtkToolbar *action_toolbar;
@@ -1305,7 +1306,6 @@ e_markdown_editor_constructed (GObject *object)
 {
        EMarkdownEditor *self = E_MARKDOWN_EDITOR (object);
        GtkWidget *widget;
-       GtkNotebook *notebook;
        GtkScrolledWindow *scrolled_window;
        guint ii;
 
@@ -1324,7 +1324,7 @@ e_markdown_editor_constructed (GObject *object)
                NULL);
        gtk_box_pack_start (GTK_BOX (self), widget, TRUE, TRUE, 0);
 
-       notebook = GTK_NOTEBOOK (widget);
+       self->priv->notebook = GTK_NOTEBOOK (widget);
 
        widget = gtk_scrolled_window_new (NULL, NULL);
        g_object_set (G_OBJECT (widget),
@@ -1337,7 +1337,7 @@ e_markdown_editor_constructed (GObject *object)
                "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
                NULL);
 
-       gtk_notebook_append_page (notebook, widget, gtk_label_new_with_mnemonic (_("_Write")));
+       gtk_notebook_append_page (self->priv->notebook, widget, gtk_label_new_with_mnemonic (_("_Write")));
 
        scrolled_window = GTK_SCROLLED_WINDOW (widget);
 
@@ -1372,7 +1372,7 @@ e_markdown_editor_constructed (GObject *object)
                "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
                NULL);
 
-       gtk_notebook_append_page (notebook, widget, gtk_label_new_with_mnemonic (_("_Preview")));
+       gtk_notebook_append_page (self->priv->notebook, widget, gtk_label_new_with_mnemonic (_("_Preview")));
 
        scrolled_window = GTK_SCROLLED_WINDOW (widget);
 
@@ -1394,7 +1394,7 @@ e_markdown_editor_constructed (GObject *object)
        widget = gtk_toolbar_new ();
        gtk_toolbar_set_icon_size (GTK_TOOLBAR (widget), GTK_ICON_SIZE_SMALL_TOOLBAR);
        gtk_widget_show (widget);
-       gtk_notebook_set_action_widget (notebook, widget, GTK_PACK_END);
+       gtk_notebook_set_action_widget (self->priv->notebook, widget, GTK_PACK_END);
 
        self->priv->action_toolbar = GTK_TOOLBAR (widget);
        self->priv->is_dark_theme = e_markdown_editor_is_dark_theme (self);
@@ -1422,7 +1422,7 @@ e_markdown_editor_constructed (GObject *object)
        }
 
        #ifdef HAVE_MARKDOWN
-       g_signal_connect_object (notebook, "switch-page", G_CALLBACK (e_markdown_editor_switch_page_cb), 
self, 0);
+       g_signal_connect_object (self->priv->notebook, "switch-page", G_CALLBACK 
(e_markdown_editor_switch_page_cb), self, 0);
        #endif
 
        g_signal_connect (self, "style-updated", G_CALLBACK (e_markdown_editor_style_updated_cb), NULL);
@@ -1692,3 +1692,46 @@ e_markdown_editor_dup_html (EMarkdownEditor *self)
        return NULL;
        #endif
 }
+
+/**
+ * e_markdown_editor_get_preview_mode:
+ * @self: an #EMarkdownEditor
+ *
+ * Returns: whether the @self is in the preview mode; %FALSE means
+ *    it is in the editing mode
+ *
+ * Since: 3.44
+ **/
+gboolean
+e_markdown_editor_get_preview_mode (EMarkdownEditor *self)
+{
+       g_return_val_if_fail (E_IS_MARKDOWN_EDITOR (self), FALSE);
+
+       return gtk_notebook_get_current_page (self->priv->notebook) == 1;
+}
+
+/**
+ * e_markdown_editor_set_preview_mode:
+ * @self: an #EMarkdownEditor
+ * @preview_mode: %TRUE to set the preview mode, %FALSE otherwise
+ *
+ * Sets the @self into the preview mode, when @preview_mode is %TRUE, or
+ * into editing mode, when @preview_mode is %FALSE.
+ *
+ * Note: The request to move to the preview mode can be silently ignored
+ *    when the Evolution was not built with the markdown support.
+ *
+ * Since: 3.44
+ **/
+void
+e_markdown_editor_set_preview_mode (EMarkdownEditor *self,
+                                   gboolean preview_mode)
+{
+       g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+
+       #ifdef HAVE_MARKDOWN
+       gtk_notebook_set_current_page (self->priv->notebook, preview_mode ? 1 : 0);
+       #else
+       gtk_notebook_set_current_page (self->priv->notebook, 0);
+       #endif
+}
diff --git a/src/e-util/e-markdown-editor.h b/src/e-util/e-markdown-editor.h
index c42959a36d..c8cc59bc5b 100644
--- a/src/e-util/e-markdown-editor.h
+++ b/src/e-util/e-markdown-editor.h
@@ -59,6 +59,9 @@ void          e_markdown_editor_set_text              (EMarkdownEditor *self,
                                                         const gchar *text);
 gchar *                e_markdown_editor_dup_text              (EMarkdownEditor *self);
 gchar *                e_markdown_editor_dup_html              (EMarkdownEditor *self);
+gboolean       e_markdown_editor_get_preview_mode      (EMarkdownEditor *self);
+void           e_markdown_editor_set_preview_mode      (EMarkdownEditor *self,
+                                                        gboolean preview_mode);
 
 G_END_DECLS
 


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