[evolution] I#1512 - Choose account with which to forward message in filter rule
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] I#1512 - Choose account with which to forward message in filter rule
- Date: Fri, 11 Jun 2021 09:47:09 +0000 (UTC)
commit 70b7d478732269fbabc4b9c6852eddeac627c128
Author: Milan Crha <mcrha redhat com>
Date: Fri Jun 11 11:46:27 2021 +0200
I#1512 - Choose account with which to forward message in filter rule
Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/1512
.../evolution-util/evolution-util-docs.sgml.in | 5 +
po/POTFILES.in | 1 +
src/e-util/CMakeLists.txt | 2 +
src/e-util/e-filter-label.c | 211 +++++++++++++
src/e-util/e-filter-label.h | 69 ++++
src/e-util/e-mail-identity-combo-box.c | 46 ++-
src/e-util/e-mail-identity-combo-box.h | 5 +
src/e-util/e-rule-context.c | 5 +-
src/e-util/e-util.h | 1 +
src/libemail-engine/e-mail-session.c | 74 ++++-
src/mail/CMakeLists.txt | 2 +
src/mail/em-filter-context.c | 8 +-
src/mail/em-filter-mail-identity-element.c | 350 +++++++++++++++++++++
src/mail/em-filter-mail-identity-element.h | 65 ++++
src/mail/filtertypes.xml.in | 6 +-
15 files changed, 841 insertions(+), 9 deletions(-)
---
diff --git a/docs/reference/evolution-util/evolution-util-docs.sgml.in
b/docs/reference/evolution-util/evolution-util-docs.sgml.in
index 20623f090b..d530b8a08c 100644
--- a/docs/reference/evolution-util/evolution-util-docs.sgml.in
+++ b/docs/reference/evolution-util/evolution-util-docs.sgml.in
@@ -87,6 +87,7 @@
<xi:include href="xml/e-filter-file.xml"/>
<xi:include href="xml/e-filter-input.xml"/>
<xi:include href="xml/e-filter-int.xml"/>
+ <xi:include href="xml/e-filter-label.xml"/>
<xi:include href="xml/e-filter-option.xml"/>
</chapter>
@@ -323,6 +324,10 @@
<title>Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
+ <index id="api-index-3-42" role="3.42">
+ <title>Index of new symbols in 3.42</title>
+ <xi:include href="xml/api-index-3.42.xml"><xi:fallback /></xi:include>
+ </index>
<index id="api-index-3-40" role="3.40">
<title>Index of new symbols in 3.40</title>
<xi:include href="xml/api-index-3.40.xml"><xi:fallback /></xi:include>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 546f5876ef..1eb44ae079 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -357,6 +357,7 @@ src/mail/e-mail-ui-session.c
src/mail/em-composer-utils.c
src/mail/em-filter-editor.c
src/mail/em-filter-editor-folder-element.c
+src/mail/em-filter-mail-identity-element.c
src/mail/em-filter-rule.c
src/mail/em-folder-properties.c
src/mail/em-folder-selection-button.c
diff --git a/src/e-util/CMakeLists.txt b/src/e-util/CMakeLists.txt
index f31f678ff8..03b60d8e4b 100644
--- a/src/e-util/CMakeLists.txt
+++ b/src/e-util/CMakeLists.txt
@@ -129,6 +129,7 @@ set(SOURCES
e-filter-file.c
e-filter-input.c
e-filter-int.c
+ e-filter-label.c
e-filter-option.c
e-filter-part.c
e-filter-rule.c
@@ -404,6 +405,7 @@ set(HEADERS
e-filter-file.h
e-filter-input.h
e-filter-int.h
+ e-filter-label.h
e-filter-option.h
e-filter-part.h
e-filter-rule.h
diff --git a/src/e-util/e-filter-label.c b/src/e-util/e-filter-label.c
new file mode 100644
index 0000000000..f6bfcefdd4
--- /dev/null
+++ b/src/e-util/e-filter-label.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2021 Red Hat (www.redhat.com)
+ *
+ * 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-lib.h>
+
+#include "e-filter-part.h"
+
+#include "e-filter-label.h"
+
+struct _EFilterLabelPrivate {
+ gchar *title;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (EFilterLabel, e_filter_label, E_TYPE_FILTER_ELEMENT)
+
+static void
+filter_label_finalize (GObject *object)
+{
+ EFilterLabel *label = E_FILTER_LABEL (object);
+
+ g_free (label->priv->title);
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (e_filter_label_parent_class)->finalize (object);
+}
+
+static gint
+filter_label_eq (EFilterElement *element_a,
+ EFilterElement *element_b)
+{
+ EFilterLabel *label_a = E_FILTER_LABEL (element_a);
+ EFilterLabel *label_b = E_FILTER_LABEL (element_b);
+
+ /* Chain up to parent's method. */
+ if (!E_FILTER_ELEMENT_CLASS (e_filter_label_parent_class)->eq (element_a, element_b))
+ return FALSE;
+
+ return g_strcmp0 (label_a->priv->title, label_b->priv->title) == 0;
+}
+
+static void
+filter_label_xml_create (EFilterElement *element,
+ xmlNodePtr node)
+{
+ EFilterLabel *label = E_FILTER_LABEL (element);
+ xmlNodePtr n;
+
+ /* Chain up to parent's method. */
+ E_FILTER_ELEMENT_CLASS (e_filter_label_parent_class)->xml_create (element, node);
+
+ n = node->children;
+ while (n) {
+ if (!g_strcmp0 ((gchar *) n->name, "title") ||
+ !g_strcmp0 ((gchar *) n->name, "_title")) {
+ if (!label->priv->title) {
+ xmlChar *tmp;
+
+ tmp = xmlNodeGetContent (n);
+ label->priv->title = tmp ? g_strdup ((gchar *) tmp) : NULL;
+ if (tmp)
+ xmlFree (tmp);
+ }
+ } else if (n->type == XML_ELEMENT_NODE) {
+ g_warning ("Unknown xml node within 'label': %s\n", n->name);
+ }
+ n = n->next;
+ }
+}
+
+static xmlNodePtr
+filter_label_xml_encode (EFilterElement *element)
+{
+ xmlNodePtr value;
+
+ value = xmlNewNode (NULL, (xmlChar *) "value");
+ xmlSetProp (value, (xmlChar *) "name", (xmlChar *) element->name);
+
+ return value;
+}
+
+static gint
+filter_label_xml_decode (EFilterElement *element,
+ xmlNodePtr node)
+{
+ xmlFree (element->name);
+ element->name = (gchar *) xmlGetProp (node, (xmlChar *) "name");
+
+ return 0;
+}
+
+static EFilterElement *
+filter_label_clone (EFilterElement *element)
+{
+ EFilterLabel *label = E_FILTER_LABEL (element);
+ EFilterLabel *clone_label;
+ EFilterElement *clone;
+
+ /* Chain up to parent's method. */
+ clone = E_FILTER_ELEMENT_CLASS (e_filter_label_parent_class)->clone (element);
+
+ clone_label = E_FILTER_LABEL (clone);
+ clone_label->priv->title = g_strdup (label->priv->title);
+
+ return clone;
+}
+
+static GtkWidget *
+filter_label_get_widget (EFilterElement *element)
+{
+ EFilterLabel *label = E_FILTER_LABEL (element);
+ GtkWidget *widget;
+
+ widget = gtk_label_new ((label->priv->title && *label->priv->title) ? _(label->priv->title) : "");
+
+ return widget;
+}
+
+static void
+filter_label_build_code (EFilterElement *element,
+ GString *out,
+ EFilterPart *part)
+{
+}
+
+static void
+filter_label_format_sexp (EFilterElement *element,
+ GString *out)
+{
+}
+
+static void
+filter_label_describe (EFilterElement *element,
+ GString *out)
+{
+ EFilterLabel *label = E_FILTER_LABEL (element);
+
+ if (label->priv->title && *label->priv->title)
+ g_string_append (out, _(label->priv->title));
+}
+
+static void
+e_filter_label_class_init (EFilterLabelClass *class)
+{
+ GObjectClass *object_class;
+ EFilterElementClass *filter_element_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = filter_label_finalize;
+
+ filter_element_class = E_FILTER_ELEMENT_CLASS (class);
+ filter_element_class->eq = filter_label_eq;
+ filter_element_class->xml_create = filter_label_xml_create;
+ filter_element_class->xml_encode = filter_label_xml_encode;
+ filter_element_class->xml_decode = filter_label_xml_decode;
+ filter_element_class->clone = filter_label_clone;
+ filter_element_class->get_widget = filter_label_get_widget;
+ filter_element_class->build_code = filter_label_build_code;
+ filter_element_class->format_sexp = filter_label_format_sexp;
+ filter_element_class->describe = filter_label_describe;
+}
+
+static void
+e_filter_label_init (EFilterLabel *label)
+{
+ label->priv = e_filter_label_get_instance_private (label);
+}
+
+EFilterElement *
+e_filter_label_new (void)
+{
+ return g_object_new (E_TYPE_FILTER_LABEL, NULL);
+}
+
+void
+e_filter_label_set_title (EFilterLabel *label,
+ const gchar *title)
+{
+ g_return_if_fail (E_IS_FILTER_LABEL (label));
+
+ if (label->priv->title != title) {
+ g_free (label->priv->title);
+ label->priv->title = g_strdup (title);
+ }
+}
+
+const gchar *
+e_filter_label_get_title (EFilterLabel *label)
+{
+ g_return_val_if_fail (E_IS_FILTER_LABEL (label), NULL);
+
+ return label->priv->title;
+}
diff --git a/src/e-util/e-filter-label.h b/src/e-util/e-filter-label.h
new file mode 100644
index 0000000000..865f041295
--- /dev/null
+++ b/src/e-util/e-filter-label.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 Red Hat (www.redhat.com)
+ *
+ * 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/>.
+ *
+ */
+
+#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION)
+#error "Only <e-util/e-util.h> should be included directly."
+#endif
+
+#ifndef E_FILTER_LABEL_H
+#define E_FILTER_LABEL_H
+
+#include <e-util/e-filter-element.h>
+
+/* Standard GObject macros */
+#define E_TYPE_FILTER_LABEL \
+ (e_filter_label_get_type ())
+#define E_FILTER_LABEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILTER_LABEL, EFilterLabel))
+#define E_FILTER_LABEL_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILTER_LABEL, EFilterLabelClass))
+#define E_IS_FILTER_LABEL(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILTER_LABEL))
+#define E_IS_FILTER_LABEL_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILTER_LABEL))
+#define E_FILTER_LABEL_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILTER_LABEL, EFilterLabelClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EFilterLabel EFilterLabel;
+typedef struct _EFilterLabelClass EFilterLabelClass;
+typedef struct _EFilterLabelPrivate EFilterLabelPrivate;
+
+struct _EFilterLabel {
+ EFilterElement parent;
+ EFilterLabelPrivate *priv;
+};
+
+struct _EFilterLabelClass {
+ EFilterElementClass parent_class;
+};
+
+GType e_filter_label_get_type (void) G_GNUC_CONST;
+EFilterElement *e_filter_label_new (void);
+void e_filter_label_set_title (EFilterLabel *option,
+ const gchar *title);
+const gchar * e_filter_label_get_title (EFilterLabel *option);
+
+G_END_DECLS
+
+#endif /* E_FILTER_LABEL_H */
diff --git a/src/e-util/e-mail-identity-combo-box.c b/src/e-util/e-mail-identity-combo-box.c
index 4bd6bb5ef1..88c78a543f 100644
--- a/src/e-util/e-mail-identity-combo-box.c
+++ b/src/e-util/e-mail-identity-combo-box.c
@@ -45,6 +45,8 @@ struct _EMailIdentityComboBoxPrivate {
gulong source_changed_handler_id;
gulong source_removed_handler_id;
+ gchar *none_title;
+
gboolean allow_none;
gboolean allow_aliases;
@@ -256,6 +258,7 @@ mail_identity_combo_box_dispose (GObject *object)
priv->refresh_idle_id = 0;
}
+ g_clear_pointer (&priv->none_title, g_free);
g_clear_object (&priv->registry);
/* Chain up to parent's dispose() method. */
@@ -691,7 +694,7 @@ e_mail_identity_combo_box_refresh (EMailIdentityComboBox *combo_box)
gtk_list_store_set (
GTK_LIST_STORE (tree_model), &iter,
- E_MAIL_IDENTITY_COMBO_BOX_COLUMN_DISPLAY_NAME, _("None"),
+ E_MAIL_IDENTITY_COMBO_BOX_COLUMN_DISPLAY_NAME,
e_mail_identity_combo_box_get_none_title (combo_box),
E_MAIL_IDENTITY_COMBO_BOX_COLUMN_UID, "",
E_MAIL_IDENTITY_COMBO_BOX_COLUMN_COMBO_ID, "",
-1);
@@ -776,6 +779,47 @@ e_mail_identity_combo_box_set_allow_none (EMailIdentityComboBox *combo_box,
e_mail_identity_combo_box_refresh (combo_box);
}
+/**
+ * e_mail_identity_combo_box_get_none_title:
+ * @combo_box: an #EMailIdentityComboBox
+ *
+ * Returns: what title the none item should have
+ *
+ * Since: 3.42
+ **/
+const gchar *
+e_mail_identity_combo_box_get_none_title (EMailIdentityComboBox *combo_box)
+{
+ g_return_val_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box), NULL);
+
+ if (combo_box->priv->none_title)
+ return combo_box->priv->none_title;
+
+ return _("None");
+}
+
+/**
+ * e_mail_identity_combo_box_set_none_title:
+ * @combo_box: an #EMailIdentityComboBox
+ * @none_title: (nullable): a title to use, or %NULL
+ *
+ * Set what title the none item should have. This is a user visible string, thus
+ * it should be localized. Use %NULL to reset to the default "None" title.
+ *
+ * Since: 3.42
+ **/
+void
+e_mail_identity_combo_box_set_none_title (EMailIdentityComboBox *combo_box,
+ const gchar *none_title)
+{
+ g_return_if_fail (E_IS_MAIL_IDENTITY_COMBO_BOX (combo_box));
+
+ if (combo_box->priv->none_title != none_title) {
+ g_free (combo_box->priv->none_title);
+ combo_box->priv->none_title = g_strdup (none_title);
+ }
+}
+
/**
* e_mail_identity_combo_box_get_allow_aliases:
* @combo_box: an #EMailIdentityComboBox
diff --git a/src/e-util/e-mail-identity-combo-box.h b/src/e-util/e-mail-identity-combo-box.h
index 36d75e6bed..e926190e0b 100644
--- a/src/e-util/e-mail-identity-combo-box.h
+++ b/src/e-util/e-mail-identity-combo-box.h
@@ -87,6 +87,11 @@ gboolean e_mail_identity_combo_box_get_allow_none
void e_mail_identity_combo_box_set_allow_none
(EMailIdentityComboBox *combo_box,
gboolean allow_none);
+const gchar * e_mail_identity_combo_box_get_none_title
+ (EMailIdentityComboBox *combo_box);
+void e_mail_identity_combo_box_set_none_title
+ (EMailIdentityComboBox *combo_box,
+ const gchar *none_title);
gboolean e_mail_identity_combo_box_get_allow_aliases
(EMailIdentityComboBox *combo_box);
void e_mail_identity_combo_box_set_allow_aliases
diff --git a/src/e-util/e-rule-context.c b/src/e-util/e-rule-context.c
index 8d73fcf1f7..4f72f7ad35 100644
--- a/src/e-util/e-rule-context.c
+++ b/src/e-util/e-rule-context.c
@@ -45,6 +45,7 @@
#include "e-filter-file.h"
#include "e-filter-input.h"
#include "e-filter-int.h"
+#include "e-filter-label.h"
#include "e-filter-option.h"
#include "e-filter-rule.h"
#include "e-rule-context.h"
@@ -460,7 +461,9 @@ static EFilterElement *
rule_context_new_element (ERuleContext *context,
const gchar *type)
{
- if (!strcmp (type, "string")) {
+ if (!strcmp (type, "label")) {
+ return (EFilterElement *) e_filter_label_new ();
+ } else if (!strcmp (type, "string")) {
return (EFilterElement *) e_filter_input_new ();
} else if (!strcmp (type, "address")) {
/* FIXME: temporary ... need real address type */
diff --git a/src/e-util/e-util.h b/src/e-util/e-util.h
index d6a50b85d6..c430fed8bd 100644
--- a/src/e-util/e-util.h
+++ b/src/e-util/e-util.h
@@ -114,6 +114,7 @@
#include <e-util/e-filter-file.h>
#include <e-util/e-filter-input.h>
#include <e-util/e-filter-int.h>
+#include <e-util/e-filter-label.h>
#include <e-util/e-filter-option.h>
#include <e-util/e-filter-part.h>
#include <e-util/e-filter-rule.h>
diff --git a/src/libemail-engine/e-mail-session.c b/src/libemail-engine/e-mail-session.c
index 8c7d410fc3..e1dbe548ff 100644
--- a/src/libemail-engine/e-mail-session.c
+++ b/src/libemail-engine/e-mail-session.c
@@ -1523,6 +1523,67 @@ mail_session_forget_password (CamelSession *session,
return TRUE;
}
+/* Expects 'forward_with' encoded as: "identity_uid|alias_name|alias_address" with '\\' and '|' being
backslash-escaped */
+static ESource *
+mail_session_decode_forward_with (ESourceRegistry *registry,
+ const gchar *forward_with,
+ gchar **out_alias_name,
+ gchar **out_alias_address)
+{
+ ESource *source = NULL;
+ GString *str;
+ gint step;
+ const gchar *ptr;
+
+ if (!forward_with || !*forward_with)
+ return NULL;
+
+ str = g_string_sized_new (strlen (forward_with));
+
+ for (step = 0, ptr = forward_with; *ptr; ptr++) {
+ if (*ptr == '\\' && ptr[1]) {
+ g_string_append_c (str, ptr[1]);
+ ptr++;
+ g_string_append_c (str, *ptr);
+ } else if (*ptr == '|') {
+ if (step == 0) { /* identity_uid */
+ source = e_source_registry_ref_source (registry, str->str);
+ if (!source)
+ break;
+ } else if (step == 1) { /* alias_name */
+ if (str->len)
+ *out_alias_name = g_strdup (str->str);
+ } else if (step == 2) { /* alias_address */
+ if (str->len)
+ *out_alias_address = g_strdup (str->str);
+ }
+
+ g_string_truncate (str, 0);
+ step++;
+
+ if (step == 3)
+ break;
+ } else {
+ g_string_append_c (str, *ptr);
+ }
+ }
+
+ /* When the string doesn't end with the '|' */
+ if (step < 3 && str->len) {
+ if (step == 0) { /* identity_uid */
+ source = e_source_registry_ref_source (registry, str->str);
+ } else if (step == 1) { /* alias_name */
+ *out_alias_name = g_strdup (str->str);
+ } else if (step == 2) { /* alias_address */
+ *out_alias_address = g_strdup (str->str);
+ }
+ }
+
+ g_string_free (str, TRUE);
+
+ return source;
+}
+
static gboolean
mail_session_forward_to_sync (CamelSession *session,
CamelFolder *folder,
@@ -1569,9 +1630,16 @@ mail_session_forward_to_sync (CamelSession *session,
registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
- /* This returns a new ESource reference. */
- source = em_utils_guess_mail_identity_with_recipients (
- registry, message, folder, NULL, &alias_name, &alias_address);
+ source = mail_session_decode_forward_with (registry,
+ camel_medium_get_header (CAMEL_MEDIUM (message), "X-Evolution-Forward-With"),
+ &alias_name, &alias_address);
+
+ if (!source) {
+ /* This returns a new ESource reference. */
+ source = em_utils_guess_mail_identity_with_recipients (
+ registry, message, folder, NULL, &alias_name, &alias_address);
+ }
+
if (source == NULL) {
g_set_error (
error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
diff --git a/src/mail/CMakeLists.txt b/src/mail/CMakeLists.txt
index 5d08d13928..0cd0a9a842 100644
--- a/src/mail/CMakeLists.txt
+++ b/src/mail/CMakeLists.txt
@@ -100,6 +100,7 @@ set(SOURCES
em-filter-context.c
em-filter-editor.c
em-filter-editor-folder-element.c
+ em-filter-mail-identity-element.c
em-filter-rule.c
em-filter-source-element.c
em-folder-properties.c
@@ -191,6 +192,7 @@ set(HEADERS
em-filter-context.h
em-filter-editor.h
em-filter-editor-folder-element.h
+ em-filter-mail-identity-element.h
em-filter-rule.h
em-filter-source-element.h
em-folder-properties.h
diff --git a/src/mail/em-filter-context.c b/src/mail/em-filter-context.c
index 445327fd81..cd62dfe721 100644
--- a/src/mail/em-filter-context.c
+++ b/src/mail/em-filter-context.c
@@ -26,10 +26,9 @@
#include "em-filter-context.h"
#include "em-filter-rule.h"
-#include "em-filter-source-element.h"
-
-/* For poking into filter-folder guts */
#include "em-filter-editor-folder-element.h"
+#include "em-filter-mail-identity-element.h"
+#include "em-filter-source-element.h"
#define EM_FILTER_CONTEXT_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -238,6 +237,9 @@ filter_context_new_element (ERuleContext *context,
if (strcmp (type, "source") == 0)
return em_filter_source_element_new (priv->session);
+ if (strcmp (type, "mail-identity") == 0)
+ return em_filter_mail_identity_element_new (e_mail_session_get_registry (priv->session));
+
return E_RULE_CONTEXT_CLASS (em_filter_context_parent_class)->
new_element (context, type);
}
diff --git a/src/mail/em-filter-mail-identity-element.c b/src/mail/em-filter-mail-identity-element.c
new file mode 100644
index 0000000000..3370c7ed79
--- /dev/null
+++ b/src/mail/em-filter-mail-identity-element.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2021 Red Hat (www.redhat.com)
+ *
+ * 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-lib.h>
+
+#include "e-util/e-util.h"
+#include "em-filter-mail-identity-element.h"
+
+struct _EMFilterMailIdentityElementPrivate {
+ ESourceRegistry *registry;
+ gchar *display_name;
+ gchar *identity_uid;
+ gchar *alias_name;
+ gchar *alias_address;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (EMFilterMailIdentityElement, em_filter_mail_identity_element,
E_TYPE_FILTER_ELEMENT)
+
+static void
+filter_mail_identity_take_value (EMFilterMailIdentityElement *mail_identity,
+ gchar *display_name,
+ gchar *identity_uid,
+ gchar *alias_name,
+ gchar *alias_address)
+{
+ if (mail_identity->priv->display_name != display_name) {
+ g_free (mail_identity->priv->display_name);
+ mail_identity->priv->display_name = display_name;
+ } else {
+ g_free (display_name);
+ }
+
+ if (mail_identity->priv->identity_uid != identity_uid) {
+ g_free (mail_identity->priv->identity_uid);
+ mail_identity->priv->identity_uid = identity_uid;
+ } else {
+ g_free (identity_uid);
+ }
+
+ if (mail_identity->priv->alias_name != alias_name) {
+ g_free (mail_identity->priv->alias_name);
+ mail_identity->priv->alias_name = alias_name;
+ } else {
+ g_free (alias_name);
+ }
+
+ if (mail_identity->priv->alias_address != alias_address) {
+ g_free (mail_identity->priv->alias_address);
+ mail_identity->priv->alias_address = alias_address;
+ } else {
+ g_free (alias_address);
+ }
+}
+
+static void
+filter_mail_identity_element_finalize (GObject *object)
+{
+ EMFilterMailIdentityElement *mail_identity = EM_FILTER_MAIL_IDENTITY_ELEMENT (object);
+
+ g_clear_object (&mail_identity->priv->registry);
+ g_free (mail_identity->priv->display_name);
+ g_free (mail_identity->priv->identity_uid);
+ g_free (mail_identity->priv->alias_name);
+ g_free (mail_identity->priv->alias_address);
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (em_filter_mail_identity_element_parent_class)->finalize (object);
+}
+
+static gint
+filter_mail_identity_element_eq (EFilterElement *element_a,
+ EFilterElement *element_b)
+{
+ EMFilterMailIdentityElement *mail_identity_a = EM_FILTER_MAIL_IDENTITY_ELEMENT (element_a);
+ EMFilterMailIdentityElement *mail_identity_b = EM_FILTER_MAIL_IDENTITY_ELEMENT (element_b);
+
+ /* Chain up to parent's method. */
+ if (!E_FILTER_ELEMENT_CLASS (em_filter_mail_identity_element_parent_class)->eq (element_a, element_b))
+ return FALSE;
+
+ return g_strcmp0 (mail_identity_a->priv->display_name, mail_identity_b->priv->display_name) == 0 &&
+ g_strcmp0 (mail_identity_a->priv->identity_uid, mail_identity_b->priv->identity_uid) == 0 &&
+ g_strcmp0 (mail_identity_a->priv->alias_name, mail_identity_b->priv->alias_name) == 0 &&
+ g_strcmp0 (mail_identity_a->priv->alias_address, mail_identity_b->priv->alias_address) == 0;
+}
+
+static void
+filter_mail_identity_element_xml_create (EFilterElement *element,
+ xmlNodePtr node)
+{
+ xmlNodePtr n;
+
+ /* Chain up to parent's method. */
+ E_FILTER_ELEMENT_CLASS (em_filter_mail_identity_element_parent_class)->xml_create (element, node);
+
+ n = node->children;
+ while (n) {
+ if (n->type == XML_ELEMENT_NODE) {
+ g_warning ("Unknown xml node within 'label': %s\n", n->name);
+ }
+ n = n->next;
+ }
+}
+
+static xmlNodePtr
+filter_mail_identity_element_xml_encode (EFilterElement *element)
+{
+ EMFilterMailIdentityElement *mail_identity = EM_FILTER_MAIL_IDENTITY_ELEMENT (element);
+ xmlNodePtr value;
+
+ value = xmlNewNode (NULL, (xmlChar *) "value");
+ xmlSetProp (value, (xmlChar *) "name", (xmlChar *) element->name);
+
+ if (mail_identity->priv->display_name)
+ xmlSetProp (value, (xmlChar *) "display-name", (xmlChar *) mail_identity->priv->display_name);
+
+ if (mail_identity->priv->identity_uid)
+ xmlSetProp (value, (xmlChar *) "identity-uid", (xmlChar *) mail_identity->priv->identity_uid);
+
+ if (mail_identity->priv->alias_name)
+ xmlSetProp (value, (xmlChar *) "alias-name", (xmlChar *) mail_identity->priv->alias_name);
+
+ if (mail_identity->priv->alias_address)
+ xmlSetProp (value, (xmlChar *) "alias-address", (xmlChar *)
mail_identity->priv->alias_address);
+
+ return value;
+}
+
+static gint
+filter_mail_identity_element_xml_decode (EFilterElement *element,
+ xmlNodePtr node)
+{
+ EMFilterMailIdentityElement *mail_identity = EM_FILTER_MAIL_IDENTITY_ELEMENT (element);
+ xmlChar *x_display_name, *x_identity_uid, *x_alias_name, *x_alias_address;
+
+ xmlFree (element->name);
+ element->name = (gchar *) xmlGetProp (node, (xmlChar *) "name");
+
+ x_display_name = xmlGetProp (node, (xmlChar *) "display-name");
+ x_identity_uid = xmlGetProp (node, (xmlChar *) "identity-uid");
+ x_alias_name = xmlGetProp (node, (xmlChar *) "alias-name");
+ x_alias_address = xmlGetProp (node, (xmlChar *) "alias-address");
+
+ filter_mail_identity_take_value (mail_identity,
+ g_strdup ((gchar *) x_display_name),
+ g_strdup ((gchar *) x_identity_uid),
+ g_strdup ((gchar *) x_alias_name),
+ g_strdup ((gchar *) x_alias_address));
+
+ g_clear_pointer (&x_display_name, xmlFree);
+ g_clear_pointer (&x_identity_uid, xmlFree);
+ g_clear_pointer (&x_alias_name, xmlFree);
+ g_clear_pointer (&x_alias_address, xmlFree);
+
+ return 0;
+}
+
+static EFilterElement *
+filter_mail_identity_element_clone (EFilterElement *element)
+{
+ EMFilterMailIdentityElement *mail_identity = EM_FILTER_MAIL_IDENTITY_ELEMENT (element);
+ EMFilterMailIdentityElement *clone_mail_identity;
+ EFilterElement *clone;
+
+ /* Chain up to parent's method. */
+ clone = E_FILTER_ELEMENT_CLASS (em_filter_mail_identity_element_parent_class)->clone (element);
+
+ clone_mail_identity = EM_FILTER_MAIL_IDENTITY_ELEMENT (clone);
+ clone_mail_identity->priv->display_name = g_strdup (mail_identity->priv->display_name);
+ clone_mail_identity->priv->identity_uid = g_strdup (mail_identity->priv->identity_uid);
+ clone_mail_identity->priv->alias_name = g_strdup (mail_identity->priv->alias_name);
+ clone_mail_identity->priv->alias_address = g_strdup (mail_identity->priv->alias_address);
+
+ if (mail_identity->priv->registry)
+ clone_mail_identity->priv->registry = g_object_ref (mail_identity->priv->registry);
+
+ return clone;
+}
+
+static void
+filter_mail_identity_element_changed_cb (GtkComboBox *combo_box,
+ gpointer user_data)
+{
+ EMFilterMailIdentityElement *mail_identity = user_data;
+ GtkTreeIter iter;
+ gchar *display_name = NULL, *identity_uid = NULL, *alias_name = NULL, *alias_address = NULL;
+
+ g_return_if_fail (EM_IS_FILTER_MAIL_IDENTITY_ELEMENT (mail_identity));
+
+ if (!e_mail_identity_combo_box_get_active_uid (E_MAIL_IDENTITY_COMBO_BOX (combo_box), &identity_uid,
&alias_name, &alias_address)) {
+ identity_uid = NULL;
+ alias_name = NULL;
+ alias_address = NULL;
+ }
+
+ if (gtk_combo_box_get_active_iter (combo_box, &iter)) {
+ GtkTreeModel *model;
+
+ model = gtk_combo_box_get_model (combo_box);
+ gtk_tree_model_get (model, &iter,
+ E_MAIL_IDENTITY_COMBO_BOX_COLUMN_DISPLAY_NAME, &display_name,
+ -1);
+ }
+
+ filter_mail_identity_take_value (mail_identity, display_name, identity_uid, alias_name,
alias_address);
+}
+
+static GtkWidget *
+filter_mail_identity_element_get_widget (EFilterElement *element)
+{
+ EMFilterMailIdentityElement *mail_identity = EM_FILTER_MAIL_IDENTITY_ELEMENT (element);
+ EMailIdentityComboBox *combo_box;
+ GtkWidget *widget;
+
+ widget = e_mail_identity_combo_box_new (mail_identity->priv->registry);
+ combo_box = E_MAIL_IDENTITY_COMBO_BOX (widget);
+ e_mail_identity_combo_box_set_none_title (combo_box, _("Default Account"));
+ e_mail_identity_combo_box_set_allow_none (combo_box, TRUE);
+ e_mail_identity_combo_box_set_allow_aliases (combo_box, TRUE);
+
+ g_signal_connect_object (combo_box, "changed",
+ G_CALLBACK (filter_mail_identity_element_changed_cb), mail_identity, 0);
+
+ if (mail_identity->priv->identity_uid) {
+ e_mail_identity_combo_box_set_active_uid (combo_box,
+ mail_identity->priv->identity_uid,
+ mail_identity->priv->alias_name,
+ mail_identity->priv->alias_address);
+ } else {
+ e_mail_identity_combo_box_set_active_uid (combo_box, "", NULL, NULL);
+ }
+
+ return widget;
+}
+
+static void
+filter_mail_identity_element_add_value (GString *str,
+ const gchar *value)
+{
+ const gchar *pp;
+
+ if (!value)
+ return;
+
+ for (pp = value; *pp; pp++) {
+ if (*pp == '\\' || *pp == '|')
+ g_string_append_c (str, '\\');
+ g_string_append_c (str, *pp);
+ }
+}
+
+static void
+filter_mail_identity_element_format_sexp (EFilterElement *element,
+ GString *out)
+{
+ EMFilterMailIdentityElement *mail_identity = EM_FILTER_MAIL_IDENTITY_ELEMENT (element);
+ GString *value = NULL;
+
+ if (mail_identity->priv->identity_uid && *mail_identity->priv->identity_uid) {
+ /* Encode the value as: "identity_uid|alias_name|alias_value" */
+ value = g_string_sized_new (strlen (mail_identity->priv->identity_uid) * 2);
+
+ filter_mail_identity_element_add_value (value, mail_identity->priv->identity_uid);
+ g_string_append_c (value, '|');
+ filter_mail_identity_element_add_value (value, mail_identity->priv->alias_name);
+ g_string_append_c (value, '|');
+ filter_mail_identity_element_add_value (value, mail_identity->priv->alias_address);
+ }
+
+ camel_sexp_encode_string (out, value ? value->str : NULL);
+
+ if (value)
+ g_string_free (value, TRUE);
+}
+
+static void
+filter_mail_identity_element_describe (EFilterElement *element,
+ GString *out)
+{
+ EMFilterMailIdentityElement *mail_identity = EM_FILTER_MAIL_IDENTITY_ELEMENT (element);
+
+ if (mail_identity->priv->display_name && *mail_identity->priv->display_name)
+ g_string_append (out, mail_identity->priv->display_name);
+}
+
+static void
+em_filter_mail_identity_element_class_init (EMFilterMailIdentityElementClass *class)
+{
+ GObjectClass *object_class;
+ EFilterElementClass *filter_element_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = filter_mail_identity_element_finalize;
+
+ filter_element_class = E_FILTER_ELEMENT_CLASS (class);
+ filter_element_class->eq = filter_mail_identity_element_eq;
+ filter_element_class->xml_create = filter_mail_identity_element_xml_create;
+ filter_element_class->xml_encode = filter_mail_identity_element_xml_encode;
+ filter_element_class->xml_decode = filter_mail_identity_element_xml_decode;
+ filter_element_class->clone = filter_mail_identity_element_clone;
+ filter_element_class->get_widget = filter_mail_identity_element_get_widget;
+ filter_element_class->format_sexp = filter_mail_identity_element_format_sexp;
+ filter_element_class->describe = filter_mail_identity_element_describe;
+}
+
+static void
+em_filter_mail_identity_element_init (EMFilterMailIdentityElement *mail_identity)
+{
+ mail_identity->priv = em_filter_mail_identity_element_get_instance_private (mail_identity);
+}
+
+EFilterElement *
+em_filter_mail_identity_element_new (ESourceRegistry *registry)
+{
+ EMFilterMailIdentityElement *mail_identity;
+
+ g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
+
+ mail_identity = g_object_new (EM_TYPE_FILTER_MAIL_IDENTITY_ELEMENT, NULL);
+ mail_identity->priv->registry = g_object_ref (registry);
+
+ return E_FILTER_ELEMENT (mail_identity);
+}
+
+ESourceRegistry *
+em_filter_mail_identity_element_get_registry (EMFilterMailIdentityElement *mail_identity)
+{
+ g_return_val_if_fail (EM_IS_FILTER_MAIL_IDENTITY_ELEMENT (mail_identity), NULL);
+
+ return mail_identity->priv->registry;
+}
diff --git a/src/mail/em-filter-mail-identity-element.h b/src/mail/em-filter-mail-identity-element.h
new file mode 100644
index 0000000000..19d1f4a38a
--- /dev/null
+++ b/src/mail/em-filter-mail-identity-element.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 Red Hat (www.redhat.com)
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef EM_FILTER_MAIL_IDENTITY_ELEMENT_H
+#define EM_FILTER_MAIL_IDENTITY_ELEMENT_H
+
+#include <libedataserver/libedataserver.h>
+#include <e-util/e-util.h>
+
+/* Standard GObject macros */
+#define EM_TYPE_FILTER_MAIL_IDENTITY_ELEMENT \
+ (em_filter_mail_identity_element_get_type ())
+#define EM_FILTER_MAIL_IDENTITY_ELEMENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), EM_TYPE_FILTER_MAIL_IDENTITY_ELEMENT, EMFilterMailIdentityElement))
+#define EM_FILTER_MAIL_IDENTITY_ELEMENT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), EM_TYPE_FILTER_MAIL_IDENTITY_ELEMENT, EMFilterMailIdentityElementClass))
+#define EM_IS_FILTER_MAIL_IDENTITY_ELEMENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), EM_TYPE_FILTER_MAIL_IDENTITY_ELEMENT))
+#define EM_IS_FILTER_MAIL_IDENTITY_ELEMENT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), EM_TYPE_FILTER_MAIL_IDENTITY_ELEMENT))
+#define EM_FILTER_MAIL_IDENTITY_ELEMENT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), EM_TYPE_FILTER_MAIL_IDENTITY_ELEMENT, EMFilterMailIdentityElementClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMFilterMailIdentityElement EMFilterMailIdentityElement;
+typedef struct _EMFilterMailIdentityElementClass EMFilterMailIdentityElementClass;
+typedef struct _EMFilterMailIdentityElementPrivate EMFilterMailIdentityElementPrivate;
+
+struct _EMFilterMailIdentityElement {
+ EFilterElement parent;
+ EMFilterMailIdentityElementPrivate *priv;
+};
+
+struct _EMFilterMailIdentityElementClass {
+ EFilterElementClass parent_class;
+};
+
+GType em_filter_mail_identity_element_get_type (void) G_GNUC_CONST;
+EFilterElement *em_filter_mail_identity_element_new (ESourceRegistry *registry);
+ESourceRegistry *
+ em_filter_mail_identity_element_get_registry (EMFilterMailIdentityElement *mail_identity);
+
+G_END_DECLS
+
+#endif /* EM_FILTER_MAIL_IDENTITY_ELEMENT_H */
diff --git a/src/mail/filtertypes.xml.in b/src/mail/filtertypes.xml.in
index d963bc65af..c5cec3f601 100644
--- a/src/mail/filtertypes.xml.in
+++ b/src/mail/filtertypes.xml.in
@@ -806,8 +806,12 @@
<part name="forward">
<_title>Forward to</_title>
- <code>(forward-to ${address})</code>
+ <code>(forward-to ${address} ${from})</code>
<input type="address" name="address" allow-empty="false"/>
+ <input type="label" name="with">
+ <_title>with</_title>
+ </input>
+ <input type="mail-identity" name="from"/>
</part>
</actionset>
</filterdescription>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]