[evolution] Bug 788543 - Add a way to filter on Source Account first
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] Bug 788543 - Add a way to filter on Source Account first
- Date: Wed, 10 Jan 2018 17:36:52 +0000 (UTC)
commit dec7ee0e1507e3e7b4ff2d72cad8bb321e7c8597
Author: Milan Crha <mcrha redhat com>
Date: Wed Jan 10 18:36:19 2018 +0100
Bug 788543 - Add a way to filter on Source Account first
src/mail/em-filter-context.c | 4 +-
src/mail/em-filter-rule.c | 300 ++++++++++++++++++++++++++++++++++++++----
src/mail/em-filter-rule.h | 9 +-
3 files changed, 287 insertions(+), 26 deletions(-)
---
diff --git a/src/mail/em-filter-context.c b/src/mail/em-filter-context.c
index da33df6..9aacffd 100644
--- a/src/mail/em-filter-context.c
+++ b/src/mail/em-filter-context.c
@@ -136,7 +136,7 @@ filter_context_rename_uri (ERuleContext *context,
while ((rule = e_rule_context_next_rule (context, rule, NULL))) {
gint rulecount = 0;
- l = EM_FILTER_RULE (rule)->actions;
+ l = em_filter_rule_get_actions (EM_FILTER_RULE (rule));
while (l) {
action = l->data;
@@ -191,7 +191,7 @@ filter_context_delete_uri (ERuleContext *context,
while ((rule = e_rule_context_next_rule (context, rule, NULL))) {
gint recorded = 0;
- l = EM_FILTER_RULE (rule)->actions;
+ l = em_filter_rule_get_actions (EM_FILTER_RULE (rule));
while (l) {
action = l->data;
diff --git a/src/mail/em-filter-rule.c b/src/mail/em-filter-rule.c
index 503dd05..ca0d43e 100644
--- a/src/mail/em-filter-rule.c
+++ b/src/mail/em-filter-rule.c
@@ -29,11 +29,17 @@
#include <e-util/e-util.h>
+#include "e-mail-ui-session.h"
#include "em-filter-rule.h"
#include "em-filter-context.h"
#define d(x)
+struct _EMFilterRulePrivate {
+ GList *actions;
+ gchar *account_uid;
+};
+
static gint validate (EFilterRule *fr, EAlert **alert);
static gint filter_eq (EFilterRule *fr, EFilterRule *cm);
static xmlNodePtr xml_encode (EFilterRule *fr);
@@ -44,11 +50,39 @@ static GtkWidget *get_widget (EFilterRule *fr, ERuleContext *rc);
G_DEFINE_TYPE (EMFilterRule, em_filter_rule, E_TYPE_FILTER_RULE)
static void
+em_filter_rule_build_code (EFilterRule *rule,
+ GString *out)
+{
+ EMFilterRule *ff;
+
+ g_return_if_fail (EM_IS_FILTER_RULE (rule));
+ g_return_if_fail (out != NULL);
+
+ ff = EM_FILTER_RULE (rule);
+
+ E_FILTER_RULE_CLASS (em_filter_rule_parent_class)->build_code (rule, out);
+
+ if (ff->priv->account_uid && *ff->priv->account_uid) {
+ if (out->len) {
+ gchar *prefix;
+
+ prefix = g_strdup_printf ("(and (header-source \"%s\")\n", ff->priv->account_uid);
+ g_string_prepend (out, prefix);
+ g_string_append (out, ")\n");
+ g_free (prefix);
+ } else {
+ g_string_append_printf (out, "(header-source \"%s\")\n", ff->priv->account_uid);
+ }
+ }
+}
+
+static void
em_filter_rule_finalize (GObject *object)
{
- EMFilterRule *ff =(EMFilterRule *) object;
+ EMFilterRule *ff = EM_FILTER_RULE (object);
- g_list_free_full (ff->actions, (GDestroyNotify) g_object_unref);
+ g_list_free_full (ff->priv->actions, g_object_unref);
+ g_free (ff->priv->account_uid);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (em_filter_rule_parent_class)->finalize (object);
@@ -60,6 +94,8 @@ em_filter_rule_class_init (EMFilterRuleClass *class)
GObjectClass *object_class;
EFilterRuleClass *filter_rule_class;
+ g_type_class_add_private (class, sizeof (EMFilterRulePrivate));
+
object_class = G_OBJECT_CLASS (class);
object_class->finalize = em_filter_rule_finalize;
@@ -68,6 +104,7 @@ em_filter_rule_class_init (EMFilterRuleClass *class)
filter_rule_class->eq = filter_eq;
filter_rule_class->xml_encode = xml_encode;
filter_rule_class->xml_decode = xml_decode;
+ filter_rule_class->build_code = em_filter_rule_build_code;
filter_rule_class->copy = rule_copy;
filter_rule_class->get_widget = get_widget;
}
@@ -75,6 +112,7 @@ em_filter_rule_class_init (EMFilterRuleClass *class)
static void
em_filter_rule_init (EMFilterRule *ff)
{
+ ff->priv = G_TYPE_INSTANCE_GET_PRIVATE (ff, EM_TYPE_FILTER_RULE, EMFilterRulePrivate);
}
/**
@@ -94,7 +132,7 @@ void
em_filter_rule_add_action (EMFilterRule *fr,
EFilterPart *fp)
{
- fr->actions = g_list_append (fr->actions, fp);
+ fr->priv->actions = g_list_append (fr->priv->actions, fp);
e_filter_rule_emit_changed ((EFilterRule *) fr);
}
@@ -103,7 +141,7 @@ void
em_filter_rule_remove_action (EMFilterRule *fr,
EFilterPart *fp)
{
- fr->actions = g_list_remove (fr->actions, fp);
+ fr->priv->actions = g_list_remove (fr->priv->actions, fp);
e_filter_rule_emit_changed ((EFilterRule *) fr);
}
@@ -115,11 +153,11 @@ em_filter_rule_replace_action (EMFilterRule *fr,
{
GList *l;
- l = g_list_find (fr->actions, fp);
+ l = g_list_find (fr->priv->actions, fp);
if (l) {
l->data = new;
} else {
- fr->actions = g_list_append (fr->actions, new);
+ fr->priv->actions = g_list_append (fr->priv->actions, new);
}
e_filter_rule_emit_changed ((EFilterRule *) fr);
@@ -130,7 +168,7 @@ em_filter_rule_build_action (EMFilterRule *fr,
GString *out)
{
g_string_append (out, "(begin\n");
- e_filter_part_build_code_list (fr->actions, out);
+ e_filter_part_build_code_list (fr->priv->actions, out);
g_string_append (out, ")\n");
}
@@ -146,7 +184,7 @@ validate (EFilterRule *fr,
validate (fr, alert);
/* validate rule actions */
- parts = ff->actions;
+ parts = ff->priv->actions;
while (parts && valid) {
valid = e_filter_part_validate ((EFilterPart *) parts->data, alert);
parts = parts->next;
@@ -177,9 +215,10 @@ filter_eq (EFilterRule *fr,
EFilterRule *cm)
{
return E_FILTER_RULE_CLASS (em_filter_rule_parent_class)->eq (fr, cm)
+ && g_strcmp0 (em_filter_rule_get_account_uid (EM_FILTER_RULE (fr)),
em_filter_rule_get_account_uid (EM_FILTER_RULE (cm))) == 0
&& list_eq (
- ((EMFilterRule *) fr)->actions,
- ((EMFilterRule *) cm)->actions);
+ ((EMFilterRule *) fr)->priv->actions,
+ ((EMFilterRule *) cm)->priv->actions);
}
static xmlNodePtr
@@ -192,9 +231,13 @@ xml_encode (EFilterRule *fr)
node = E_FILTER_RULE_CLASS (em_filter_rule_parent_class)->
xml_encode (fr);
g_return_val_if_fail (node != NULL, NULL);
+
+ if (ff->priv->account_uid && *ff->priv->account_uid)
+ xmlSetProp (node, (const xmlChar *) "account-uid", (const xmlChar *) ff->priv->account_uid);
+
set = xmlNewNode (NULL, (const guchar *)"actionset");
xmlAddChild (node, set);
- l = ff->actions;
+ l = ff->priv->actions;
while (l) {
work = e_filter_part_xml_encode ((EFilterPart *) l->data);
xmlAddChild (set, work);
@@ -241,6 +284,7 @@ xml_decode (EFilterRule *fr,
{
EMFilterRule *ff =(EMFilterRule *) fr;
xmlNodePtr work;
+ xmlChar *account_uid;
gint result;
result = E_FILTER_RULE_CLASS (em_filter_rule_parent_class)->
@@ -248,6 +292,16 @@ xml_decode (EFilterRule *fr,
if (result != 0)
return result;
+ g_clear_pointer (&ff->priv->account_uid, g_free);
+
+ account_uid = xmlGetProp (node, (const xmlChar *) "account-uid");
+ if (account_uid) {
+ if (*account_uid)
+ ff->priv->account_uid = g_strdup ((const gchar *) account_uid);
+
+ xmlFree (account_uid);
+ }
+
work = node->children;
while (work) {
if (!strcmp ((gchar *) work->name, "actionset")) {
@@ -269,21 +323,22 @@ rule_copy (EFilterRule *dest,
fdest =(EMFilterRule *) dest;
fsrc =(EMFilterRule *) src;
- if (fdest->actions) {
- g_list_foreach (fdest->actions, (GFunc) g_object_unref, NULL);
- g_list_free (fdest->actions);
- fdest->actions = NULL;
+ if (fdest->priv->actions) {
+ g_list_free_full (fdest->priv->actions, g_object_unref);
+ fdest->priv->actions = NULL;
}
- node = fsrc->actions;
+ node = fsrc->priv->actions;
while (node) {
EFilterPart *part = node->data;
g_object_ref (part);
- fdest->actions = g_list_append (fdest->actions, part);
+ fdest->priv->actions = g_list_append (fdest->priv->actions, part);
node = node->next;
}
+ em_filter_rule_set_account_uid (fdest, em_filter_rule_get_account_uid (fsrc));
+
E_FILTER_RULE_CLASS (em_filter_rule_parent_class)->copy (dest, src);
}
@@ -494,9 +549,9 @@ event_box_drag_motion_cb (GtkWidget *widget,
gpointer rule;
/* Move internal data first */
- rule = g_list_nth_data (fr->actions, index_src);
- fr->actions = g_list_remove (fr->actions, rule);
- fr->actions = g_list_insert (fr->actions, rule, index_des);
+ rule = g_list_nth_data (fr->priv->actions, index_src);
+ fr->priv->actions = g_list_remove (fr->priv->actions, rule);
+ fr->priv->actions = g_list_insert (fr->priv->actions, rule, index_des);
/* Then the UI part */
event_box = gtk_grid_get_child_at (data->parts_grid, 0, index_src);
@@ -558,7 +613,7 @@ less_parts (GtkWidget *button,
struct _part_data *part_data;
gint index;
- if (g_list_length (((EMFilterRule *) data->fr)->actions) < 2)
+ if (g_list_length (((EMFilterRule *) data->fr)->priv->actions) < 2)
return;
for (index = 0; index < data->n_rows; index++) {
@@ -576,7 +631,7 @@ less_parts (GtkWidget *button,
part = part_data->part;
- index = g_list_index (((EMFilterRule *) data->fr)->actions, part);
+ index = g_list_index (((EMFilterRule *) data->fr)->priv->actions, part);
g_warn_if_fail (index >= 0);
/* remove the part from the list */
@@ -800,6 +855,166 @@ filter_type_changed_cb (GtkComboBox *combobox,
e_filter_rule_set_source (fr, id);
}
+static void
+filter_rule_accounts_changed_cb (GtkComboBox *combobox,
+ EMFilterRule *fr)
+{
+ const gchar *id;
+
+ g_return_if_fail (GTK_IS_COMBO_BOX (combobox));
+ g_return_if_fail (EM_IS_FILTER_RULE (fr));
+
+ id = gtk_combo_box_get_active_id (combobox);
+ if (id && *id)
+ em_filter_rule_set_account_uid (fr, id);
+}
+
+/* This should have blocked the filter_rule_accounts_changed_cb() handler */
+static void
+filter_rule_select_account (GtkComboBox *accounts,
+ const gchar *account_uid)
+{
+ g_return_if_fail (GTK_IS_COMBO_BOX (accounts));
+
+ if (!account_uid || !*account_uid) {
+ gtk_combo_box_set_active (accounts, 0);
+ return;
+ }
+
+ if (!gtk_combo_box_set_active_id (accounts, account_uid)) {
+ CamelSession *session = g_object_get_data (G_OBJECT (accounts), "e-mail-session");
+ CamelService *service = camel_session_ref_service (session, account_uid);
+
+ if (service) {
+ /* It is disabled account */
+ gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (accounts),
+ camel_service_get_uid (service),
+ camel_service_get_display_name (service));
+ } else {
+ /* It is removed/non-existent account */
+ gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (accounts),
+ account_uid, account_uid);
+ }
+
+ g_warn_if_fail (gtk_combo_box_set_active_id (accounts, account_uid));
+
+ g_clear_object (&service);
+ }
+}
+
+static gint
+filter_rule_compare_services (gconstpointer s1,
+ gconstpointer s2)
+{
+ CamelService *service1 = (CamelService *) s1;
+ CamelService *service2 = (CamelService *) s2;
+
+ return g_utf8_collate (camel_service_get_display_name (service1), camel_service_get_display_name
(service2));
+}
+
+static void
+filter_rule_fill_account_combo (GtkComboBox *source_combo,
+ GtkComboBoxText *accounts_combo)
+{
+ ESourceRegistry *registry;
+ CamelSession *session;
+ GList *services, *link;
+ GSList *add_services = NULL, *slink;
+ gboolean is_incoming;
+ gchar *account_id;
+
+ g_return_if_fail (GTK_IS_COMBO_BOX (source_combo));
+ g_return_if_fail (GTK_IS_COMBO_BOX_TEXT (accounts_combo));
+
+ session = g_object_get_data (G_OBJECT (accounts_combo), "e-mail-session");
+ g_return_if_fail (E_IS_MAIL_SESSION (session));
+
+ registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+ is_incoming = g_strcmp0 (gtk_combo_box_get_active_id (source_combo), E_FILTER_SOURCE_INCOMING) == 0;
+ account_id = g_strdup (gtk_combo_box_get_active_id (GTK_COMBO_BOX (accounts_combo)));
+
+ g_signal_handlers_block_matched (accounts_combo, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
filter_rule_accounts_changed_cb, NULL);
+
+ gtk_combo_box_text_remove_all (accounts_combo);
+
+ /* Translators: This is in a Mail filter rule editor, part of "For account: [ Any ]" section */
+ gtk_combo_box_text_append (accounts_combo, NULL, C_("mail-filter-rule", "Any"));
+
+ services = camel_session_list_services (session);
+
+ for (link = services; link; link = g_list_next (link)) {
+ CamelService *service = link->data;
+ const gchar *uid = camel_service_get_uid (service);
+
+ if (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0 ||
+ g_strcmp0 (uid, E_MAIL_SESSION_VFOLDER_UID) == 0)
+ continue;
+
+ if ((is_incoming && CAMEL_IS_STORE (service)) ||
+ (!is_incoming && CAMEL_IS_TRANSPORT (service))) {
+ ESource *source = e_source_registry_ref_source (registry, uid);
+
+ if (!source || !e_source_registry_check_enabled (registry, source)) {
+ g_clear_object (&source);
+ continue;
+ }
+
+ g_clear_object (&source);
+
+ add_services = g_slist_prepend (add_services, service);
+ }
+ }
+
+ add_services = g_slist_sort (add_services, filter_rule_compare_services);
+
+ for (slink = add_services; slink; slink = g_slist_next (slink)) {
+ CamelService *service = slink->data;
+
+ gtk_combo_box_text_append (accounts_combo,
+ camel_service_get_uid (service),
+ camel_service_get_display_name (service));
+ }
+
+ g_list_free_full (services, g_object_unref);
+ g_slist_free (add_services);
+
+ filter_rule_select_account (GTK_COMBO_BOX (accounts_combo), account_id);
+
+ g_signal_handlers_unblock_matched (accounts_combo, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
filter_rule_accounts_changed_cb, NULL);
+
+ g_free (account_id);
+}
+
+static GtkWidget *
+filter_rule_create_account_combo (EMFilterRule *fr,
+ EMailSession *session,
+ GtkWidget *source_combo)
+{
+ GtkComboBox *accounts;
+ gulong handler_id;
+
+ g_return_val_if_fail (EM_IS_FILTER_RULE (fr), NULL);
+ g_return_val_if_fail (E_IS_MAIL_UI_SESSION (session), NULL);
+ g_return_val_if_fail (GTK_IS_COMBO_BOX (source_combo), NULL);
+
+ accounts = GTK_COMBO_BOX (gtk_combo_box_text_new ());
+ g_object_set_data_full (G_OBJECT (accounts), "e-mail-session", g_object_ref (session),
g_object_unref);
+
+ g_signal_connect (source_combo, "changed",
+ G_CALLBACK (filter_rule_fill_account_combo), accounts);
+
+ handler_id = g_signal_connect (accounts, "changed",
+ G_CALLBACK (filter_rule_accounts_changed_cb), fr);
+
+ filter_rule_fill_account_combo (GTK_COMBO_BOX (source_combo), GTK_COMBO_BOX_TEXT (accounts));
+
+ g_signal_handler_block (accounts, handler_id);
+ filter_rule_select_account (accounts, fr->priv->account_uid);
+ g_signal_handler_unblock (accounts, handler_id);
+
+ return GTK_WIDGET (accounts);
+}
+
static GtkWidget *
get_widget (EFilterRule *fr,
ERuleContext *rc)
@@ -838,6 +1053,14 @@ get_widget (EFilterRule *fr,
gtk_grid_attach (hgrid, label, 0, 0, 1, 1);
gtk_grid_attach_next_to (hgrid, w, label, GTK_POS_RIGHT, 1, 1);
+ label = gtk_label_new_with_mnemonic (_("_For Account:"));
+ w = filter_rule_create_account_combo (ff, em_filter_context_get_session (EM_FILTER_CONTEXT (rc)), w);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), w);
+
+ gtk_grid_attach (hgrid, label, 2, 0, 1, 1);
+ gtk_grid_attach_next_to (hgrid, w, label, GTK_POS_RIGHT, 1, 1);
+
gtk_grid_insert_row (GTK_GRID (widget), 1);
gtk_grid_attach (GTK_GRID (widget), GTK_WIDGET (hgrid), 0, 1, 1, 1);
@@ -886,7 +1109,7 @@ get_widget (EFilterRule *fr,
/* only set to automatically clean up the memory */
g_object_set_data_full ((GObject *) hgrid, "data", data, g_free);
- for (link = ff->actions; link; link = g_list_next (link)) {
+ for (link = ff->priv->actions; link; link = g_list_next (link)) {
part = link->data;
d (printf ("adding action %s\n", part->title));
w = get_rule_part_widget ((EMFilterContext *) rc, part, fr);
@@ -935,3 +1158,34 @@ get_widget (EFilterRule *fr,
return widget;
}
+
+GList *
+em_filter_rule_get_actions (EMFilterRule *rule)
+{
+ g_return_val_if_fail (EM_IS_FILTER_RULE (rule), NULL);
+
+ return rule->priv->actions;
+}
+
+const gchar *
+em_filter_rule_get_account_uid (EMFilterRule *rule)
+{
+ g_return_val_if_fail (EM_IS_FILTER_RULE (rule), NULL);
+
+ return rule->priv->account_uid;
+}
+
+void
+em_filter_rule_set_account_uid (EMFilterRule *rule,
+ const gchar *account_uid)
+{
+ g_return_if_fail (EM_IS_FILTER_RULE (rule));
+
+ if (g_strcmp0 (account_uid, rule->priv->account_uid) == 0)
+ return;
+
+ g_clear_pointer (&rule->priv->account_uid, g_free);
+ rule->priv->account_uid = (account_uid && *account_uid) ? g_strdup (account_uid) : NULL;
+
+ e_filter_rule_emit_changed (E_FILTER_RULE (rule));
+}
diff --git a/src/mail/em-filter-rule.h b/src/mail/em-filter-rule.h
index 7ee2a80..c72be9a 100644
--- a/src/mail/em-filter-rule.h
+++ b/src/mail/em-filter-rule.h
@@ -25,6 +25,7 @@
#define EM_FILTER_RULE_H
#include <e-util/e-util.h>
+#include <libemail-engine/libemail-engine.h>
#define EM_TYPE_FILTER_RULE \
(em_filter_rule_get_type ())
@@ -36,11 +37,12 @@
typedef struct _EMFilterRule EMFilterRule;
typedef struct _EMFilterRuleClass EMFilterRuleClass;
+typedef struct _EMFilterRulePrivate EMFilterRulePrivate;
struct _EMFilterRule {
EFilterRule parent_object;
- GList *actions;
+ EMFilterRulePrivate *priv;
};
struct _EMFilterRuleClass {
@@ -57,4 +59,9 @@ void em_filter_rule_replace_action (EMFilterRule *fr, EFilterPart *fp
void em_filter_rule_build_action (EMFilterRule *fr, GString *out);
+GList * em_filter_rule_get_actions (EMFilterRule *rule);
+const gchar * em_filter_rule_get_account_uid (EMFilterRule *rule);
+void em_filter_rule_set_account_uid (EMFilterRule *rule,
+ const gchar *account_uid);
+
#endif /* EM_FILTER_RULE_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]