739 lines
20 KiB
C
739 lines
20 KiB
C
/*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "evolution-config.h"
|
|
|
|
#include <string.h>
|
|
#include <gtk/gtk.h>
|
|
#include <glib/gi18n.h>
|
|
|
|
#include <em-format/e-mail-extension-registry.h>
|
|
#include <em-format/e-mail-parser-extension.h>
|
|
#include <em-format/e-mail-part.h>
|
|
#include <em-format/e-mail-part-utils.h>
|
|
|
|
#include <libebackend/libebackend.h>
|
|
#include <e-util/e-util.h>
|
|
|
|
#include "e-mail-parser-prefer-plain.h"
|
|
|
|
typedef struct _EMailParserPreferPlain EMailParserPreferPlain;
|
|
typedef struct _EMailParserPreferPlainClass EMailParserPreferPlainClass;
|
|
|
|
struct _EMailParserPreferPlain {
|
|
EMailParserExtension parent;
|
|
|
|
GSettings *settings;
|
|
gint mode;
|
|
gboolean show_suppressed;
|
|
};
|
|
|
|
struct _EMailParserPreferPlainClass {
|
|
EMailParserExtensionClass parent_class;
|
|
};
|
|
|
|
GType e_mail_parser_prefer_plain_get_type (void);
|
|
|
|
enum {
|
|
PREFER_HTML,
|
|
PREFER_PLAIN,
|
|
PREFER_SOURCE,
|
|
ONLY_PLAIN
|
|
};
|
|
|
|
G_DEFINE_DYNAMIC_TYPE (EMailParserPreferPlain, e_mail_parser_prefer_plain, E_TYPE_MAIL_PARSER_EXTENSION)
|
|
|
|
static const gchar *parser_mime_types[] = {
|
|
"multipart/alternative",
|
|
"text/html",
|
|
NULL
|
|
};
|
|
|
|
static struct {
|
|
const gchar *key;
|
|
const gchar *label;
|
|
const gchar *description;
|
|
} epp_options[] = {
|
|
{ "normal",
|
|
N_("Show HTML if present"),
|
|
N_("Let Evolution choose the best part to show.") },
|
|
|
|
{ "prefer_plain",
|
|
N_("Show plain text if present"),
|
|
N_("Show plain text part, if present, otherwise "
|
|
"let Evolution choose the best part to show.") },
|
|
|
|
{ "prefer_source",
|
|
N_("Show plain text if present, or HTML source"),
|
|
N_("Show plain text part, if present, otherwise "
|
|
"the HTML part source.") },
|
|
|
|
{ "only_plain",
|
|
N_("Only ever show plain text"),
|
|
N_("Always show plain text part and make attachments "
|
|
"from other parts, if requested.") },
|
|
};
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_MODE,
|
|
PROP_SHOW_SUPPRESSED
|
|
};
|
|
|
|
static void
|
|
mark_parts_not_printable (GQueue *parts)
|
|
{
|
|
GList *link;
|
|
|
|
for (link = g_queue_peek_head_link (parts); link; link = g_list_next (link)) {
|
|
EMailPart *part = link->data;
|
|
|
|
if (part)
|
|
e_mail_part_set_is_printable (part, FALSE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
make_part_attachment (EMailParser *parser,
|
|
CamelMimePart *part,
|
|
GString *part_id,
|
|
gboolean force_html,
|
|
GCancellable *cancellable,
|
|
GQueue *out_mail_parts)
|
|
{
|
|
CamelContentType *ct;
|
|
|
|
ct = camel_mime_part_get_content_type (part);
|
|
|
|
if (camel_content_type_is (ct, "text", "html")) {
|
|
GQueue work_queue = G_QUEUE_INIT;
|
|
EMailPart *mail_part;
|
|
gboolean was_attachment;
|
|
gint len;
|
|
|
|
was_attachment = e_mail_part_is_attachment (part);
|
|
|
|
/* always show HTML as attachments and not inline */
|
|
camel_mime_part_set_disposition (part, "attachment");
|
|
|
|
if (camel_mime_part_get_filename (part) == NULL) {
|
|
gchar *filename;
|
|
|
|
filename = g_strdup_printf ("%s.html", _("attachment"));
|
|
camel_mime_part_set_filename (part, filename);
|
|
g_free (filename);
|
|
}
|
|
|
|
len = part_id->len;
|
|
g_string_append (part_id, ".text_html");
|
|
mail_part = e_mail_part_new (part, part_id->str);
|
|
e_mail_part_set_mime_type (mail_part, "text/html");
|
|
g_string_truncate (part_id, len);
|
|
|
|
g_queue_push_tail (&work_queue, mail_part);
|
|
|
|
e_mail_parser_wrap_as_attachment (
|
|
parser, part, part_id, &work_queue);
|
|
|
|
if (!was_attachment && !force_html)
|
|
mark_parts_not_printable (&work_queue);
|
|
|
|
e_queue_transfer (&work_queue, out_mail_parts);
|
|
|
|
} else if (force_html && CAMEL_IS_MIME_MESSAGE (part)) {
|
|
/* Note, the message was asked to be formatted as
|
|
* text/html; but the message may already be text/html. */
|
|
CamelMimePart *new_part;
|
|
CamelDataWrapper *content;
|
|
|
|
content = camel_medium_get_content (CAMEL_MEDIUM (part));
|
|
g_return_if_fail (content != NULL);
|
|
|
|
new_part = camel_mime_part_new ();
|
|
camel_medium_set_content (CAMEL_MEDIUM (new_part), content);
|
|
|
|
e_mail_parser_parse_part (
|
|
parser, new_part, part_id,
|
|
cancellable, out_mail_parts);
|
|
|
|
g_object_unref (new_part);
|
|
} else {
|
|
e_mail_parser_parse_part (
|
|
parser, part, part_id, cancellable, out_mail_parts);
|
|
}
|
|
}
|
|
|
|
static void
|
|
hide_parts (GQueue *work_queue)
|
|
{
|
|
GList *head, *link;
|
|
|
|
head = g_queue_peek_head_link (work_queue);
|
|
|
|
for (link = head; link != NULL; link = g_list_next (link)) {
|
|
EMailPart *mail_part = link->data;
|
|
|
|
if (!e_mail_part_get_is_attachment (mail_part))
|
|
mail_part->is_hidden = TRUE;
|
|
}
|
|
}
|
|
|
|
static gchar *
|
|
mail_parser_prefer_plain_dup_part_text (CamelMimePart *mime_part,
|
|
GCancellable *cancellable)
|
|
{
|
|
CamelDataWrapper *data_wrapper;
|
|
CamelMedium *medium;
|
|
CamelStream *stream;
|
|
GByteArray *array;
|
|
gchar *content;
|
|
|
|
if (!mime_part)
|
|
return NULL;
|
|
|
|
array = g_byte_array_new ();
|
|
medium = CAMEL_MEDIUM (mime_part);
|
|
|
|
/* Stream takes ownership of the byte array. */
|
|
stream = camel_stream_mem_new_with_byte_array (array);
|
|
data_wrapper = camel_medium_get_content (medium);
|
|
camel_data_wrapper_decode_to_stream_sync (
|
|
data_wrapper, stream, NULL, NULL);
|
|
|
|
content = g_strndup ((gchar *) array->data, array->len);
|
|
|
|
g_object_unref (stream);
|
|
|
|
return content;
|
|
}
|
|
|
|
typedef struct _AsyncContext {
|
|
gchar *text_input;
|
|
gchar *text_output;
|
|
GCancellable *cancellable;
|
|
EFlag *flag;
|
|
WebKitWebView *web_view;
|
|
} AsyncContext;
|
|
|
|
static void
|
|
mail_parser_prefer_plain_convert_jsc_call_done_cb (GObject *source,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
WebKitJavascriptResult *js_result;
|
|
AsyncContext *async_context = user_data;
|
|
GError *error = NULL;
|
|
|
|
g_return_if_fail (async_context != NULL);
|
|
|
|
js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (source), result, &error);
|
|
|
|
if (error) {
|
|
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
|
|
(!g_error_matches (error, WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED) ||
|
|
/* WebKit can return empty error message, thus ignore those. */
|
|
(error->message && *(error->message))))
|
|
g_warning ("%s: JSC call failed: %s:%d: %s", G_STRFUNC, g_quark_to_string (error->domain), error->code, error->message);
|
|
g_clear_error (&error);
|
|
}
|
|
|
|
if (js_result) {
|
|
JSCException *exception;
|
|
JSCValue *value;
|
|
|
|
value = webkit_javascript_result_get_js_value (js_result);
|
|
exception = jsc_context_get_exception (jsc_value_get_context (value));
|
|
|
|
if (exception) {
|
|
g_warning ("%s: JSC call failed: %s", G_STRFUNC, jsc_exception_get_message (exception));
|
|
jsc_context_clear_exception (jsc_value_get_context (value));
|
|
} else if (jsc_value_is_string (value)) {
|
|
async_context->text_output = jsc_value_to_string (value);
|
|
}
|
|
|
|
webkit_javascript_result_unref (js_result);
|
|
}
|
|
|
|
g_clear_object (&async_context->web_view);
|
|
|
|
e_flag_set (async_context->flag);
|
|
}
|
|
|
|
static gboolean
|
|
mail_parser_prefer_plain_convert_text (gpointer user_data)
|
|
{
|
|
AsyncContext *async_context = user_data;
|
|
gchar *script;
|
|
|
|
g_return_val_if_fail (async_context != NULL, FALSE);
|
|
|
|
async_context->web_view = WEBKIT_WEB_VIEW (g_object_ref_sink (e_web_view_new ()));
|
|
|
|
e_web_view_load_uri (E_WEB_VIEW (async_context->web_view), "evo://disable-remote-content");
|
|
|
|
script = e_web_view_jsc_printf_script (
|
|
"var elem;\n"
|
|
"elem = document.createElement('X-EVO-CONVERT');\n"
|
|
"elem.innerHTML = %s;\n"
|
|
"EvoConvert.ToPlainText(elem, -1);",
|
|
async_context->text_input);
|
|
|
|
webkit_web_view_run_javascript (async_context->web_view, script, async_context->cancellable,
|
|
mail_parser_prefer_plain_convert_jsc_call_done_cb, async_context);
|
|
|
|
g_free (script);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gchar *
|
|
mail_parser_prefer_plain_convert_content_sync (CamelMimePart *mime_part,
|
|
GCancellable *cancellable)
|
|
{
|
|
AsyncContext async_context;
|
|
gchar *res = NULL;
|
|
|
|
memset (&async_context, 0, sizeof (AsyncContext));
|
|
|
|
async_context.text_input = mail_parser_prefer_plain_dup_part_text (mime_part, cancellable);
|
|
|
|
if (!async_context.text_input || g_cancellable_is_cancelled (cancellable)) {
|
|
g_free (async_context.text_input);
|
|
return NULL;
|
|
}
|
|
|
|
async_context.flag = e_flag_new ();
|
|
async_context.cancellable = cancellable;
|
|
|
|
/* Run it in the main/GUI thread */
|
|
g_timeout_add (1, mail_parser_prefer_plain_convert_text, &async_context);
|
|
|
|
e_flag_wait (async_context.flag);
|
|
e_flag_free (async_context.flag);
|
|
|
|
if (async_context.text_output) {
|
|
res = async_context.text_output;
|
|
async_context.text_output = NULL;
|
|
}
|
|
|
|
g_free (async_context.text_input);
|
|
g_free (async_context.text_output);
|
|
|
|
return res;
|
|
}
|
|
|
|
static gboolean
|
|
empe_prefer_plain_parse (EMailParserExtension *extension,
|
|
EMailParser *parser,
|
|
CamelMimePart *part,
|
|
GString *part_id,
|
|
GCancellable *cancellable,
|
|
GQueue *out_mail_parts)
|
|
{
|
|
EMailParserPreferPlain *emp_pp;
|
|
CamelMultipart *mp;
|
|
gint i, nparts, partidlen;
|
|
CamelContentType *ct;
|
|
gboolean has_calendar = FALSE;
|
|
gboolean has_html = FALSE;
|
|
gboolean prefer_html;
|
|
GQueue plain_text_parts = G_QUEUE_INIT;
|
|
GQueue work_queue = G_QUEUE_INIT;
|
|
GQueue attachments_queue = G_QUEUE_INIT;
|
|
|
|
emp_pp = (EMailParserPreferPlain *) extension;
|
|
prefer_html = (emp_pp->mode == PREFER_HTML);
|
|
|
|
ct = camel_mime_part_get_content_type (part);
|
|
|
|
/* We can actually parse HTML, but just discard it
|
|
* when "Only ever show plain text" mode is set. */
|
|
if (camel_content_type_is (ct, "text", "html")) {
|
|
|
|
/* Prevent recursion, fall back to next (real text/html) parser */
|
|
if (strstr (part_id->str, ".alternative-prefer-plain.") != NULL)
|
|
return FALSE;
|
|
|
|
if (emp_pp->mode == PREFER_SOURCE && !e_mail_part_is_attachment (part)) {
|
|
EMailPart *mail_part;
|
|
|
|
partidlen = part_id->len;
|
|
|
|
g_string_truncate (part_id, partidlen);
|
|
g_string_append_printf (part_id, ".alternative-prefer-plain.%d", -1);
|
|
|
|
mail_part = e_mail_part_new (part, part_id->str);
|
|
e_mail_part_set_mime_type (mail_part, "application/vnd.evolution.plaintext");
|
|
|
|
g_string_truncate (part_id, partidlen);
|
|
|
|
g_queue_push_tail (out_mail_parts, mail_part);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Not enforcing text/plain, so use real parser. */
|
|
if (emp_pp->mode != ONLY_PLAIN)
|
|
return FALSE;
|
|
|
|
/* The convert schedules a timeout GSource on the main thread and waits for an EFlag,
|
|
which causes a deadlock of the main thread. This can happen when opening a message
|
|
in the composer. Skip the plugin in this case. */
|
|
if (e_util_is_main_thread (NULL))
|
|
return FALSE;
|
|
|
|
if (!e_mail_part_is_attachment (part)) {
|
|
gchar *content;
|
|
|
|
partidlen = part_id->len;
|
|
|
|
g_string_truncate (part_id, partidlen);
|
|
g_string_append_printf (part_id, ".alternative-prefer-plain.%d.converted", -1);
|
|
|
|
content = mail_parser_prefer_plain_convert_content_sync (part, cancellable);
|
|
|
|
if (content) {
|
|
EMailPart *mail_part;
|
|
CamelMimePart *text_part;
|
|
|
|
text_part = camel_mime_part_new ();
|
|
camel_mime_part_set_content (text_part, content, strlen (content), "application/vnd.evolution.plaintext");
|
|
mail_part = e_mail_part_new (text_part, part_id->str);
|
|
e_mail_part_set_mime_type (mail_part, "application/vnd.evolution.plaintext");
|
|
g_free (content);
|
|
|
|
g_queue_push_tail (out_mail_parts, mail_part);
|
|
}
|
|
|
|
g_string_truncate (part_id, partidlen);
|
|
}
|
|
|
|
if (emp_pp->show_suppressed || e_mail_part_is_attachment (part)) {
|
|
/* Enforcing text/plain but got only HTML part, so add it
|
|
* as attachment to not show empty message preview, which
|
|
* is confusing. */
|
|
make_part_attachment (
|
|
parser, part, part_id, TRUE,
|
|
cancellable, out_mail_parts);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
partidlen = part_id->len;
|
|
|
|
mp = (CamelMultipart *) camel_medium_get_content (CAMEL_MEDIUM (part));
|
|
|
|
if (!CAMEL_IS_MULTIPART (mp))
|
|
return e_mail_parser_parse_part_as (
|
|
parser, part, part_id,
|
|
"application/vnd.evolution.source",
|
|
cancellable, out_mail_parts);
|
|
|
|
nparts = camel_multipart_get_number (mp);
|
|
for (i = 0; i < nparts; i++) {
|
|
CamelMimePart *sp;
|
|
|
|
sp = camel_multipart_get_part (mp, i);
|
|
ct = camel_mime_part_get_content_type (sp);
|
|
|
|
g_string_truncate (part_id, partidlen);
|
|
g_string_append_printf (part_id, ".alternative-prefer-plain.%d", i);
|
|
|
|
if (camel_content_type_is (ct, "text", "html")) {
|
|
if (prefer_html) {
|
|
e_mail_parser_parse_part (
|
|
parser, sp, part_id,
|
|
cancellable, &work_queue);
|
|
} else if (emp_pp->show_suppressed) {
|
|
make_part_attachment (
|
|
parser, sp, part_id, FALSE,
|
|
cancellable, &work_queue);
|
|
}
|
|
|
|
has_html = TRUE;
|
|
|
|
} else if (camel_content_type_is (ct, "text", "plain")) {
|
|
e_mail_parser_parse_part (
|
|
parser, sp, part_id,
|
|
cancellable, &plain_text_parts);
|
|
|
|
/* Always show calendar part! */
|
|
} else if (camel_content_type_is (ct, "text", "calendar") ||
|
|
camel_content_type_is (ct, "text", "x-calendar")) {
|
|
|
|
/* Hide everything else, displaying
|
|
* native calendar part only. */
|
|
hide_parts (&work_queue);
|
|
|
|
e_mail_parser_parse_part (
|
|
parser, sp, part_id, cancellable, &work_queue);
|
|
|
|
has_calendar = TRUE;
|
|
|
|
/* Multiparts can represent a text/html message
|
|
* with other things like embedded images, etc. */
|
|
} else if (camel_content_type_is (ct, "multipart", "*")) {
|
|
GQueue inner_queue = G_QUEUE_INIT;
|
|
GList *head, *link;
|
|
gboolean multipart_has_html = FALSE;
|
|
|
|
e_mail_parser_parse_part (
|
|
parser, sp, part_id, cancellable, &inner_queue);
|
|
|
|
head = g_queue_peek_head_link (&inner_queue);
|
|
|
|
/* Check whether the multipart contains a text/html part */
|
|
for (link = head; link != NULL; link = g_list_next (link)) {
|
|
EMailPart *mail_part = link->data;
|
|
|
|
if (e_mail_part_id_has_substr (mail_part, ".text_html")) {
|
|
multipart_has_html = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (multipart_has_html && !prefer_html) {
|
|
if (emp_pp->show_suppressed) {
|
|
GQueue suppressed_queue = G_QUEUE_INIT;
|
|
|
|
e_mail_parser_wrap_as_attachment (
|
|
parser, sp, part_id,
|
|
&suppressed_queue);
|
|
|
|
mark_parts_not_printable (&suppressed_queue);
|
|
|
|
e_queue_transfer (&suppressed_queue, &inner_queue);
|
|
} else {
|
|
hide_parts (&inner_queue);
|
|
}
|
|
}
|
|
|
|
e_queue_transfer (&inner_queue, &work_queue);
|
|
|
|
has_html |= multipart_has_html;
|
|
|
|
/* Parse other than 'X' (those are custom types) as an attachment */
|
|
} else if (ct && ct->subtype && ct->subtype[0] && ct->subtype[0] != 'x' && ct->subtype[0] != 'X') {
|
|
e_mail_parser_parse_part (
|
|
parser, sp, part_id,
|
|
cancellable, &attachments_queue);
|
|
e_mail_parser_wrap_as_attachment (
|
|
parser, sp, part_id, &attachments_queue);
|
|
}
|
|
}
|
|
|
|
/* Don't hide the plain text if there's nothing else to display */
|
|
if (has_calendar || (has_html && prefer_html))
|
|
hide_parts (&plain_text_parts);
|
|
|
|
if (!g_queue_is_empty (&plain_text_parts) && !g_queue_is_empty (&work_queue) && has_html) {
|
|
/* a text/html part is hidden, but not marked as attachment,
|
|
* thus do that now, when there exists a text/plain part */
|
|
GList *qiter;
|
|
|
|
for (qiter = g_queue_peek_head_link (&work_queue); qiter; qiter = g_list_next (qiter)) {
|
|
EMailPart *mpart = qiter->data;
|
|
const gchar *mime_type;
|
|
|
|
mime_type = e_mail_part_get_mime_type (mpart);
|
|
|
|
if (mpart && mpart->is_hidden && g_strcmp0 (mime_type, "text/html") == 0) {
|
|
e_mail_part_set_is_attachment (mpart, TRUE);
|
|
e_mail_part_set_is_printable (mpart, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* plain_text parts should be always first */
|
|
e_queue_transfer (&plain_text_parts, out_mail_parts);
|
|
e_queue_transfer (&work_queue, out_mail_parts);
|
|
e_queue_transfer (&attachments_queue, out_mail_parts);
|
|
|
|
g_string_truncate (part_id, partidlen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
e_mail_parser_prefer_plain_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
EMailParserPreferPlain *parser;
|
|
|
|
parser = (EMailParserPreferPlain *) object;
|
|
|
|
switch (property_id) {
|
|
case PROP_MODE:
|
|
g_value_set_int (value, parser->mode);
|
|
return;
|
|
case PROP_SHOW_SUPPRESSED:
|
|
g_value_set_boolean (value, parser->show_suppressed);
|
|
return;
|
|
}
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
}
|
|
|
|
static void
|
|
e_mail_parser_prefer_plain_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
EMailParserPreferPlain *parser;
|
|
|
|
parser = (EMailParserPreferPlain *) object;
|
|
|
|
switch (property_id) {
|
|
case PROP_MODE:
|
|
parser->mode = g_value_get_int (value);
|
|
return;
|
|
case PROP_SHOW_SUPPRESSED:
|
|
parser->show_suppressed = g_value_get_boolean (value);
|
|
return;
|
|
}
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
}
|
|
|
|
static void
|
|
e_mail_parser_prefer_plain_dispose (GObject *object)
|
|
{
|
|
EMailParserPreferPlain *parser;
|
|
|
|
parser = (EMailParserPreferPlain *) object;
|
|
|
|
g_clear_object (&parser->settings);
|
|
|
|
/* Chain up to parent's dispose() method. */
|
|
G_OBJECT_CLASS (e_mail_parser_prefer_plain_parent_class)->
|
|
dispose (object);
|
|
}
|
|
|
|
static void
|
|
e_mail_parser_prefer_plain_class_init (EMailParserPreferPlainClass *class)
|
|
{
|
|
GObjectClass *object_class;
|
|
EMailParserExtensionClass *extension_class;
|
|
|
|
object_class = G_OBJECT_CLASS (class);
|
|
object_class->get_property = e_mail_parser_prefer_plain_get_property;
|
|
object_class->set_property = e_mail_parser_prefer_plain_set_property;
|
|
object_class->dispose = e_mail_parser_prefer_plain_dispose;
|
|
|
|
extension_class = E_MAIL_PARSER_EXTENSION_CLASS (class);
|
|
extension_class->mime_types = parser_mime_types;
|
|
extension_class->parse = empe_prefer_plain_parse;
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_MODE,
|
|
g_param_spec_int (
|
|
"mode",
|
|
"Mode",
|
|
NULL,
|
|
PREFER_HTML,
|
|
ONLY_PLAIN,
|
|
PREFER_HTML,
|
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_SHOW_SUPPRESSED,
|
|
g_param_spec_boolean (
|
|
"show-suppressed",
|
|
"Show Suppressed",
|
|
NULL,
|
|
FALSE,
|
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|
}
|
|
|
|
void
|
|
e_mail_parser_prefer_plain_class_finalize (EMailParserPreferPlainClass *class)
|
|
{
|
|
}
|
|
|
|
static gboolean
|
|
parser_mode_get_mapping (GValue *value,
|
|
GVariant *variant,
|
|
gpointer user_data)
|
|
{
|
|
gint i;
|
|
|
|
const gchar *key = g_variant_get_string (variant, NULL);
|
|
if (key) {
|
|
for (i = 0; i < G_N_ELEMENTS (epp_options); i++) {
|
|
if (!strcmp (epp_options[i].key, key)) {
|
|
g_value_set_int (value, i);
|
|
return TRUE;
|
|
}
|
|
}
|
|
} else {
|
|
g_value_set_int (value, 0);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static GVariant *
|
|
parser_mode_set_mapping (const GValue *value,
|
|
const GVariantType *expected_type,
|
|
gpointer user_data)
|
|
{
|
|
return g_variant_new_string (epp_options[g_value_get_int (value)].key);
|
|
}
|
|
|
|
static void
|
|
e_mail_parser_prefer_plain_init (EMailParserPreferPlain *parser)
|
|
{
|
|
gchar *key;
|
|
gint i;
|
|
|
|
parser->settings = e_util_ref_settings ("org.gnome.evolution.plugin.prefer-plain");
|
|
g_settings_bind_with_mapping (
|
|
parser->settings, "mode",
|
|
parser, "mode", G_SETTINGS_BIND_DEFAULT,
|
|
parser_mode_get_mapping,
|
|
parser_mode_set_mapping,
|
|
NULL, NULL);
|
|
g_settings_bind (
|
|
parser->settings, "show-suppressed",
|
|
parser, "show-suppressed", G_SETTINGS_BIND_DEFAULT);
|
|
|
|
/* Initialize the settings */
|
|
key = g_settings_get_string (parser->settings, "mode");
|
|
if (key) {
|
|
for (i = 0; i < G_N_ELEMENTS (epp_options); i++) {
|
|
if (!strcmp (epp_options[i].key, key)) {
|
|
parser->mode = i;
|
|
break;
|
|
}
|
|
}
|
|
g_free (key);
|
|
} else {
|
|
parser->mode = 0;
|
|
}
|
|
|
|
parser->show_suppressed = g_settings_get_boolean (parser->settings, "show-suppressed");
|
|
}
|
|
|
|
void
|
|
e_mail_parser_prefer_plain_type_register (GTypeModule *type_module)
|
|
{
|
|
e_mail_parser_prefer_plain_register_type (type_module);
|
|
}
|