diff options
-rw-r--r-- | filter/ChangeLog | 24 | ||||
-rw-r--r-- | filter/filter-rule.c | 124 | ||||
-rw-r--r-- | filter/filter-rule.h | 9 | ||||
-rw-r--r-- | filter/rule-context.c | 2 | ||||
-rw-r--r-- | filter/rule-context.h | 8 | ||||
-rw-r--r-- | filter/vfolder-context.c | 2 |
6 files changed, 142 insertions, 27 deletions
diff --git a/filter/ChangeLog b/filter/ChangeLog index a1f20d8611..3510ece44d 100644 --- a/filter/ChangeLog +++ b/filter/ChangeLog @@ -1,5 +1,29 @@ 2004-05-12 Not Zed <NotZed@Ximian.com> + * filter-rule.c (xml_decode): load threading option if threading + enabled. + (xml_encode): write out threading setting. + (rule_copy): copy threading option. + (rule_eq): compare threading. + (build_code): build the match-threads stuff if set. + (fr_grouping_changed): insead of the match_all match_any activate + clalbacks. + (fr_threading_changed): handle threading option menu + + * rule-context.c (rule_context_init): set capabilities flags. + + * vfolder-context.c (vfolder_context_init): set capabilities flags + to include threading. + + * rule-context.h: added a capabilities flag, grouping and + threading capabilities. Sort of a hack to workaround not being + able to put grouping or threading into rules. + + * filter-rule.h: added an option for threading as well as + grouping. + +2004-05-12 Not Zed <NotZed@Ximian.com> + * Makefile.am (%.xml.h): fix i18n file generation rules. * filter-errors.xml: rename from xml.in and fix tags. diff --git a/filter/filter-rule.c b/filter/filter-rule.c index 8b90fffee0..2088d7133c 100644 --- a/filter/filter-rule.c +++ b/filter/filter-rule.c @@ -20,7 +20,6 @@ * Boston, MA 02111-1307, USA. */ - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -259,6 +258,7 @@ static int rule_eq (FilterRule *fr, FilterRule *cm) { return fr->grouping == cm->grouping + && fr->threading == fr->threading && ((fr->name && cm->name && strcmp (fr->name, cm->name) == 0) || (fr->name == NULL && cm->name == NULL)) && ((fr->source && cm->source && strcmp (fr->source, cm->source) == 0) @@ -289,7 +289,21 @@ xml_encode (FilterRule *fr) xmlSetProp (node, "grouping", "any"); break; } - + + switch (fr->threading) { + case FILTER_THREAD_NONE: + break; + case FILTER_THREAD_ALL: + xmlSetProp(node, "threading", "all"); + break; + case FILTER_THREAD_REPLIES: + xmlSetProp(node, "threading", "replies"); + break; + case FILTER_THREAD_REPLIES_PARENTS: + xmlSetProp(node, "threading", "replies_parents"); + break; + } + if (fr->source) { xmlSetProp (node, "source", fr->source); } else { @@ -378,6 +392,18 @@ xml_decode (FilterRule *fr, xmlNodePtr node, RuleContext *f) else fr->grouping = FILTER_GROUP_ALL; xmlFree (grouping); + + fr->threading = FILTER_THREAD_NONE; + if (f->flags & RULE_CONTEXT_THREADING + && (grouping = xmlGetProp (node, "threading"))) { + if (!strcmp(grouping, "all")) + fr->threading = FILTER_THREAD_ALL; + else if (!strcmp(grouping, "replies")) + fr->threading = FILTER_THREAD_REPLIES; + else if (!strcmp(grouping, "replies_parents")) + fr->threading = FILTER_THREAD_REPLIES_PARENTS; + xmlFree (grouping); + } g_free (fr->source); source = xmlGetProp (node, "source"); @@ -422,7 +448,8 @@ rule_copy (FilterRule *dest, FilterRule *src) dest->source = g_strdup (src->source); dest->grouping = src->grouping; - + dest->threading = src->threading; + if (dest->parts) { g_list_foreach (dest->parts, (GFunc) g_object_unref, NULL); g_list_free (dest->parts); @@ -514,6 +541,20 @@ filter_rule_emit_changed(FilterRule *fr) static void build_code (FilterRule *fr, GString *out) { + switch (fr->threading) { + case FILTER_THREAD_NONE: + break; + case FILTER_THREAD_ALL: + g_string_append(out, " (match-threads \"all\" "); + break; + case FILTER_THREAD_REPLIES: + g_string_append(out, " (match-threads \"replies\" "); + break; + case FILTER_THREAD_REPLIES_PARENTS: + g_string_append(out, " (match-threads \"replies_parents\" "); + break; + } + switch (fr->grouping) { case FILTER_GROUP_ALL: g_string_append (out, " (and\n "); @@ -527,18 +568,21 @@ build_code (FilterRule *fr, GString *out) filter_part_build_code_list (fr->parts, out); g_string_append (out, ")\n"); + + if (fr->threading != FILTER_THREAD_NONE) + g_string_append (out, ")\n"); } static void -match_all (GtkWidget *widget, FilterRule *fr) +fr_grouping_changed(GtkWidget *w, FilterRule *fr) { - fr->grouping = FILTER_GROUP_ALL; + fr->grouping = gtk_option_menu_get_history((GtkOptionMenu *)w); } static void -match_any (GtkWidget *widget, FilterRule *fr) +fr_threading_changed(GtkWidget *w, FilterRule *fr) { - fr->grouping = FILTER_GROUP_ANY; + fr->threading = gtk_option_menu_get_history((GtkOptionMenu *)w); } struct _part_data { @@ -737,7 +781,7 @@ get_widget (FilterRule *fr, struct _RuleContext *f) GList *l; FilterPart *part; struct _rule_data *data; - int rows, i = 0; + int rows, i; /* this stuff should probably be a table, but the rule parts need to be a vbox */ @@ -801,35 +845,61 @@ get_widget (FilterRule *fr, struct _RuleContext *f) g_object_set_data_full ((GObject *) vbox, "data", data, g_free); hbox = gtk_hbox_new (FALSE, 3); - label = gtk_label_new (_("Execute actions")); + + add = gtk_button_new_from_stock (GTK_STOCK_ADD); + g_signal_connect (add, "clicked", G_CALLBACK (more_parts), data); + gtk_box_pack_start (GTK_BOX (hbox), add, FALSE, FALSE, 0); + + if (f->flags & RULE_CONTEXT_GROUPING) { + const char *thread_types[] = { N_("if all criteria are met"), N_("if any criteria are met") }; + + label = gtk_label_new (_("Execute actions")); + menu = gtk_menu_new (); - menu = gtk_menu_new (); + for (i=0;i<2;i++) { + item = gtk_menu_item_new_with_label(_(thread_types[i])); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + } - item = gtk_menu_item_new_with_label (_("if all criteria are met")); - g_signal_connect (item, "activate", G_CALLBACK (match_all), fr); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show (item); + omenu = gtk_option_menu_new (); + gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu); + gtk_option_menu_set_history (GTK_OPTION_MENU (omenu), fr->grouping); + gtk_widget_show (omenu); - item = gtk_menu_item_new_with_label (_("if any criteria are met")); - g_signal_connect (item, "activate", G_CALLBACK (match_any), fr); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show (item); + gtk_box_pack_end (GTK_BOX (hbox), omenu, FALSE, FALSE, 0); + gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0); + + g_signal_connect(omenu, "changed", G_CALLBACK(fr_grouping_changed), fr); + } + + if (f->flags & RULE_CONTEXT_THREADING) { + const char *thread_types[] = { N_("None"), N_("All related"), N_("Replies"), N_("Replies and parents") }; + + label = gtk_label_new (_("Include threads")); + menu = gtk_menu_new (); - omenu = gtk_option_menu_new (); - gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu); - gtk_option_menu_set_history (GTK_OPTION_MENU (omenu), fr->grouping == FILTER_GROUP_ALL ? 0 : 1); - gtk_widget_show (omenu); + for (i=0;i<4;i++) { + item = gtk_menu_item_new_with_label(_(thread_types[i])); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + } - add = gtk_button_new_from_stock (GTK_STOCK_ADD); - g_signal_connect (add, "clicked", G_CALLBACK (more_parts), data); - gtk_box_pack_start (GTK_BOX (hbox), add, FALSE, FALSE, 0); + omenu = gtk_option_menu_new (); + gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu); + gtk_option_menu_set_history (GTK_OPTION_MENU (omenu), fr->threading); + gtk_widget_show (omenu); - gtk_box_pack_end (GTK_BOX (hbox), omenu, FALSE, FALSE, 0); - gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_box_pack_end (GTK_BOX (hbox), omenu, FALSE, FALSE, 0); + gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0); + + g_signal_connect(omenu, "changed", G_CALLBACK(fr_threading_changed), fr); + } gtk_box_pack_start (GTK_BOX (inframe), hbox, FALSE, FALSE, 3); l = fr->parts; + i = 0; while (l) { part = l->data; d(printf ("adding rule %s\n", part->title)); diff --git a/filter/filter-rule.h b/filter/filter-rule.h index a6b2c3996a..2d5ba8174a 100644 --- a/filter/filter-rule.h +++ b/filter/filter-rule.h @@ -45,6 +45,13 @@ enum _filter_grouping_t { FILTER_GROUP_ANY /* any rule must match */ }; +/* threading, if the context supports it */ +enum _filter_threading_t { + FILTER_THREAD_NONE, /* don't add any thread matching */ + FILTER_THREAD_ALL, /* add all possible threads */ + FILTER_THREAD_REPLIES, /* add only replies */ + FILTER_THREAD_REPLIES_PARENTS, /* replies plus parents */ +}; #define FILTER_SOURCE_INCOMING "incoming" /* performed on incoming email */ #define FILTER_SOURCE_DEMAND "demand" /* performed on the selected folder @@ -60,6 +67,8 @@ struct _FilterRule { char *source; enum _filter_grouping_t grouping; + enum _filter_threading_t threading; + unsigned int system:1; /* this is a system rule, cannot be edited/deleted */ GList *parts; }; diff --git a/filter/rule-context.c b/filter/rule-context.c index 61fa4cbf1b..291f9d303f 100644 --- a/filter/rule-context.c +++ b/filter/rule-context.c @@ -150,6 +150,8 @@ rule_context_init(RuleContext *rc) rc->part_set_map = g_hash_table_new(g_str_hash, g_str_equal); rc->rule_set_map = g_hash_table_new(g_str_hash, g_str_equal); + + rc->flags = RULE_CONTEXT_GROUPING; } static void diff --git a/filter/rule-context.h b/filter/rule-context.h index 681ab7a61d..2f54a574f8 100644 --- a/filter/rule-context.h +++ b/filter/rule-context.h @@ -41,12 +41,20 @@ typedef struct _RuleContext RuleContext; typedef struct _RuleContextClass RuleContextClass; +/* backend capabilities, this is a hack since we don't support nested rules */ +enum { + RULE_CONTEXT_GROUPING = 1 << 0, + RULE_CONTEXT_THREADING = 1 << 1, +}; + struct _RuleContext { GObject parent_object; struct _RuleContextPrivate *priv; char *error; /* string version of error */ + guint32 flags; /* capability flags */ + GList *parts; GList *rules; diff --git a/filter/vfolder-context.c b/filter/vfolder-context.c index 9c2eee4278..a904305787 100644 --- a/filter/vfolder-context.c +++ b/filter/vfolder-context.c @@ -78,6 +78,8 @@ vfolder_context_init (VfolderContext *vc) rule_context_add_rule_set ((RuleContext *) vc, "ruleset", vfolder_rule_get_type (), rule_context_add_rule, rule_context_next_rule); + + ((RuleContext *)vc)->flags = RULE_CONTEXT_THREADING | RULE_CONTEXT_GROUPING; } static void |