diff options
-rw-r--r-- | filter/ChangeLog | 25 | ||||
-rw-r--r-- | filter/Makefile.am | 2 | ||||
-rw-r--r-- | filter/filter-colour.c | 14 | ||||
-rw-r--r-- | filter/filter-datespec.c | 12 | ||||
-rw-r--r-- | filter/filter-element.c | 18 | ||||
-rw-r--r-- | filter/filter-element.h | 4 | ||||
-rw-r--r-- | filter/filter-file.c | 14 | ||||
-rw-r--r-- | filter/filter-filter.c | 25 | ||||
-rw-r--r-- | filter/filter-folder.c | 9 | ||||
-rw-r--r-- | filter/filter-input.c | 26 | ||||
-rw-r--r-- | filter/filter-int.c | 70 | ||||
-rw-r--r-- | filter/filter-int.h | 9 | ||||
-rw-r--r-- | filter/filter-label.c | 95 | ||||
-rw-r--r-- | filter/filter-label.h | 10 | ||||
-rw-r--r-- | filter/filter-option.c | 12 | ||||
-rw-r--r-- | filter/filter-part.c | 29 | ||||
-rw-r--r-- | filter/filter-part.h | 1 | ||||
-rw-r--r-- | filter/filter-rule.c | 39 | ||||
-rw-r--r-- | filter/filter-rule.h | 2 | ||||
-rw-r--r-- | filter/filter-source.c | 12 | ||||
-rw-r--r-- | filter/libfilter-i18n.h | 36 | ||||
-rw-r--r-- | filter/rule-context.c | 144 | ||||
-rw-r--r-- | filter/rule-context.h | 2 | ||||
-rw-r--r-- | filter/vfolder-rule.c | 25 |
24 files changed, 496 insertions, 139 deletions
diff --git a/filter/ChangeLog b/filter/ChangeLog index 84448c091f..dabe4cdccf 100644 --- a/filter/ChangeLog +++ b/filter/ChangeLog @@ -1,3 +1,28 @@ +2002-07-10 Not Zed <NotZed@Ximian.com> + + ** fixes for #10781 + + * filter-int.c (xml_encode): + (xml_decode): Handle encoding/decoding with a type name, in a + manner compatible with the score/label elemtns. + (filter_int_new_type): New constructor to create a generic 'int' + type. + + * filter-score.c: Removed. Now relies on using a filter-int with + appropriate settings. + + * filter-label.[ch]: Now inherits from filter-int. + + * rule-context.c (rule_context_revert): New method to revert a + filter context back to a user-file's definition. + (revert): implementation. + + * filter-rule.h: Added new virtual method _eq and wrapper, and + fixed all subclasses to implement it. + + * filter-element.h: Added new virtual method _eq and wrapper. + Fixed all subclasses to implement it. + 2002-07-08 Jeffrey Stedfast <fejj@ximian.com> * filtertypes.xml: Make the sound type for (play-sound ) a "file" diff --git a/filter/Makefile.am b/filter/Makefile.am index 1a3e5d2d74..d832c3b1e0 100644 --- a/filter/Makefile.am +++ b/filter/Makefile.am @@ -48,8 +48,6 @@ libfilter_la_SOURCES = \ filter-part.h \ filter-rule.c \ filter-rule.h \ - filter-score.c \ - filter-score.h \ filter-source.h \ filter-source.c \ rule-context.c \ diff --git a/filter/filter-colour.c b/filter/filter-colour.c index 0836c30932..2a3f68b887 100644 --- a/filter/filter-colour.c +++ b/filter/filter-colour.c @@ -30,6 +30,7 @@ #define d(x) +static int colour_eq(FilterElement *fe, FilterElement *cm); static void xml_create(FilterElement *fe, xmlNodePtr node); static xmlNodePtr xml_encode(FilterElement *fe); static int xml_decode(FilterElement *fe, xmlNodePtr node); @@ -88,6 +89,7 @@ filter_colour_class_init (FilterColourClass *class) object_class->finalize = filter_colour_finalise; /* override methods */ + filter_element->eq = colour_eq; filter_element->xml_create = xml_create; filter_element->xml_encode = xml_encode; filter_element->xml_decode = xml_decode; @@ -130,6 +132,18 @@ filter_colour_new(void) return o; } +static int +colour_eq(FilterElement *fe, FilterElement *cm) +{ + FilterColour *fc = (FilterColour *)fe, *cc = (FilterColour *)cm; + + return ((FilterElementClass *)(parent_class))->eq(fe, cm) + && fc->r == cc->r + && fc->g == cc->g + && fc->b == cc->b + && fc->a == cc->a; +} + static void xml_create(FilterElement *fe, xmlNodePtr node) { /*FilterColour *fc = (FilterColour *)fe;*/ diff --git a/filter/filter-datespec.c b/filter/filter-datespec.c index fe4e5e3b32..dd8f02614e 100644 --- a/filter/filter-datespec.c +++ b/filter/filter-datespec.c @@ -46,6 +46,7 @@ #define d(x) static gboolean validate (FilterElement *fe); +static int date_eq(FilterElement *fe, FilterElement *cm); static void xml_create (FilterElement *fe, xmlNodePtr node); static xmlNodePtr xml_encode (FilterElement *fe); static int xml_decode (FilterElement *fe, xmlNodePtr node); @@ -138,6 +139,7 @@ filter_datespec_class_init (FilterDatespecClass *class) /* override methods */ filter_element->validate = validate; + filter_element->eq = date_eq; filter_element->xml_create = xml_create; filter_element->xml_encode = xml_encode; filter_element->xml_decode = xml_decode; @@ -201,6 +203,16 @@ validate (FilterElement *fe) return valid; } +static int +date_eq(FilterElement *fe, FilterElement *cm) +{ + FilterDatespec *fd = (FilterDatespec *)fe, *cd = (FilterDatespec *)cm; + + return ((FilterElementClass *)(parent_class))->eq(fe, cm) + && (fd->type == cd->type) + && (fd->value == cd->value); +} + static void xml_create (FilterElement *fe, xmlNodePtr node) { diff --git a/filter/filter-element.c b/filter/filter-element.c index cbdab0409f..fa1a6844f9 100644 --- a/filter/filter-element.c +++ b/filter/filter-element.c @@ -41,6 +41,7 @@ static gboolean validate (FilterElement *fe); +static int element_eq(FilterElement *fe, FilterElement *cm); static void xml_create(FilterElement *fe, xmlNodePtr node); static FilterElement *clone(FilterElement *fe); @@ -94,6 +95,7 @@ filter_element_class_init (FilterElementClass *class) /* override methods */ class->validate = validate; + class->eq = element_eq; class->xml_create = xml_create; class->clone = clone; @@ -138,6 +140,13 @@ filter_element_validate (FilterElement *fe) return ((FilterElementClass *)((GtkObject *)fe)->klass)->validate (fe); } +int +filter_element_eq(FilterElement *fe, FilterElement *cm) +{ + return ((GtkObject *)fe)->klass == ((GtkObject *)cm)->klass + && ((FilterElementClass *)((GtkObject *)fe)->klass)->eq(fe, cm); +} + /** * filter_element_xml_create: * @fe: filter element @@ -268,7 +277,7 @@ filter_element_new_type_name (const char *type) } else if (!strcmp (type, "datespec")) { return (FilterElement *)filter_datespec_new (); } else if (!strcmp (type, "score")) { - return (FilterElement *)filter_score_new (); + return (FilterElement *)filter_int_new_type("score", -3, 3); } else if (!strcmp (type, "integer")) { return (FilterElement *)filter_int_new (); } else if (!strcmp (type, "regex")) { @@ -300,6 +309,13 @@ validate (FilterElement *fe) return TRUE; } +static int +element_eq(FilterElement *fe, FilterElement *cm) +{ + return ((fe->name && cm->name && strcmp(fe->name, cm->name) == 0) + || (fe->name == NULL && cm->name == NULL)); +} + static void xml_create (FilterElement *fe, xmlNodePtr node) { diff --git a/filter/filter-element.h b/filter/filter-element.h index d5ff5177ce..f6570ef98d 100644 --- a/filter/filter-element.h +++ b/filter/filter-element.h @@ -48,7 +48,8 @@ struct _FilterElementClass { /* virtual methods */ gboolean (*validate)(FilterElement *fe); - + int (*eq)(FilterElement *fe, FilterElement *cm); + void (*xml_create)(FilterElement *, xmlNodePtr); xmlNodePtr (*xml_encode)(FilterElement *); int (*xml_decode)(FilterElement *, xmlNodePtr); @@ -71,6 +72,7 @@ void filter_element_set_data (FilterElement *fe, gpointer data); /* methods */ gboolean filter_element_validate (FilterElement *fe); +int filter_element_eq (FilterElement *fe, FilterElement *cm); void filter_element_xml_create (FilterElement *fe, xmlNodePtr node); diff --git a/filter/filter-file.c b/filter/filter-file.c index 7a0d1468e6..b34dd0f773 100644 --- a/filter/filter-file.c +++ b/filter/filter-file.c @@ -44,6 +44,7 @@ #define d(x) static gboolean validate (FilterElement *fe); +static int file_eq(FilterElement *fe, FilterElement *cm); static void xml_create(FilterElement *fe, xmlNodePtr node); static xmlNodePtr xml_encode(FilterElement *fe); static int xml_decode(FilterElement *fe, xmlNodePtr node); @@ -102,6 +103,7 @@ filter_file_class_init (FilterFileClass *klass) /* override methods */ filter_element->validate = validate; + filter_element->eq = file_eq; filter_element->xml_create = xml_create; filter_element->xml_encode = xml_encode; filter_element->xml_decode = xml_decode; @@ -197,6 +199,18 @@ validate (FilterElement *fe) return TRUE; } +static int +file_eq(FilterElement *fe, FilterElement *cm) +{ + FilterFile *ff = (FilterFile *)fe, *cf = (FilterFile *)cm; + + return ((FilterElementClass *)(parent_class))->eq(fe, cm) + && ((ff->path && cf->path && strcmp(ff->path, cf->path) == 0) + || (ff->path == NULL && cf->path == NULL)) + && ((ff->type && cf->type && strcmp(ff->type, cf->type) == 0) + || (ff->type == NULL && cf->type == NULL)); +} + static void xml_create (FilterElement *fe, xmlNodePtr node) { diff --git a/filter/filter-filter.c b/filter/filter-filter.c index 199018da6c..0aae6b9805 100644 --- a/filter/filter-filter.c +++ b/filter/filter-filter.c @@ -40,6 +40,7 @@ #define d(x) static int validate(FilterRule *); +static int filter_eq(FilterRule *fr, FilterRule *cm); static xmlNodePtr xml_encode (FilterRule *); static int xml_decode (FilterRule *, xmlNodePtr, struct _RuleContext *f); static void rule_copy (FilterRule *dest, FilterRule *src); @@ -98,6 +99,7 @@ filter_filter_class_init (FilterFilterClass *class) /* override methods */ filter_rule->validate = validate; + filter_rule->eq = filter_eq; filter_rule->xml_encode = xml_encode; filter_rule->xml_decode = xml_decode; /*filter_rule->build_code = build_code;*/ @@ -206,6 +208,29 @@ validate(FilterRule *fr) return valid; } +static int +list_eq(GList *al, GList *bl) +{ + int truth = TRUE; + + while (truth && al && bl) { + FilterPart *a = al->data, *b = bl->data; + + truth = filter_part_eq(a, b); + al = al->next; + bl = bl->next; + } + + return truth && al == NULL && bl == NULL; +} + +static int +filter_eq(FilterRule *fr, FilterRule *cm) +{ + return ((FilterRuleClass *)(parent_class))->eq(fr, cm) + && list_eq(((FilterFilter *)fr)->actions, ((FilterFilter *)cm)->actions); +} + static xmlNodePtr xml_encode (FilterRule *fr) { diff --git a/filter/filter-folder.c b/filter/filter-folder.c index 100b4fe253..935e19df0f 100644 --- a/filter/filter-folder.c +++ b/filter/filter-folder.c @@ -34,6 +34,7 @@ #define d(x) static gboolean validate (FilterElement *fe); +static int folder_eq(FilterElement *fe, FilterElement *cm); static void xml_create(FilterElement *fe, xmlNodePtr node); static xmlNodePtr xml_encode(FilterElement *fe); static int xml_decode(FilterElement *fe, xmlNodePtr node); @@ -89,6 +90,7 @@ filter_folder_class_init (FilterFolderClass *class) /* override methods */ filter_element->validate = validate; + filter_element->eq = folder_eq; filter_element->xml_create = xml_create; filter_element->xml_encode = xml_encode; filter_element->xml_decode = xml_decode; @@ -153,6 +155,13 @@ validate (FilterElement *fe) } } +static int +folder_eq(FilterElement *fe, FilterElement *cm) +{ + return ((FilterElementClass *)(parent_class))->eq(fe, cm) + && strcmp(((FilterFolder *)fe)->uri, ((FilterFolder *)cm)->uri) == 0; +} + static void xml_create (FilterElement *fe, xmlNodePtr node) { diff --git a/filter/filter-input.c b/filter/filter-input.c index 8343abbfa8..9be03e66c1 100644 --- a/filter/filter-input.c +++ b/filter/filter-input.c @@ -40,6 +40,7 @@ #define d(x) static gboolean validate (FilterElement *fe); +static int input_eq(FilterElement *fe, FilterElement *cm); static void xml_create(FilterElement *fe, xmlNodePtr node); static xmlNodePtr xml_encode(FilterElement *fe); static int xml_decode(FilterElement *fe, xmlNodePtr node); @@ -99,6 +100,7 @@ filter_input_class_init (FilterInputClass *class) /* override methods */ filter_element->validate = validate; + filter_element->eq = input_eq; filter_element->xml_create = xml_create; filter_element->xml_encode = xml_encode; filter_element->xml_decode = xml_decode; @@ -213,6 +215,30 @@ validate (FilterElement *fe) return valid; } +static int +list_eq(GList *al, GList *bl) +{ + int truth = TRUE; + + while (truth && al && bl) { + truth = strcmp((char *)al->data, (char *)bl->data) == 0; + al = al->next; + bl = bl->next; + } + + return truth && al == NULL && bl == NULL; +} + +static int +input_eq(FilterElement *fe, FilterElement *cm) +{ + FilterInput *fi = (FilterInput *)fe, *ci = (FilterInput *)cm; + + return ((FilterElementClass *)(parent_class))->eq(fe, cm) + && strcmp(fi->type, ci->type) == 0 + && list_eq(fi->values, ci->values); +} + static void xml_create (FilterElement *fe, xmlNodePtr node) { diff --git a/filter/filter-int.c b/filter/filter-int.c index 25d70e43e2..a92b0b1b2b 100644 --- a/filter/filter-int.c +++ b/filter/filter-int.c @@ -32,6 +32,7 @@ #define d(x) +static int int_eq(FilterElement *fe, FilterElement *cm); static void xml_create (FilterElement *fe, xmlNodePtr node); static xmlNodePtr xml_encode (FilterElement *fe); static int xml_decode (FilterElement *fe, xmlNodePtr node); @@ -90,6 +91,7 @@ filter_int_class_init (FilterIntClass *class) object_class->finalize = filter_int_finalise; /* override methods */ + filter_element->eq = int_eq; filter_element->xml_create = xml_create; filter_element->xml_encode = xml_encode; filter_element->xml_decode = xml_decode; @@ -105,6 +107,8 @@ filter_int_class_init (FilterIntClass *class) static void filter_int_init (FilterInt *o) { + o->min = 0; + o->max = G_MAXINT; o->priv = g_malloc0 (sizeof (*o->priv)); } @@ -112,8 +116,8 @@ static void filter_int_finalise(GtkObject *obj) { FilterInt *o = (FilterInt *)obj; - - o = o; + + g_free(o->type); ((GtkObjectClass *)(parent_class))->finalize(obj); } @@ -132,6 +136,29 @@ filter_int_new (void) return o; } +FilterInt * +filter_int_new_type(const char *type, int min, int max) +{ + FilterInt *o = (FilterInt *)gtk_type_new(filter_int_get_type ()); + o->type = g_strdup(type); + o->min = min; + o->max = max; + return o; +} + +void +filter_int_set_value(FilterInt *fi, int val) +{ + fi->val = val; +} + +static int +int_eq(FilterElement *fe, FilterElement *cm) +{ + return ((FilterElementClass *)(parent_class))->eq(fe, cm) + && ((FilterInt *)fe)->val == ((FilterInt *)cm)->val; +} + static void xml_create (FilterElement *fe, xmlNodePtr node) { @@ -144,17 +171,19 @@ xml_encode (FilterElement *fe) { xmlNodePtr value; FilterInt *fs = (FilterInt *)fe; - char *intval; + char intval[32]; + const char *type; - d(printf("Encoding integer as xml\n")); + type = fs->type?fs->type:"integer"; + + d(printf("Encoding %s as xml\n", type)); value = xmlNewNode (NULL, "value"); xmlSetProp (value, "name", fe->name); - xmlSetProp (value, "type", "integer"); + xmlSetProp (value, "type", type); - intval = g_strdup_printf ("%d", fs->val); - xmlSetProp (value, "integer", intval); - g_free (intval); + sprintf(intval, "%d", fs->val); + xmlSetProp (value, type, intval); return value; } @@ -163,7 +192,7 @@ static int xml_decode (FilterElement *fe, xmlNodePtr node) { FilterInt *fs = (FilterInt *)fe; - char *name; + char *name, *type; char *intval; d(printf("Decoding integer from xml %p\n", fe)); @@ -172,7 +201,13 @@ xml_decode (FilterElement *fe, xmlNodePtr node) d(printf ("Name = %s\n", name)); xmlFree (fe->name); fe->name = name; - intval = xmlGetProp (node, "integer"); + + type = xmlGetProp(node, "type"); + g_free(fs->type); + fs->type = g_strdup(type); + xmlFree(type); + + intval = xmlGetProp (node, type?type:"integer"); if (intval) { fs->val = atoi (intval); xmlFree (intval); @@ -197,14 +232,12 @@ get_widget (FilterElement *fe) GtkObject *adjustment; FilterInt *fs = (FilterInt *)fe; - adjustment = gtk_adjustment_new (0.0, 0.0, (gfloat)G_MAXINT, - 1.0, 1.0, 1.0); - spin = gtk_spin_button_new (GTK_ADJUSTMENT (adjustment), 5.0, 0); + adjustment = gtk_adjustment_new (0.0, (gfloat)fs->min, (gfloat)fs->max, 1.0, 1.0, 1.0); + spin = gtk_spin_button_new (GTK_ADJUSTMENT (adjustment), fs->max>fs->min+1000?5.0:1.0, 0); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE); - if (fs->val) { + if (fs->val) gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), (gfloat) fs->val); - } gtk_signal_connect (GTK_OBJECT (spin), "changed", spin_changed, fe); @@ -221,9 +254,6 @@ static void format_sexp (FilterElement *fe, GString *out) { FilterInt *fs = (FilterInt *)fe; - char *str; - - str = g_strdup_printf ("%d", fs->val); - g_string_append (out, str); - g_free (str); + + g_string_sprintfa(out, "%d", fs->val); } diff --git a/filter/filter-int.h b/filter/filter-int.h index 7a451f29ff..4ed508cd36 100644 --- a/filter/filter-int.h +++ b/filter/filter-int.h @@ -37,8 +37,11 @@ typedef struct _FilterIntClass FilterIntClass; struct _FilterInt { FilterElement parent; struct _FilterIntPrivate *priv; - - gint32 val; + + char *type; + int val; + int min; + int max; }; struct _FilterIntClass { @@ -51,6 +54,8 @@ struct _FilterIntClass { guint filter_int_get_type (void); FilterInt *filter_int_new (void); +FilterInt *filter_int_new_type(const char *type, int min, int max); +void filter_int_set_value(FilterInt *fi, int val); /* methods */ diff --git a/filter/filter-label.c b/filter/filter-label.c index 0262c3d5f8..fb921eef61 100644 --- a/filter/filter-label.c +++ b/filter/filter-label.c @@ -50,11 +50,7 @@ static gboolean validate (FilterElement *fe); static void xml_create (FilterElement *fe, xmlNodePtr node); -static xmlNodePtr xml_encode (FilterElement *fe); -static int xml_decode (FilterElement *fe, xmlNodePtr node); static GtkWidget *get_widget (FilterElement *fe); -static void build_code (FilterElement *fe, GString *out, struct _FilterPart *ff); -static void format_sexp (FilterElement *fe, GString *out); static void filter_label_class_init (FilterLabelClass *klass); static void filter_label_init (FilterLabel *label); @@ -86,7 +82,7 @@ filter_label_get_type (void) (GtkArgGetFunc) NULL }; - type = gtk_type_unique (filter_element_get_type (), &type_info); + type = gtk_type_unique (filter_int_get_type (), &type_info); } return type; @@ -98,18 +94,14 @@ filter_label_class_init (FilterLabelClass *klass) GtkObjectClass *object_class = (GtkObjectClass *) klass; FilterElementClass *filter_element = (FilterElementClass *) klass; - parent_class = gtk_type_class (filter_element_get_type ()); + parent_class = gtk_type_class (filter_int_get_type ()); object_class->finalize = filter_label_finalise; /* override methods */ filter_element->validate = validate; filter_element->xml_create = xml_create; - filter_element->xml_encode = xml_encode; - filter_element->xml_decode = xml_decode; filter_element->get_widget = get_widget; - filter_element->build_code = build_code; - filter_element->format_sexp = format_sexp; /* signals */ @@ -141,20 +133,13 @@ filter_label_new (void) return (FilterLabel *) gtk_type_new (filter_label_get_type ()); } - -void -filter_label_set_label (FilterLabel *filter, int label) -{ - filter->label = label; -} - static gboolean validate (FilterElement *fe) { - FilterLabel *label = (FilterLabel *) fe; + FilterInt *label = (FilterInt *)fe; GtkWidget *dialog; - if (label->label < 0 || label->label > 4) { + if (label->val < 0 || label->val > 4) { dialog = gnome_ok_dialog (_("You must specify a label name")); gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); @@ -172,65 +157,18 @@ xml_create (FilterElement *fe, xmlNodePtr node) } -static xmlNodePtr -xml_encode (FilterElement *fe) -{ - FilterLabel *label = (FilterLabel *) fe; - xmlNodePtr value; - char *encstr; - - d(printf ("Encoding label as xml\n")); - - encstr = g_strdup_printf ("%d", label->label); - - value = xmlNewNode (NULL, "value"); - xmlSetProp (value, "name", fe->name); - xmlSetProp (value, "type", "label"); - xmlSetProp (value, "label", encstr); - g_free (encstr); - - return value; -} - -static int -xml_decode (FilterElement *fe, xmlNodePtr node) -{ - FilterLabel *label = (FilterLabel *) fe; - char *name, *str, *type; - - type = xmlGetProp (node, "type"); - if (strcmp (type, "label") != 0) { - xmlFree (type); - return -1; - } - - xmlFree (type); - - d(printf("Decoding label from xml %p\n", fe)); - - name = xmlGetProp (node, "name"); - xmlFree (fe->name); - fe->name = name; - - str = xmlGetProp (node, "label"); - label->label = atoi (str); - xmlFree (str); - - return 0; -} - static void label_selected (GtkWidget *item, gpointer user_data) { - FilterLabel *label = user_data; + FilterInt *label = user_data; - label->label = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (item), "label")); + label->val = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (item), "label")); } static GtkWidget * get_widget (FilterElement *fe) { - FilterLabel *label = (FilterLabel *) fe; + FilterInt *label = (FilterInt *) fe; GtkWidget *omenu, *menu, *item; Bonobo_ConfigDatabase db; CORBA_Environment ev; @@ -282,24 +220,7 @@ get_widget (FilterElement *fe) g_free (path); gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu); - gtk_option_menu_set_history (GTK_OPTION_MENU (omenu), label->label); + gtk_option_menu_set_history (GTK_OPTION_MENU (omenu), label->val); return omenu; } - -static void -build_code (FilterElement *fe, GString *out, struct _FilterPart *ff) -{ - return; -} - -static void -format_sexp (FilterElement *fe, GString *out) -{ - FilterLabel *label = (FilterLabel *) fe; - char *str; - - str = g_strdup_printf ("%d", label->label); - g_string_append (out, str); - g_free (str); -} diff --git a/filter/filter-label.h b/filter/filter-label.h index 384e0864aa..0e78b6d3c1 100644 --- a/filter/filter-label.h +++ b/filter/filter-label.h @@ -29,7 +29,7 @@ extern "C" { #pragma } #endif /* __cplusplus */ -#include "filter-element.h" +#include "filter-int.h" #define FILTER_LABEL(obj) GTK_CHECK_CAST (obj, filter_label_get_type (), FilterLabel) #define FILTER_LABEL_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_label_get_type (), FilterLabelClass) @@ -39,13 +39,11 @@ typedef struct _FilterLabel FilterLabel; typedef struct _FilterLabelClass FilterLabelClass; struct _FilterLabel { - FilterElement parent; - - int label; + FilterInt parent; }; struct _FilterLabelClass { - FilterElementClass parent_class; + FilterIntClass parent_class; /* virtual methods */ @@ -56,8 +54,6 @@ GtkType filter_label_get_type (void); FilterLabel *filter_label_new (void); -void filter_label_set_label (FilterLabel *filter, int label); - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/filter/filter-option.c b/filter/filter-option.c index b0e1abc3d0..4102cd5eaf 100644 --- a/filter/filter-option.c +++ b/filter/filter-option.c @@ -34,6 +34,7 @@ #define d(x) +static int option_eq(FilterElement *fe, FilterElement *cm); static void xml_create(FilterElement *fe, xmlNodePtr node); static xmlNodePtr xml_encode(FilterElement *fe); static int xml_decode(FilterElement *fe, xmlNodePtr node); @@ -93,6 +94,7 @@ filter_option_class_init (FilterOptionClass *class) object_class->finalize = filter_option_finalise; /* override methods */ + filter_element->eq = option_eq; filter_element->xml_create = xml_create; filter_element->xml_encode = xml_encode; filter_element->xml_decode = xml_decode; @@ -171,6 +173,16 @@ filter_option_set_current (FilterOption *option, const char *name) option->current = find_option (option, name); } +static int +option_eq(FilterElement *fe, FilterElement *cm) +{ + FilterOption *fo = (FilterOption *)fe, *co = (FilterOption *)cm; + + return ((FilterElementClass *)(parent_class))->eq(fe, cm) + && ((fo->current && co->current && strcmp(fo->current->value, co->current->value) == 0) + || (fo->current == NULL && co->current == NULL)); +} + static void xml_create (FilterElement *fe, xmlNodePtr node) { diff --git a/filter/filter-part.c b/filter/filter-part.c index e92c42aafb..3f05341c81 100644 --- a/filter/filter-part.c +++ b/filter/filter-part.c @@ -153,10 +153,37 @@ filter_part_validate (FilterPart *fp) } int +filter_part_eq(FilterPart *fp, FilterPart *fc) +{ + int truth; + GList *al, *bl; + + truth = ((fp->name && fc->name && strcmp(fp->name, fc->name) == 0) + || (fp->name == NULL && fc->name == NULL)) + && ((fp->title && fc->title && strcmp(fp->title, fc->title) == 0) + || (fp->title == NULL && fc->title == NULL)) + && ((fp->code && fc->code && strcmp(fp->code, fc->code) == 0) + || (fp->code == NULL && fc->code == NULL)); + + al = fp->elements; + bl = fc->elements; + while (truth && al && bl) { + FilterElement *a = al->data, *b = bl->data; + + truth = filter_element_eq(a, b); + + al = al->next; + bl = bl->next; + } + + return truth && al == NULL && bl == NULL; +} + +int filter_part_xml_create (FilterPart *ff, xmlNodePtr node) { xmlNodePtr n; - char *type, *str, *decstr; + char *type, *str; FilterElement *el; str = xmlGetProp(node, "name"); diff --git a/filter/filter-part.h b/filter/filter-part.h index 904be6b191..e47f9a28f2 100644 --- a/filter/filter-part.h +++ b/filter/filter-part.h @@ -54,6 +54,7 @@ FilterPart *filter_part_new (void); /* methods */ gboolean filter_part_validate (FilterPart *fp); +int filter_part_eq (FilterPart *fp, FilterPart *fc); int filter_part_xml_create (FilterPart *ff, xmlNodePtr node); diff --git a/filter/filter-rule.c b/filter/filter-rule.c index 89e0d76726..4adffeaf3c 100644 --- a/filter/filter-rule.c +++ b/filter/filter-rule.c @@ -41,6 +41,7 @@ #define d(x) static int validate(FilterRule *); +static int rule_eq(FilterRule *fr, FilterRule *cm); static xmlNodePtr xml_encode (FilterRule *); static int xml_decode (FilterRule *, xmlNodePtr, RuleContext *); static void build_code (FilterRule *, GString * out); @@ -100,6 +101,7 @@ filter_rule_class_init (FilterRuleClass * class) /* override methods */ class->validate = validate; + class->eq = rule_eq; class->xml_encode = xml_encode; class->xml_decode = xml_decode; class->build_code = build_code; @@ -231,6 +233,43 @@ validate (FilterRule *fr) return valid; } +int +filter_rule_eq(FilterRule *fr, FilterRule *cm) +{ + g_assert(IS_FILTER_RULE(fr)); + g_assert(IS_FILTER_RULE(cm)); + + return ((GtkObject *)fr)->klass == ((GtkObject *)cm)->klass + && ((FilterRuleClass *) ((GtkObject *) fr)->klass)->eq(fr, cm); +} + +static int +list_eq(GList *al, GList *bl) +{ + int truth = TRUE; + + while (truth && al && bl) { + FilterPart *a = al->data, *b = bl->data; + + truth = filter_part_eq(a, b); + al = al->next; + bl = bl->next; + } + + return truth && al == NULL && bl == NULL; +} + +static int +rule_eq(FilterRule *fr, FilterRule *cm) +{ + return fr->grouping == cm->grouping + && ( (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) + || (fr->source == NULL && cm->source == NULL) ) + && list_eq(fr->parts, cm->parts); +} + xmlNodePtr filter_rule_xml_encode (FilterRule *fr) { diff --git a/filter/filter-rule.h b/filter/filter-rule.h index f0558d0f2b..5e4793c872 100644 --- a/filter/filter-rule.h +++ b/filter/filter-rule.h @@ -60,6 +60,7 @@ struct _FilterRuleClass { /* virtual methods */ int (*validate)(FilterRule *); + int (*eq)(FilterRule *fr, FilterRule *cm); xmlNodePtr (*xml_encode)(FilterRule *); int (*xml_decode)(FilterRule *, xmlNodePtr, struct _RuleContext *); @@ -84,6 +85,7 @@ void filter_rule_set_name (FilterRule *fr, const char *name); void filter_rule_set_source (FilterRule *fr, const char *source); int filter_rule_validate (FilterRule *fr); +int filter_rule_eq (FilterRule *fr, FilterRule *cm); xmlNodePtr filter_rule_xml_encode (FilterRule *fr); int filter_rule_xml_decode (FilterRule *fr, xmlNodePtr node, struct _RuleContext *f); diff --git a/filter/filter-source.c b/filter/filter-source.c index fee37f5ad1..83e20d1bd5 100644 --- a/filter/filter-source.c +++ b/filter/filter-source.c @@ -65,6 +65,7 @@ static void filter_source_class_init (FilterSourceClass *); static void filter_source_init (FilterSource *); static void filter_source_finalize (GtkObject *); +static int source_eq(FilterElement *fe, FilterElement *cm); static void xml_create(FilterElement *fe, xmlNodePtr node); static xmlNodePtr xml_encode(FilterElement *fe); static int xml_decode(FilterElement *fe, xmlNodePtr node); @@ -112,6 +113,7 @@ filter_source_class_init (FilterSourceClass *class) object_class->finalize = filter_source_finalize; /* override methods */ + filter_element->eq = source_eq; filter_element->xml_create = xml_create; filter_element->xml_encode = xml_encode; filter_element->xml_decode = xml_decode; @@ -164,6 +166,16 @@ filter_source_new (void) return s; } +static int +source_eq(FilterElement *fe, FilterElement *cm) +{ + FilterSource *fs = (FilterSource *)fe, *cs = (FilterSource *)cm; + + return ((FilterElementClass *)parent_class)->eq(fe, cm) + && ((fs->priv->current_url && cs->priv->current_url && strcmp(fs->priv->current_url, cs->priv->current_url) == 0) + || (fs->priv->current_url == NULL && cs->priv->current_url == NULL)); +} + static void xml_create (FilterElement *fe, xmlNodePtr node) { diff --git a/filter/libfilter-i18n.h b/filter/libfilter-i18n.h index 9d930d930b..982ebae371 100644 --- a/filter/libfilter-i18n.h +++ b/filter/libfilter-i18n.h @@ -5,34 +5,18 @@ char *s = N_("Assign Score"); char *s = N_("Attachments"); char *s = N_("Beep"); char *s = N_("Command"); -char *s = N_("contains"); char *s = N_("Copy to Folder"); char *s = N_("Date received"); char *s = N_("Date sent"); char *s = N_("Delete"); char *s = N_("Deleted"); -char *s = N_("does not contain"); -char *s = N_("does not end with"); -char *s = N_("does not exist"); -char *s = N_("does not sound like"); -char *s = N_("does not start with"); char *s = N_("Do Not Exist"); char *s = N_("Draft"); -char *s = N_("ends with"); char *s = N_("Execute Shell Command"); char *s = N_("Exist"); -char *s = N_("exists"); char *s = N_("Expression"); char *s = N_("Follow Up"); char *s = N_("Important"); -char *s = N_("is"); -char *s = N_("is after"); -char *s = N_("is before"); -char *s = N_("is Flagged"); -char *s = N_("is greater than"); -char *s = N_("is less than"); -char *s = N_("is not"); -char *s = N_("is not Flagged"); char *s = N_("Label"); char *s = N_("Mailing list"); char *s = N_("Message Body"); @@ -47,10 +31,26 @@ char *s = N_("Score"); char *s = N_("Sender"); char *s = N_("Set Status"); char *s = N_("Size (kB)"); -char *s = N_("sounds like"); char *s = N_("Source Account"); char *s = N_("Specific header"); -char *s = N_("starts with"); char *s = N_("Status"); char *s = N_("Stop Processing"); char *s = N_("Subject"); +char *s = N_("contains"); +char *s = N_("does not contain"); +char *s = N_("does not end with"); +char *s = N_("does not exist"); +char *s = N_("does not sound like"); +char *s = N_("does not start with"); +char *s = N_("ends with"); +char *s = N_("exists"); +char *s = N_("is Flagged"); +char *s = N_("is after"); +char *s = N_("is before"); +char *s = N_("is greater than"); +char *s = N_("is less than"); +char *s = N_("is not Flagged"); +char *s = N_("is not"); +char *s = N_("is"); +char *s = N_("sounds like"); +char *s = N_("starts with"); diff --git a/filter/rule-context.c b/filter/rule-context.c index 18939a0041..490c169d05 100644 --- a/filter/rule-context.c +++ b/filter/rule-context.c @@ -38,6 +38,7 @@ static int load(RuleContext * f, const char *system, const char *user); static int save(RuleContext * f, const char *user); +static int revert(RuleContext *f, const char *user); static GList *rename_uri(RuleContext *f, const char *olduri, const char *newuri, GCompareFunc cmp); static GList *delete_uri(RuleContext *f, const char *uri, GCompareFunc cmp); @@ -97,6 +98,7 @@ rule_context_class_init (RuleContextClass * class) /* override methods */ class->load = load; class->save = save; + class->revert = revert; class->rename_uri = rename_uri; class->delete_uri = delete_uri; @@ -418,6 +420,148 @@ save (RuleContext *f, const char *user) return ret; } +/** + * rule_context_revert: + * @f: + * @user: + * + * Reverts a rule context from a user description file. Assumes the + * system description file is unchanged from when it was loaded. + * + * Return value: + **/ +int +rule_context_revert(RuleContext *f, const char *user) +{ + g_assert(f); + + d(printf("rule_context: restoring %s %s\n", user)); + + return ((RuleContextClass *) ((GtkObject *) f)->klass)->revert(f, user); +} + +struct _revert_data { + GHashTable *rules; + int rank; +}; + +static void +revert_rule_remove(void *key, FilterRule *frule, RuleContext *f) +{ + rule_context_remove_rule(f, frule); + gtk_object_unref((GtkObject *)frule); +} + +static void +revert_source_remove(void *key, struct _revert_data *rest_data, RuleContext *f) +{ + g_hash_table_foreach(rest_data->rules, (GHFunc)revert_rule_remove, f); + g_hash_table_destroy(rest_data->rules); + g_free(rest_data); +} + +static guint source_hashf(const char *a) +{ + if (a) + return g_str_hash(a); + return 0; +} + +static int source_eqf(const char *a, const char *b) +{ + return (a && b && strcmp(a, b) == 0) + || (a == NULL && b == NULL); +} + +static int +revert(RuleContext *f, const char *user) +{ + xmlNodePtr set, rule; + /*struct _part_set_map *part_map;*/ + struct _rule_set_map *rule_map; + struct _revert_data *rest_data; + GHashTable *source_hash; + xmlDocPtr userdoc; + FilterRule *frule; + + rule_context_set_error (f, NULL); + + d(printf("restoring rules %s %s\n", user)); + + userdoc = xmlParseFile (user); + if (userdoc == NULL) + /* clear out anythign we have? */ + return 0; + + source_hash = g_hash_table_new((GHashFunc)source_hashf, (GCompareFunc)source_eqf); + + /* setup stuff we have now */ + /* Note that we assume there is only 1 set of rules in a given rule context, + although other parts of the code dont assume this */ + frule = NULL; + while ((frule = rule_context_next_rule(f, frule, NULL))) { + rest_data = g_hash_table_lookup(source_hash, frule->source); + if (rest_data == NULL) { + rest_data = g_malloc0(sizeof(*rest_data)); + rest_data->rules = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(source_hash, frule->source, rest_data); + } + g_hash_table_insert(rest_data->rules, frule->name, frule); + } + + /* make what we have, match what we load */ + set = userdoc->root->childs; + while (set) { + d(printf("set name = %s\n", set->name)); + rule_map = g_hash_table_lookup (f->rule_set_map, set->name); + if (rule_map) { + d(printf("loading rules ...\n")); + rule = set->childs; + while (rule) { + d(printf("checking node: %s\n", rule->name)); + if (!strcmp (rule->name, "rule")) { + FilterRule *part = FILTER_RULE(gtk_type_new (rule_map->type)); + + if (filter_rule_xml_decode (part, rule, f) == 0) { + /* use the revert data to keep track of the right rank of this rule part */ + rest_data = g_hash_table_lookup(source_hash, part->source); + if (rest_data == NULL) { + rest_data = g_malloc0(sizeof(*rest_data)); + rest_data->rules = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(source_hash, part->source, rest_data); + } + frule = g_hash_table_lookup(rest_data->rules, part->name); + if (frule) { + if (f->priv->frozen == 0 && !filter_rule_eq(frule, part)) + filter_rule_copy(frule, part); + gtk_object_unref (GTK_OBJECT (part)); + rule_context_rank_rule(f, frule, rest_data->rank); + g_hash_table_remove(rest_data->rules, frule->name); + } else { + rule_context_add_rule(f, part); + rule_context_rank_rule(f, part, rest_data->rank); + } + rest_data->rank++; + } else { + gtk_object_unref (GTK_OBJECT (part)); + g_warning ("Cannot load filter part"); + } + } + rule = rule->next; + } + } + set = set->next; + } + + xmlFreeDoc(userdoc); + + /* remove any we still have that weren't in the file */ + g_hash_table_foreach(source_hash, (GHFunc)revert_source_remove, f); + g_hash_table_destroy(source_hash); + + return 0; +} + FilterPart * rule_context_find_part (RuleContext *f, const char *name) { diff --git a/filter/rule-context.h b/filter/rule-context.h index 56c1bb491e..60d0d6f932 100644 --- a/filter/rule-context.h +++ b/filter/rule-context.h @@ -60,6 +60,7 @@ struct _RuleContextClass { /* virtual methods */ int (*load)(RuleContext *f, const char *system, const char *user); int (*save)(RuleContext *f, const char *user); + int (*revert)(RuleContext *f, const char *user); GList *(*delete_uri)(RuleContext *f, const char *uri, GCompareFunc cmp); GList *(*rename_uri)(RuleContext *f, const char *olduri, const char *newuri, GCompareFunc cmp); @@ -95,6 +96,7 @@ RuleContext *rule_context_new (void); /* methods */ int rule_context_load(RuleContext *f, const char *system, const char *user); int rule_context_save(RuleContext *f, const char *user); +int rule_context_revert(RuleContext *f, const char *user); void rule_context_add_part(RuleContext *f, FilterPart *new); FilterPart *rule_context_find_part(RuleContext *f, const char *name); diff --git a/filter/vfolder-rule.c b/filter/vfolder-rule.c index 36b381eb06..053561b4eb 100644 --- a/filter/vfolder-rule.c +++ b/filter/vfolder-rule.c @@ -39,6 +39,7 @@ #define d(x) x static gint validate(FilterRule *); +static int vfolder_eq(FilterRule *fr, FilterRule *cm); static xmlNodePtr xml_encode(FilterRule *); static int xml_decode(FilterRule *, xmlNodePtr, struct _RuleContext *f); static void rule_copy (FilterRule *dest, FilterRule *src); @@ -93,6 +94,7 @@ vfolder_rule_class_init (VfolderRuleClass *class) /* override methods */ filter_rule->validate = validate; + filter_rule->eq = vfolder_eq; filter_rule->xml_encode = xml_encode; filter_rule->xml_decode = xml_decode; filter_rule->copy = rule_copy; @@ -222,6 +224,29 @@ validate (FilterRule *fr) return 1; } +static int +list_eq(GList *al, GList *bl) +{ + int truth = TRUE; + + while (truth && al && bl) { + char *a = al->data, *b = bl->data; + + truth = strcmp(a, b) == 0; + al = al->next; + bl = bl->next; + } + + return truth && al == NULL && bl == NULL; +} + +static int +vfolder_eq(FilterRule *fr, FilterRule *cm) +{ + return ((FilterRuleClass *)(parent_class))->eq(fr, cm) + && list_eq(((VfolderRule *)fr)->sources, ((VfolderRule *)cm)->sources); +} + static xmlNodePtr xml_encode (FilterRule *fr) { |