I#1512 - Choose account with which to forward message in filter rule

Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/1512
This commit is contained in:
Milan Crha
2021-06-11 11:46:27 +02:00
parent 91d4f2229e
commit 70b7d47873
15 changed files with 841 additions and 9 deletions

View File

@ -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>

View File

@ -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

View File

@ -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

211
src/e-util/e-filter-label.c Normal file
View File

@ -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;
}

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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>

View File

@ -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,

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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>