aboutsummaryrefslogtreecommitdiffstats
path: root/filter
diff options
context:
space:
mode:
authorPeter Williams <peterw@src.gnome.org>2000-08-18 01:42:21 +0800
committerPeter Williams <peterw@src.gnome.org>2000-08-18 01:42:21 +0800
commit7cf30eb79276d4f255c1d603e2c203bb054cf50e (patch)
tree687a003be1d0fbcc0ff06eccd900a04c38ad7aa0 /filter
parentb3f1da4f99afadb51862fe732d66b72437224b99 (diff)
downloadgsoc2013-evolution-7cf30eb79276d4f255c1d603e2c203bb054cf50e.tar
gsoc2013-evolution-7cf30eb79276d4f255c1d603e2c203bb054cf50e.tar.gz
gsoc2013-evolution-7cf30eb79276d4f255c1d603e2c203bb054cf50e.tar.bz2
gsoc2013-evolution-7cf30eb79276d4f255c1d603e2c203bb054cf50e.tar.lz
gsoc2013-evolution-7cf30eb79276d4f255c1d603e2c203bb054cf50e.tar.xz
gsoc2013-evolution-7cf30eb79276d4f255c1d603e2c203bb054cf50e.tar.zst
gsoc2013-evolution-7cf30eb79276d4f255c1d603e2c203bb054cf50e.zip
Filtering on demand! booyeah!
svn path=/trunk/; revision=4864
Diffstat (limited to 'filter')
-rw-r--r--filter/ChangeLog42
-rw-r--r--filter/filter-driver.c22
-rw-r--r--filter/filter-driver.h1
-rw-r--r--filter/filter-editor.c79
-rw-r--r--filter/filter-rule.c31
-rw-r--r--filter/filter-rule.h8
-rw-r--r--filter/filter.glade3
-rw-r--r--filter/rule-context.c35
-rw-r--r--filter/rule-context.h9
9 files changed, 197 insertions, 33 deletions
diff --git a/filter/ChangeLog b/filter/ChangeLog
index 70950b51be..fff445dcf6 100644
--- a/filter/ChangeLog
+++ b/filter/ChangeLog
@@ -1,3 +1,45 @@
+2000-08-17 Peter Williams <peterw@helixcode.com>
+
+ Implement filtering on demand.
+
+ * rule-context.h: Add a new callback to rule_context_load
+ that allows the caller to hook on-demand rules into its UI.
+
+ * rule-context.c (rule_context_load): Changed to pass the
+ extra parameters to load().
+ (load): If the rule is successfully loaded, call the provided
+ callback so that the UI can be updated.
+
+ * filter-editor.c (rule_add): Set the source of the new filter.
+ (rule_edit): Use the new rule_context_get_rank_rule_with_source()
+ so that we don't get a bad index into the GtkList.
+ (rule_delete): Same as above.
+ (rule_up): Same as above.
+ (rule_down): Same as above.
+ (select_source): New function. When the user changes the
+ dropdown list to select a new source type, repopulate the
+ list with rules of the appropriate type.
+ (filter_editor_construct): Code moved from here into
+ select_source(). Hook up all the elements of the source optionmenu
+ to callbacks to select_source().
+
+ * filter-rule.c (xml_encode): Save the rule's source type.
+ (xml_decode): Load it. Default to 'incoming' if unspecified.
+
+ * filter-rule.h: New enumeration, _filter_source_t, the
+ specifies the rule's source. Add it to struct _FilterRule.
+
+ * filter-driver.c (filter_driver_run): Add a new input,
+ sourcetype, that specifies which rules to run (only ones
+ with the same source will be run). struct filter_mail_input_t
+ changed to accomodate.
+ (do_filter_mail): Skip rules if they're not the specified source.
+ If source and dest are the same, don't delete the messages or
+ copy unnecessarily.
+
+ * filter.glade: Make the optionmenu sensitive. Change "Outgoing"
+ to "On Demand" (outgoing should be added later).
+
2000-08-15 Peter Williams <peterw@curious-george.helixcode.com>
* vfoldertype.xml, filtertypes.xml: Add entries defining the
diff --git a/filter/filter-driver.c b/filter/filter-driver.c
index e22fc7235b..e3e1c7df5e 100644
--- a/filter/filter-driver.c
+++ b/filter/filter-driver.c
@@ -37,11 +37,14 @@
#include "filter-filter.h"
#include "e-util/e-sexp.h"
+#define d(x)
+
/* mail-thread filter input data type */
typedef struct {
FilterDriver *driver;
CamelFolder *source;
CamelFolder *inbox;
+ enum _filter_source_t sourcetype;
gboolean self_destruct;
gpointer unhook_func;
gpointer unhook_data;
@@ -414,6 +417,7 @@ static const mail_operation_spec op_filter_mail =
void
filter_driver_run (FilterDriver *d, CamelFolder *source, CamelFolder *inbox,
+ enum _filter_source_t sourcetype,
gboolean self_destruct, gpointer unhook_func, gpointer unhook_data)
{
filter_mail_input_t *input;
@@ -422,6 +426,7 @@ filter_driver_run (FilterDriver *d, CamelFolder *source, CamelFolder *inbox,
input->driver = d;
input->source = source;
input->inbox = inbox;
+ input->sourcetype = sourcetype;
input->self_destruct = self_destruct;
input->unhook_func = unhook_func;
input->unhook_data = unhook_data;
@@ -502,15 +507,20 @@ do_filter_mail (gpointer in_data, gpointer op_data, CamelException *ex)
rule = NULL;
while ( (rule = (FilterFilter *)rule_context_next_rule((RuleContext *)p->context, (FilterRule *)rule)) ) {
+
+ if (((FilterRule *)rule)->source != input->sourcetype) {
+ d(printf("skipping rule %s - wrong source type (%d %d)\n", ((FilterRule *)rule)->name,
+ ((FilterRule *)rule)->source, input->sourcetype));
+ continue;
+ }
+
g_string_truncate(s, 0);
g_string_truncate(a, 0);
filter_rule_build_code((FilterRule *)rule, s);
filter_filter_build_action(rule, a);
-#if 0
- printf("applying rule %s\n action %s\n", s->str, a->str);
-#endif
+ d(printf("applying rule %s\n action %s\n", s->str, a->str));
mail_tool_camel_lock_up ();
p->matches = camel_folder_search_by_expression (p->source, s->str, p->ex);
@@ -574,14 +584,16 @@ do_filter_mail (gpointer in_data, gpointer op_data, CamelException *ex)
copies = tmp;
}
- if (!procuid) {
+ if (!procuid && inbox != source) {
printf("Applying default rule to message %s\n", uid);
camel_folder_append_message(inbox, mm, info, p->ex);
}
camel_object_unref (CAMEL_OBJECT (mm));
}
- camel_folder_delete_message (p->source, uid);
+
+ if (inbox != source)
+ camel_folder_delete_message (p->source, uid);
mail_tool_camel_lock_down ();
}
diff --git a/filter/filter-driver.h b/filter/filter-driver.h
index 338243212a..1ef62b7118 100644
--- a/filter/filter-driver.h
+++ b/filter/filter-driver.h
@@ -56,6 +56,7 @@ FilterDriver *filter_driver_new (FilterContext *ctx, FilterGetFolderFunc fe
/* apply rules to a folder, unmatched messages goto inbox, if not NULL */
void filter_driver_run(FilterDriver *d, CamelFolder *source, CamelFolder *inbox,
+ enum _filter_source_t sourcetype,
gboolean self_destruct, gpointer unhook_func, gpointer unhook_data);
#if 0
diff --git a/filter/filter-editor.c b/filter/filter-editor.c
index 368a5fbcfc..76fe9df704 100644
--- a/filter/filter-editor.c
+++ b/filter/filter-editor.c
@@ -129,6 +129,7 @@ struct _editor_data {
FilterRule *current;
GtkList *list;
GtkButton *buttons[BUTTON_LAST];
+ enum _filter_source_t current_source;
};
static void set_sensitive(struct _editor_data *data);
@@ -144,6 +145,7 @@ static void rule_add(GtkWidget *widget, struct _editor_data *data)
d(printf("add rule\n"));
/* create a new rule with 1 match and 1 action */
rule = filter_filter_new();
+ ((FilterRule *)rule)->source = data->current_source;
part = rule_context_next_part(data->f, NULL);
filter_rule_add_part((FilterRule *)rule, filter_part_clone(part));
@@ -183,13 +185,14 @@ static void rule_edit(GtkWidget *widget, struct _editor_data *data)
d(printf("edit rule\n"));
rule = data->current;
w = filter_rule_get_widget(rule, data->f);
- gd = (GnomeDialog *)gnome_dialog_new("Edit Rule", "Ok", NULL);
+ gd = (GnomeDialog *)gnome_dialog_new("Edit Rule", GNOME_STOCK_BUTTON_OK,
+ GNOME_STOCK_BUTTON_CANCEL, NULL);
gtk_box_pack_start((GtkBox *)gd->vbox, w, FALSE, TRUE, 0);
gtk_widget_show((GtkWidget *)gd);
result = gnome_dialog_run_and_close(gd);
if (result == 0) {
- pos = rule_context_get_rank_rule(data->f, data->current);
+ pos = rule_context_get_rank_rule_with_source (data->f, data->current, data->current_source);
if (pos != -1) {
GtkListItem *item = g_list_nth_data(data->list->children, pos);
gtk_label_set_text((GtkLabel *)(((GtkBin *)item)->child), data->current->name);
@@ -204,7 +207,7 @@ static void rule_delete(GtkWidget *widget, struct _editor_data *data)
GtkListItem *item;
d(printf("ddelete rule\n"));
- pos = rule_context_get_rank_rule(data->f, data->current);
+ pos = rule_context_get_rank_rule_with_source (data->f, data->current, data->current_source);
if (pos != -1) {
rule_context_remove_rule(data->f, data->current);
@@ -240,7 +243,7 @@ static void rule_up(GtkWidget *widget, struct _editor_data *data)
int pos;
d(printf("up rule\n"));
- pos = rule_context_get_rank_rule(data->f, data->current);
+ pos = rule_context_get_rank_rule_with_source(data->f, data->current, data->current_source);
if (pos>0) {
rule_move(data, pos, pos-1);
}
@@ -251,7 +254,7 @@ static void rule_down(GtkWidget *widget, struct _editor_data *data)
int pos;
d(printf("down rule\n"));
- pos = rule_context_get_rank_rule(data->f, data->current);
+ pos = rule_context_get_rank_rule_with_source(data->f, data->current, data->current_source);
rule_move(data, pos, pos+1);
}
@@ -296,12 +299,49 @@ select_rule(GtkWidget *w, GtkWidget *child, struct _editor_data *data)
set_sensitive(data);
}
+/* FIXME: we need a way to change a rule from one source type
+ * to a different type. Maybe keep the selected ones?
+ */
+
+static void
+select_source (GtkMenuItem *mi, struct _editor_data *data)
+{
+ FilterRule *rule = NULL;
+ GList *newitems = NULL;
+ enum _filter_source_t source;
+
+ source = (enum _filter_source_t) GPOINTER_TO_INT (
+ gtk_object_get_data (GTK_OBJECT (mi), "number"));
+
+ gtk_list_clear_items (GTK_LIST (data->list), 0, -1);
+
+ d(printf("Checking for rules that are of type %d\n", source));
+ while ((rule = rule_context_next_rule (data->f, rule)) != NULL) {
+ GtkWidget *item;
+
+ if (rule->source != source) {
+ d(printf(" skipping %s: %d != %d\n", rule->name, rule->source, source));
+ continue;
+ }
+
+ d(printf(" hit %s (%d)\n", rule->name, source));
+ item = gtk_list_item_new_with_label (rule->name);
+ gtk_object_set_data (GTK_OBJECT (item), "rule", rule);
+ gtk_widget_show (GTK_WIDGET (item));
+ newitems = g_list_append (newitems, item);
+ }
+
+ gtk_list_append_items (data->list, newitems);
+ data->current_source = source;
+ data->current = NULL;
+ set_sensitive (data);
+}
+
GtkWidget *filter_editor_construct (struct _FilterContext *f)
{
GladeXML *gui;
- GtkWidget *d, *w;
+ GtkWidget *d, *w, *b, *firstitem = NULL;
GList *l;
- FilterRule *rule = NULL;
struct _editor_data *data;
int i;
@@ -320,29 +360,28 @@ GtkWidget *filter_editor_construct (struct _FilterContext *f)
gtk_signal_connect((GtkObject *)w, "clicked", edit_buttons[i].func, data);
}
- /* to be defined yet */
-#if 0
w = glade_xml_get_widget (gui, "filter_source");
l = GTK_MENU_SHELL(GTK_OPTION_MENU(w)->menu)->children;
+ i = 0;
while (l) {
- b = l->data;
+ b = GTK_WIDGET (l->data);
+
+ if (i == 0)
+ firstitem = b;
+
+ /* make sure that the glade is in sync with enum _filter_source_t! */
+ gtk_object_set_data (GTK_OBJECT (b), "number", GINT_TO_POINTER (i));
+ gtk_signal_connect (GTK_OBJECT (b), "activate", select_source, data);
+
+ i++;
l = l->next;
}
-#endif
w = glade_xml_get_widget (gui, "rule_list");
data->list = (GtkList *)w;
- l = NULL;
- while ((rule = rule_context_next_rule((RuleContext *)f, rule))) {
- GtkListItem *item = (GtkListItem *)gtk_list_item_new_with_label(rule->name);
- gtk_object_set_data((GtkObject *)item, "rule", rule);
- gtk_widget_show((GtkWidget *)item);
- l = g_list_append(l, item);
- }
- gtk_list_append_items(data->list, l);
gtk_signal_connect((GtkObject *)w, "select_child", select_rule, data);
+ select_source (GTK_MENU_ITEM (firstitem), data);
- set_sensitive(data);
gtk_object_unref((GtkObject *)gui);
return d;
diff --git a/filter/filter-rule.c b/filter/filter-rule.c
index 9c47af6daf..58a2d76518 100644
--- a/filter/filter-rule.c
+++ b/filter/filter-rule.c
@@ -158,6 +158,19 @@ static xmlNodePtr xml_encode(FilterRule *fr)
xmlSetProp(node, "grouping", "any");
break;
}
+
+ switch (fr->source) {
+ case FILTER_SOURCE_INCOMING:
+ xmlSetProp(node, "source", "incoming");
+ break;
+ case FILTER_SOURCE_DEMAND:
+ xmlSetProp(node, "source", "ondemand");
+ break;
+ case FILTER_SOURCE_OUTGOING:
+ xmlSetProp(node, "source", "outgoing");
+ break;
+ }
+
if (fr->name) {
work = xmlNewNode(NULL, "title");
xmlNodeSetContent(work, fr->name);
@@ -209,16 +222,34 @@ static int xml_decode(FilterRule *fr, xmlNodePtr node, RuleContext *f)
{
xmlNodePtr work;
char *grouping;
+ char *source;
if (fr->name) {
g_free(fr->name);
fr->name = NULL;
}
+
grouping = xmlGetProp(node, "grouping");
if (!strcmp(grouping, "any"))
fr->grouping = FILTER_GROUP_ANY;
else
fr->grouping = FILTER_GROUP_ALL;
+
+ /* FIXME: free source and grouping? */
+ source = xmlGetProp (node, "source");
+ if (!source) /*default to incoming*/
+ fr->source = FILTER_SOURCE_INCOMING;
+ else if (!strcmp (source, "outgoing"))
+ fr->source = FILTER_SOURCE_OUTGOING;
+ else if (!strcmp (source, "ondemand"))
+ fr->source = FILTER_SOURCE_DEMAND;
+ else if (!strcmp (source, "incoming"))
+ fr->source = FILTER_SOURCE_INCOMING;
+ else {
+ g_warning ("Unknown filter source type \"%s\"", source);
+ fr->source = FILTER_SOURCE_INCOMING;
+ }
+
work = node->childs;
while (work) {
if (!strcmp(work->name, "partset")) {
diff --git a/filter/filter-rule.h b/filter/filter-rule.h
index 396af19e59..425d0ac350 100644
--- a/filter/filter-rule.h
+++ b/filter/filter-rule.h
@@ -39,6 +39,13 @@ enum _filter_grouping_t {
FILTER_GROUP_ANY /* any rule must match */
};
+enum _filter_source_t {
+ FILTER_SOURCE_INCOMING, /* performed on incoming email */
+ FILTER_SOURCE_DEMAND, /* performed on the selected folder
+ * when the user asks for it */
+ FILTER_SOURCE_OUTGOING /* performed on outgoing mail */
+};
+
struct _FilterRule {
GtkObject parent;
struct _FilterRulePrivate *priv;
@@ -46,6 +53,7 @@ struct _FilterRule {
char *name;
enum _filter_grouping_t grouping;
+ enum _filter_source_t source;
GList *parts;
};
diff --git a/filter/filter.glade b/filter/filter.glade
index d9b26e4489..5f8a04d64e 100644
--- a/filter/filter.glade
+++ b/filter/filter.glade
@@ -73,10 +73,9 @@
<widget>
<class>GtkOptionMenu</class>
<name>filter_source</name>
- <sensitive>False</sensitive>
<can_focus>True</can_focus>
<items>Incoming
-Outgoing
+On Demand
</items>
<initial_choice>0</initial_choice>
<child>
diff --git a/filter/rule-context.c b/filter/rule-context.c
index c297ae1a61..8114d34197 100644
--- a/filter/rule-context.c
+++ b/filter/rule-context.c
@@ -26,7 +26,8 @@
#define d(x) x
-static int load(RuleContext *f, const char *system, const char *user);
+static int load(RuleContext *f, const char *system, const char *user,
+ RCRegisterFunc on_demand_cb, gpointer user_data);
static int save(RuleContext *f, const char *user);
static void rule_context_class_init (RuleContextClass *class);
@@ -167,19 +168,25 @@ rule_context_set_error(RuleContext *f, char *error)
* @f:
* @system:
* @user:
+ * @on_demand_cb: An optional callback to allow UI registration of on-demand rules
+ * @user_data: Extra data for the callback
*
* Load a rule context from a system and user description file.
*
* Return value:
**/
-int rule_context_load(RuleContext *f, const char *system, const char *user)
+int rule_context_load(RuleContext *f, const char *system, const char *user,
+ RCRegisterFunc on_demand_cb, gpointer user_data )
{
printf("rule_context: loading %s %s\n", system, user);
- return ((RuleContextClass *)((GtkObject *)f)->klass)->load(f, system, user);
+ return ((RuleContextClass *)((GtkObject *)f)->klass)->load(f, system, user,
+ on_demand_cb,
+ user_data);
}
-static int load(RuleContext *f, const char *system, const char *user)
+static int load(RuleContext *f, const char *system, const char *user,
+ RCRegisterFunc on_demand_cb, gpointer user_data)
{
xmlNodePtr set, rule;
struct _part_set_map *part_map;
@@ -245,6 +252,9 @@ static int load(RuleContext *f, const char *system, const char *user)
FilterRule *part = FILTER_RULE(gtk_type_new(rule_map->type));
if (filter_rule_xml_decode(part, rule, f) == 0) {
rule_map->append(f, part);
+
+ if (on_demand_cb && part->source == FILTER_SOURCE_DEMAND)
+ (on_demand_cb) (f, part, user_data);
} else {
gtk_object_unref((GtkObject *)part);
g_warning("Cannot load filter part");
@@ -398,3 +408,20 @@ int rule_context_get_rank_rule(RuleContext *f, FilterRule *rule)
{
return g_list_index(f->rules, rule);
}
+
+int
+rule_context_get_rank_rule_with_source(RuleContext *f, FilterRule *rule, enum _filter_source_t source)
+{
+ int i;
+ GList *iter;
+
+ i = 0;
+ for (iter = f->rules; iter; iter = iter->next) {
+ if (iter->data == rule)
+ return i;
+ if (((FilterRule *)iter->data)->source == source)
+ i++;
+ }
+
+ return -1;
+}
diff --git a/filter/rule-context.h b/filter/rule-context.h
index 06d32e0be3..27078adbcf 100644
--- a/filter/rule-context.h
+++ b/filter/rule-context.h
@@ -52,11 +52,14 @@ struct _RuleContext {
GList *rule_set_list;
};
+typedef void (*RCRegisterFunc)(RuleContext *f, FilterRule *rule, gpointer data);
+
struct _RuleContextClass {
GtkObjectClass parent_class;
/* virtual methods */
- int (*load)(RuleContext *f, const char *system, const char *user);
+ int (*load)(RuleContext *f, const char *system, const char *user,
+ RCRegisterFunc on_demand_cb, gpointer user_data);
int (*save)(RuleContext *f, const char *user);
/* signals */
@@ -85,7 +88,8 @@ guint rule_context_get_type (void);
RuleContext *rule_context_new (void);
/* methods */
-int rule_context_load(RuleContext *f, const char *system, const char *user);
+int rule_context_load(RuleContext *f, const char *system, const char *user,
+ RCRegisterFunc on_demand_cb, gpointer user_data);
int rule_context_save(RuleContext *f, const char *user);
void rule_context_add_part(RuleContext *f, FilterPart *new);
@@ -102,6 +106,7 @@ void rule_context_remove_rule(RuleContext *f, FilterRule *rule);
/* get/set the rank (position) of a rule */
void rule_context_rank_rule(RuleContext *f, FilterRule *rule, int rank);
int rule_context_get_rank_rule(RuleContext *f, FilterRule *rule);
+int rule_context_get_rank_rule_with_source(RuleContext *f, FilterRule *rule, enum _filter_source_t source);
void rule_context_delete_rule(RuleContext *f, FilterRule *rule);