aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-10-25 21:17:23 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-10-27 21:25:01 +0800
commit2b16aef84141800099f859e72d05e1e6bf8e02dd (patch)
treeb7168d8e9a4157a1f6733b0c667dd6239c5e0055
parent58166e645971a4812fef23702f45cacc8e64e419 (diff)
downloadgsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar.gz
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar.bz2
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar.lz
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar.xz
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.tar.zst
gsoc2013-evolution-2b16aef84141800099f859e72d05e1e6bf8e02dd.zip
Cleanup and rename filter classes.
-rw-r--r--addressbook/gui/widgets/e-addressbook-view.c2
-rw-r--r--e-util/e-util.c4
-rw-r--r--filter/Makefile.am72
-rw-r--r--filter/e-filter-code.c126
-rw-r--r--filter/e-filter-code.h68
-rw-r--r--filter/e-filter-color.c180
-rw-r--r--filter/e-filter-color.h70
-rw-r--r--filter/e-filter-datespec.c (renamed from filter/filter-datespec.c)376
-rw-r--r--filter/e-filter-datespec.h87
-rw-r--r--filter/e-filter-element.c472
-rw-r--r--filter/e-filter-element.h118
-rw-r--r--filter/e-filter-file.c278
-rw-r--r--filter/e-filter-file.h74
-rw-r--r--filter/e-filter-input.c322
-rw-r--r--filter/e-filter-input.h74
-rw-r--r--filter/e-filter-int.c261
-rw-r--r--filter/e-filter-int.h77
-rw-r--r--filter/e-filter-option.c514
-rw-r--r--filter/e-filter-option.h92
-rw-r--r--filter/e-filter-part.c532
-rw-r--r--filter/e-filter-part.h104
-rw-r--r--filter/e-filter-rule.c1116
-rw-r--r--filter/e-filter-rule.h161
-rw-r--r--filter/e-rule-context.c988
-rw-r--r--filter/e-rule-context.h215
-rw-r--r--filter/e-rule-editor.c912
-rw-r--r--filter/e-rule-editor.h122
-rw-r--r--filter/filter-code.c136
-rw-r--r--filter/filter-code.h56
-rw-r--r--filter/filter-colour.c219
-rw-r--r--filter/filter-colour.h58
-rw-r--r--filter/filter-datespec.h75
-rw-r--r--filter/filter-element.c336
-rw-r--r--filter/filter-element.h93
-rw-r--r--filter/filter-file.c292
-rw-r--r--filter/filter-file.h67
-rw-r--r--filter/filter-input.c360
-rw-r--r--filter/filter-input.h62
-rw-r--r--filter/filter-int.c270
-rw-r--r--filter/filter-int.h62
-rw-r--r--filter/filter-option.c497
-rw-r--r--filter/filter-option.h75
-rw-r--r--filter/filter-part.c541
-rw-r--r--filter/filter-part.h89
-rw-r--r--filter/filter-rule.c1044
-rw-r--r--filter/filter-rule.h134
-rw-r--r--filter/rule-context.c952
-rw-r--r--filter/rule-context.h149
-rw-r--r--filter/rule-editor.c880
-rw-r--r--filter/rule-editor.h104
-rw-r--r--mail/e-mail-reader-utils.c8
-rw-r--r--mail/em-filter-context.c86
-rw-r--r--mail/em-filter-context.h14
-rw-r--r--mail/em-filter-editor.c28
-rw-r--r--mail/em-filter-editor.h6
-rw-r--r--mail/em-filter-folder-element.c49
-rw-r--r--mail/em-filter-folder-element.h6
-rw-r--r--mail/em-filter-rule.c112
-rw-r--r--mail/em-filter-rule.h12
-rw-r--r--mail/em-filter-source-element.c52
-rw-r--r--mail/em-filter-source-element.h6
-rw-r--r--mail/em-folder-utils.c2
-rw-r--r--mail/em-search-context.c30
-rw-r--r--mail/em-search-context.h8
-rw-r--r--mail/em-utils.c8
-rw-r--r--mail/em-vfolder-context.c36
-rw-r--r--mail/em-vfolder-context.h6
-rw-r--r--mail/em-vfolder-editor.c22
-rw-r--r--mail/em-vfolder-editor.h6
-rw-r--r--mail/em-vfolder-rule.c52
-rw-r--r--mail/em-vfolder-rule.h6
-rw-r--r--mail/mail-autofilter.c140
-rw-r--r--mail/mail-autofilter.h8
-rw-r--r--mail/mail-ops.c4
-rw-r--r--mail/mail-send-recv.c12
-rw-r--r--mail/mail-session.c20
-rw-r--r--mail/mail-tools.c4
-rw-r--r--mail/mail-vfolder.c102
-rw-r--r--mail/mail-vfolder.h8
-rw-r--r--modules/addressbook/e-book-shell-view-actions.c2
-rw-r--r--modules/addressbook/e-book-shell-view.c8
-rw-r--r--modules/calendar/e-cal-shell-view.c8
-rw-r--r--modules/calendar/e-memo-shell-view.c8
-rw-r--r--modules/calendar/e-task-shell-view.c8
-rw-r--r--modules/mail/e-mail-shell-backend.c2
-rw-r--r--modules/mail/e-mail-shell-view-actions.c8
-rw-r--r--modules/mail/e-mail-shell-view-private.c14
-rw-r--r--modules/mail/e-mail-shell-view-private.h4
-rw-r--r--modules/mail/e-mail-shell-view.c20
-rw-r--r--plugins/groupwise-features/share-folder-common.c4
-rw-r--r--shell/e-shell-content.c98
-rw-r--r--shell/e-shell-content.h12
-rw-r--r--shell/e-shell-window-actions.c14
93 files changed, 7712 insertions, 7319 deletions
diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c
index 8d07a8007a..1583f26c92 100644
--- a/addressbook/gui/widgets/e-addressbook-view.c
+++ b/addressbook/gui/widgets/e-addressbook-view.c
@@ -29,7 +29,7 @@
#include <table/e-cell-date.h>
#include <misc/e-gui-utils.h>
#include <widgets/menus/gal-view-factory-etable.h>
-#include <filter/rule-editor.h>
+#include <filter/e-rule-editor.h>
#include <widgets/menus/gal-view-etable.h>
#include <shell/e-shell-sidebar.h>
diff --git a/e-util/e-util.c b/e-util/e-util.c
index f4bf144c5d..533b3ef908 100644
--- a/e-util/e-util.c
+++ b/e-util/e-util.c
@@ -47,7 +47,9 @@
#include <libedataserver/e-data-server-util.h>
#include <libedataserver/e-categories.h>
-#include "filter/filter-option.h"
+
+#include "filter/e-filter-option.h"
+
#include "e-util.h"
#include "e-util-private.h"
diff --git a/filter/Makefile.am b/filter/Makefile.am
index 48cfa5cc7a..d05842738b 100644
--- a/filter/Makefile.am
+++ b/filter/Makefile.am
@@ -13,44 +13,44 @@ libfilter_la_CPPFLAGS = \
filterincludedir = $(privincludedir)/filter
filterinclude_HEADERS = \
- filter-code.h \
- filter-colour.h \
- filter-datespec.h \
- filter-element.h \
- filter-file.h \
- filter-input.h \
- filter-int.h \
- filter-option.h \
- filter-part.h \
- filter-rule.h \
- rule-context.h \
- rule-editor.h
+ e-filter-code.h \
+ e-filter-color.h \
+ e-filter-datespec.h \
+ e-filter-element.h \
+ e-filter-file.h \
+ e-filter-input.h \
+ e-filter-int.h \
+ e-filter-option.h \
+ e-filter-part.h \
+ e-filter-rule.h \
+ e-rule-context.h \
+ e-rule-editor.h
libfilter_la_SOURCES = \
- filter-code.c \
- filter-code.h \
- filter-colour.c \
- filter-colour.h \
- filter-datespec.c \
- filter-datespec.h \
- filter-element.c \
- filter-element.h \
- filter-file.c \
- filter-file.h \
- filter-input.c \
- filter-input.h \
- filter-int.c \
- filter-int.h \
- filter-option.c \
- filter-option.h \
- filter-part.c \
- filter-part.h \
- filter-rule.c \
- filter-rule.h \
- rule-context.c \
- rule-context.h \
- rule-editor.c \
- rule-editor.h
+ e-filter-code.c \
+ e-filter-code.h \
+ e-filter-color.c \
+ e-filter-color.h \
+ e-filter-datespec.c \
+ e-filter-datespec.h \
+ e-filter-element.c \
+ e-filter-element.h \
+ e-filter-file.c \
+ e-filter-file.h \
+ e-filter-input.c \
+ e-filter-input.h \
+ e-filter-int.c \
+ e-filter-int.h \
+ e-filter-option.c \
+ e-filter-option.h \
+ e-filter-part.c \
+ e-filter-part.h \
+ e-filter-rule.c \
+ e-filter-rule.h \
+ e-rule-context.c \
+ e-rule-context.h \
+ e-rule-editor.c \
+ e-rule-editor.h
libfilter_la_LDFLAGS = $(NO_UNDEFINED)
diff --git a/filter/e-filter-code.c b/filter/e-filter-code.c
new file mode 100644
index 0000000000..7c00baf8d8
--- /dev/null
+++ b/filter/e-filter-code.c
@@ -0,0 +1,126 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-filter-code.h"
+
+static gpointer parent_class;
+
+/* here, the string IS the code */
+static void
+filter_code_build_code (EFilterElement *element,
+ GString *out,
+ struct _EFilterPart *part)
+{
+ GList *l;
+ EFilterInput *fi = (EFilterInput *)element;
+ gboolean is_rawcode = fi && fi->type && g_str_equal (fi->type, "rawcode");
+
+ if (!is_rawcode)
+ g_string_append(out, "(match-all ");
+
+ l = fi->values;
+ while (l) {
+ g_string_append(out, (gchar *)l->data);
+ l = g_list_next(l);
+ }
+
+ if (!is_rawcode)
+ g_string_append (out, ")");
+}
+
+/* and we have no value */
+static void
+filter_code_format_sexp (EFilterElement *element,
+ GString *out)
+{
+}
+
+static void
+filter_code_class_init (EFilterCodeClass *class)
+{
+ EFilterElementClass *filter_element_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ filter_element_class = E_FILTER_ELEMENT_CLASS (class);
+ filter_element_class->build_code = filter_code_build_code;
+ filter_element_class->format_sexp = filter_code_format_sexp;
+}
+
+static void
+filter_code_init (EFilterCode *code)
+{
+ EFilterInput *input = E_FILTER_INPUT (code);
+
+ input->type = (gchar *) xmlStrdup ((xmlChar *) "code");
+}
+
+GType
+e_filter_code_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFilterCodeClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) filter_code_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFilterCode),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) filter_code_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ E_TYPE_FILTER_INPUT, "EFilterCode", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * filter_code_new:
+ *
+ * Create a new EFilterCode object.
+ *
+ * Return value: A new #EFilterCode object.
+ **/
+EFilterCode *
+e_filter_code_new (gboolean raw_code)
+{
+ EFilterCode *fc = g_object_new (E_TYPE_FILTER_CODE, NULL, NULL);
+
+ if (fc && raw_code) {
+ xmlFree (((EFilterInput *) fc)->type);
+ ((EFilterInput *) fc)->type = (gchar *)xmlStrdup ((xmlChar *)"rawcode");
+ }
+
+ return fc;
+}
diff --git a/filter/e-filter-code.h b/filter/e-filter-code.h
new file mode 100644
index 0000000000..6a903a5dcb
--- /dev/null
+++ b/filter/e-filter-code.h
@@ -0,0 +1,68 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FILTER_CODE_H
+#define E_FILTER_CODE_H
+
+#include "e-filter-input.h"
+
+/* Standard GObject macros */
+#define E_TYPE_FILTER_CODE \
+ (e_filter_code_get_type ())
+#define E_FILTER_CODE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILTER_CODE, EFilterCode))
+#define E_FILTER_CODE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILTER_CODE, EFilterCodeClass))
+#define E_IS_FILTER_CODE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILTER_CODE))
+#define E_IS_FILTER_CODE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILTER_CODE))
+#define E_FILTER_CODE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILTER_CODE, EFilterCodeClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EFilterCode EFilterCode;
+typedef struct _EFilterCodeClass EFilterCodeClass;
+typedef struct _EFilterCodePrivate EFilterCodePrivate;
+
+struct _EFilterCode {
+ EFilterInput parent;
+ EFilterCodePrivate *priv;
+};
+
+struct _EFilterCodeClass {
+ EFilterInputClass parent_class;
+};
+
+GType e_filter_code_get_type (void);
+EFilterCode * e_filter_code_new (gboolean raw_code);
+
+G_END_DECLS
+
+#endif /* E_FILTER_CODE_H */
diff --git a/filter/e-filter-color.c b/filter/e-filter-color.c
new file mode 100644
index 0000000000..c4a36607cb
--- /dev/null
+++ b/filter/e-filter-color.c
@@ -0,0 +1,180 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libedataserver/e-sexp.h>
+
+#include "e-filter-color.h"
+
+static gpointer parent_class;
+
+static void
+set_color (GtkColorButton *color_button, EFilterColor *fc)
+{
+ gtk_color_button_get_color (color_button, &fc->color);
+}
+
+static gint
+filter_color_eq (EFilterElement *element_a,
+ EFilterElement *element_b)
+{
+ EFilterColor *color_a = E_FILTER_COLOR (element_a);
+ EFilterColor *color_b = E_FILTER_COLOR (element_b);
+
+ return E_FILTER_ELEMENT_CLASS (parent_class)->eq (element_a, element_b)
+ && gdk_color_equal (&color_a->color, &color_b->color);
+}
+
+static xmlNodePtr
+filter_color_xml_encode (EFilterElement *element)
+{
+ EFilterColor *fc = E_FILTER_COLOR (element);
+ xmlNodePtr value;
+ gchar spec[16];
+
+ g_snprintf (spec, sizeof (spec), "#%04x%04x%04x",
+ fc->color.red, fc->color.green, fc->color.blue);
+
+ value = xmlNewNode(NULL, (xmlChar *)"value");
+ xmlSetProp(value, (xmlChar *)"type", (xmlChar *)"colour");
+ xmlSetProp(value, (xmlChar *)"name", (xmlChar *)element->name);
+ xmlSetProp(value, (xmlChar *)"spec", (xmlChar *)spec);
+
+ return value;
+}
+
+static gint
+filter_color_xml_decode (EFilterElement *element,
+ xmlNodePtr node)
+{
+ EFilterColor *fc = E_FILTER_COLOR (element);
+ xmlChar *prop;
+
+ xmlFree (element->name);
+ element->name = (gchar *)xmlGetProp(node, (xmlChar *)"name");
+
+ prop = xmlGetProp(node, (xmlChar *)"spec");
+ if (prop != NULL) {
+ gdk_color_parse((gchar *)prop, &fc->color);
+ xmlFree (prop);
+ } else {
+ /* try reading the old RGB properties */
+ prop = xmlGetProp(node, (xmlChar *)"red");
+ sscanf((gchar *)prop, "%" G_GINT16_MODIFIER "x", &fc->color.red);
+ xmlFree (prop);
+ prop = xmlGetProp(node, (xmlChar *)"green");
+ sscanf((gchar *)prop, "%" G_GINT16_MODIFIER "x", &fc->color.green);
+ xmlFree (prop);
+ prop = xmlGetProp(node, (xmlChar *)"blue");
+ sscanf((gchar *)prop, "%" G_GINT16_MODIFIER "x", &fc->color.blue);
+ xmlFree (prop);
+ }
+
+ return 0;
+}
+
+static GtkWidget *
+filter_color_get_widget (EFilterElement *element)
+{
+ EFilterColor *fc = E_FILTER_COLOR (element);
+ GtkWidget *color_button;
+
+ color_button = gtk_color_button_new_with_color (&fc->color);
+ gtk_widget_show (color_button);
+
+ g_signal_connect (
+ G_OBJECT (color_button), "color_set",
+ G_CALLBACK (set_color), element);
+
+ return color_button;
+}
+
+static void
+filter_color_format_sexp (EFilterElement *element,
+ GString *out)
+{
+ EFilterColor *fc = E_FILTER_COLOR (element);
+ gchar spec[16];
+
+ g_snprintf (spec, sizeof (spec), "#%04x%04x%04x",
+ fc->color.red, fc->color.green, fc->color.blue);
+ e_sexp_encode_string (out, spec);
+}
+
+static void
+filter_color_class_init (EFilterColorClass *class)
+{
+ EFilterElementClass *filter_element_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ filter_element_class = E_FILTER_ELEMENT_CLASS (class);
+ filter_element_class->eq = filter_color_eq;
+ filter_element_class->xml_encode = filter_color_xml_encode;
+ filter_element_class->xml_decode = filter_color_xml_decode;
+ filter_element_class->get_widget = filter_color_get_widget;
+ filter_element_class->format_sexp = filter_color_format_sexp;
+}
+
+GType
+e_filter_color_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFilterColorClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) filter_color_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFilterColor),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ E_TYPE_FILTER_ELEMENT, "EFilterColor", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * filter_color_new:
+ *
+ * Create a new EFilterColor object.
+ *
+ * Return value: A new #EFilterColor object.
+ **/
+EFilterColor *
+e_filter_color_new (void)
+{
+ return g_object_new (E_TYPE_FILTER_COLOR, NULL);
+}
diff --git a/filter/e-filter-color.h b/filter/e-filter-color.h
new file mode 100644
index 0000000000..cf75bc13ce
--- /dev/null
+++ b/filter/e-filter-color.h
@@ -0,0 +1,70 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FILTER_COLOR_H
+#define E_FILTER_COLOR_H
+
+#include "e-filter-element.h"
+
+/* Standard GObject macros */
+#define E_TYPE_FILTER_COLOR \
+ (e_filter_color_get_type ())
+#define E_FILTER_COLOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILTER_COLOR, EFilterColor))
+#define E_FILTER_COLOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILTER_COLOR, EFilterColorClass))
+#define E_IS_FILTER_COLOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILTER_COLOR))
+#define E_IS_FILTER_COLOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILTER_COLOR))
+#define E_FILTER_COLOR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILTER_COLOR, EFilterColorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EFilterColor EFilterColor;
+typedef struct _EFilterColorClass EFilterColorClass;
+typedef struct _EFilterColorPrivate EFilterColorPrivate;
+
+struct _EFilterColor {
+ EFilterElement parent;
+ EFilterColorPrivate *priv;
+
+ GdkColor color;
+};
+
+struct _EFilterColorClass {
+ EFilterElementClass parent_class;
+};
+
+GType e_filter_color_get_type (void);
+EFilterColor * e_filter_color_new (void);
+
+G_END_DECLS
+
+#endif /* E_FILTER_COLOR_H */
diff --git a/filter/filter-datespec.c b/filter/e-filter-datespec.c
index a0e981d111..1a34cce525 100644
--- a/filter/filter-datespec.c
+++ b/filter/e-filter-datespec.c
@@ -33,34 +33,25 @@
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <glade/glade.h>
+#include <libedataserver/e-sexp.h>
-#include "filter-datespec.h"
-#include "libedataserver/e-sexp.h"
#include "e-util/e-error.h"
#include "e-util/e-util-private.h"
+#include "e-filter-datespec.h"
+#include "e-filter-part.h"
+
#ifdef G_OS_WIN32
#define localtime_r(tp,tmp) memcpy(tmp,localtime(tp),sizeof(struct tm))
#endif
-#define d(x)
-
-static gboolean validate (FilterElement *fe, GtkWindow *error_parent);
-static gint date_eq (FilterElement *fe, FilterElement *cm);
-static void xml_create (FilterElement *fe, xmlNodePtr node);
-static xmlNodePtr xml_encode (FilterElement *fe);
-static gint xml_decode (FilterElement *fe, xmlNodePtr node);
-static GtkWidget *get_widget (FilterElement *fe);
-static void build_code (FilterElement *fe, GString *out, struct _FilterPart *fds);
-static void format_sexp (FilterElement *, GString *);
+#define E_FILTER_DATESPEC_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_FILTER_DATESPEC, EFilterDatespecPrivate))
-static void filter_datespec_class_init (FilterDatespecClass *klass);
-static void filter_datespec_init (FilterDatespec *fd);
-static void filter_datespec_finalise (GObject *obj);
-
-#define PRIV(x) (((FilterDatespec *)(x))->priv)
+#define d(x)
-typedef struct _timespan {
+typedef struct {
guint32 seconds;
const gchar *past_singular;
const gchar *past_plural;
@@ -92,171 +83,14 @@ static const timespan timespans[] = {
#define DAY_INDEX 3
-struct _FilterDatespecPrivate {
+struct _EFilterDatespecPrivate {
GtkWidget *label_button;
GtkWidget *notebook_type, *combobox_type, *calendar_specify, *spin_relative, *combobox_relative, *combobox_past_future;
- FilterDatespec_type type;
+ EFilterDatespecType type;
gint span;
};
-static FilterElementClass *parent_class;
-
-GType
-filter_datespec_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (FilterDatespecClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) filter_datespec_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (FilterDatespec),
- 0, /* n_preallocs */
- (GInstanceInitFunc) filter_datespec_init,
- };
-
- type = g_type_register_static (FILTER_TYPE_ELEMENT, "FilterDatespec", &info, 0);
- }
-
- return type;
-}
-
-static void
-filter_datespec_class_init (FilterDatespecClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- FilterElementClass *fe_class = FILTER_ELEMENT_CLASS (klass);
-
- parent_class = g_type_class_ref (FILTER_TYPE_ELEMENT);
-
- object_class->finalize = filter_datespec_finalise;
-
- /* override methods */
- fe_class->validate = validate;
- fe_class->eq = date_eq;
- fe_class->xml_create = xml_create;
- fe_class->xml_encode = xml_encode;
- fe_class->xml_decode = xml_decode;
- fe_class->get_widget = get_widget;
- fe_class->build_code = build_code;
- fe_class->format_sexp = format_sexp;
-}
-
-static void
-filter_datespec_init (FilterDatespec *fd)
-{
- fd->priv = g_malloc0 (sizeof (*fd->priv));
- fd->type = FDST_UNKNOWN;
-}
-
-static void
-filter_datespec_finalise (GObject *obj)
-{
- FilterDatespec *fd = (FilterDatespec *) obj;
-
- g_free (fd->priv);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-/**
- * filter_datespec_new:
- *
- * Create a new FilterDatespec object.
- *
- * Return value: A new #FilterDatespec object.
- **/
-FilterDatespec *
-filter_datespec_new (void)
-{
- return (FilterDatespec *) g_object_new (FILTER_TYPE_DATESPEC, NULL, NULL);
-}
-
-static gboolean
-validate (FilterElement *fe, GtkWindow *error_parent)
-{
- FilterDatespec *fds = (FilterDatespec *) fe;
- gboolean valid;
-
- valid = fds->type != FDST_UNKNOWN;
- if (!valid) {
- e_error_run (error_parent, "filter:no-date", NULL);
- }
-
- return valid;
-}
-
-static gint
-date_eq (FilterElement *fe, FilterElement *cm)
-{
- FilterDatespec *fd = (FilterDatespec *)fe, *cd = (FilterDatespec *)cm;
-
- return FILTER_ELEMENT_CLASS (parent_class)->eq(fe, cm)
- && (fd->type == cd->type)
- && (fd->value == cd->value);
-}
-
-static void
-xml_create (FilterElement *fe, xmlNodePtr node)
-{
- /* parent implementation */
- FILTER_ELEMENT_CLASS (parent_class)->xml_create (fe, node);
-}
-
-static xmlNodePtr
-xml_encode (FilterElement *fe)
-{
- xmlNodePtr value, work;
- FilterDatespec *fds = (FilterDatespec *)fe;
- gchar str[32];
-
- d(printf ("Encoding datespec as xml\n"));
-
- value = xmlNewNode (NULL, (const guchar *)"value");
- xmlSetProp (value, (const guchar *)"name", (guchar *)fe->name);
- xmlSetProp (value, (const guchar *)"type", (const guchar *)"datespec");
-
- work = xmlNewChild (value, NULL, (const guchar *)"datespec", NULL);
- sprintf (str, "%d", fds->type);
- xmlSetProp (work, (const guchar *)"type", (guchar *)str);
- sprintf (str, "%d", (gint)fds->value);
- xmlSetProp (work, (const guchar *)"value", (guchar *)str);
-
- return value;
-}
-
-static gint
-xml_decode (FilterElement *fe, xmlNodePtr node)
-{
- FilterDatespec *fds = (FilterDatespec *)fe;
- xmlNodePtr n;
- xmlChar *val;
-
- d(printf ("Decoding datespec from xml %p\n", fe));
-
- xmlFree (fe->name);
- fe->name = (gchar *)xmlGetProp (node, (const guchar *)"name");
-
- n = node->children;
- while (n) {
- if (!strcmp ((gchar *)n->name, "datespec")) {
- val = xmlGetProp (n, (const guchar *)"type");
- fds->type = atoi ((gchar *)val);
- xmlFree (val);
- val = xmlGetProp (n, (const guchar *)"value");
- fds->value = atoi ((gchar *)val);
- xmlFree (val);
- break;
- }
- n = n->next;
- }
-
- return 0;
-}
+static gpointer parent_class;
static gint
get_best_span (time_t val)
@@ -273,7 +107,7 @@ get_best_span (time_t val)
/* sets button label */
static void
-set_button (FilterDatespec *fds)
+set_button (EFilterDatespec *fds)
{
gchar buf[128];
gchar *label = buf;
@@ -320,9 +154,9 @@ set_button (FilterDatespec *fds)
}
static void
-get_values (FilterDatespec *fds)
+get_values (EFilterDatespec *fds)
{
- struct _FilterDatespecPrivate *p = PRIV(fds);
+ EFilterDatespecPrivate *p = E_FILTER_DATESPEC_GET_PRIVATE (fds);
switch (fds->priv->type) {
case FDST_SPECIFIED: {
@@ -353,11 +187,11 @@ get_values (FilterDatespec *fds)
}
static void
-set_values (FilterDatespec *fds)
+set_values (EFilterDatespec *fds)
{
gint note_type;
- struct _FilterDatespecPrivate *p = PRIV(fds);
+ EFilterDatespecPrivate *p = E_FILTER_DATESPEC_GET_PRIVATE (fds);
p->type = fds->type==FDST_UNKNOWN ? FDST_NOW : fds->type;
@@ -396,20 +230,20 @@ set_values (FilterDatespec *fds)
}
static void
-set_combobox_type (GtkComboBox *combobox, FilterDatespec *fds)
+set_combobox_type (GtkComboBox *combobox, EFilterDatespec *fds)
{
fds->priv->type = gtk_combo_box_get_active (combobox);
gtk_notebook_set_current_page ((GtkNotebook*) fds->priv->notebook_type, fds->priv->type);
}
static void
-set_combobox_relative (GtkComboBox *combobox, FilterDatespec *fds)
+set_combobox_relative (GtkComboBox *combobox, EFilterDatespec *fds)
{
fds->priv->span = gtk_combo_box_get_active (combobox);
}
static void
-set_combobox_past_future (GtkComboBox *combobox, FilterDatespec *fds)
+set_combobox_past_future (GtkComboBox *combobox, EFilterDatespec *fds)
{
if (gtk_combo_box_get_active (combobox) == 0)
fds->type = fds->priv->type = FDST_X_AGO;
@@ -418,9 +252,9 @@ set_combobox_past_future (GtkComboBox *combobox, FilterDatespec *fds)
}
static void
-button_clicked (GtkButton *button, FilterDatespec *fds)
+button_clicked (GtkButton *button, EFilterDatespec *fds)
{
- struct _FilterDatespecPrivate *p = PRIV(fds);
+ EFilterDatespecPrivate *p = E_FILTER_DATESPEC_GET_PRIVATE (fds);
GtkWidget *content_area;
GtkWidget *toplevel;
GtkDialog *dialog;
@@ -465,10 +299,92 @@ button_clicked (GtkButton *button, FilterDatespec *fds)
gtk_widget_destroy ((GtkWidget *)dialog);
}
+static gboolean
+filter_datespec_validate (EFilterElement *element,
+ GtkWindow *error_parent)
+{
+ EFilterDatespec *fds = E_FILTER_DATESPEC (element);
+ gboolean valid;
+
+ valid = fds->type != FDST_UNKNOWN;
+ if (!valid) {
+ e_error_run (error_parent, "filter:no-date", NULL);
+ }
+
+ return valid;
+}
+
+static gint
+filter_datespec_eq (EFilterElement *element_a,
+ EFilterElement *element_b)
+{
+ EFilterDatespec *datespec_a = E_FILTER_DATESPEC (element_a);
+ EFilterDatespec *datespec_b = E_FILTER_DATESPEC (element_b);
+
+ /* Chain up to parent's eq() method. */
+ if (!E_FILTER_ELEMENT_CLASS (parent_class)->eq (element_a, element_b))
+ return FALSE;
+
+ return (datespec_a->type == datespec_b->type) &&
+ (datespec_a->value == datespec_b->value);
+}
+
+static xmlNodePtr
+filter_datespec_xml_encode (EFilterElement *element)
+{
+ xmlNodePtr value, work;
+ EFilterDatespec *fds = E_FILTER_DATESPEC (element);
+ gchar str[32];
+
+ d(printf ("Encoding datespec as xml\n"));
+
+ value = xmlNewNode (NULL, (xmlChar *)"value");
+ xmlSetProp (value, (xmlChar *)"name", (xmlChar *)element->name);
+ xmlSetProp (value, (xmlChar *)"type", (xmlChar *)"datespec");
+
+ work = xmlNewChild (value, NULL, (xmlChar *)"datespec", NULL);
+ sprintf (str, "%d", fds->type);
+ xmlSetProp (work, (xmlChar *)"type", (xmlChar *)str);
+ sprintf (str, "%d", (gint)fds->value);
+ xmlSetProp (work, (xmlChar *)"value", (xmlChar *)str);
+
+ return value;
+}
+
+static gint
+filter_datespec_xml_decode (EFilterElement *element,
+ xmlNodePtr node)
+{
+ EFilterDatespec *fds = E_FILTER_DATESPEC (element);
+ xmlNodePtr n;
+ xmlChar *val;
+
+ d(printf ("Decoding datespec from xml %p\n", element));
+
+ xmlFree (element->name);
+ element->name = (gchar *)xmlGetProp (node, (xmlChar *)"name");
+
+ n = node->children;
+ while (n) {
+ if (!strcmp ((gchar *)n->name, "datespec")) {
+ val = xmlGetProp (n, (xmlChar *)"type");
+ fds->type = atoi ((gchar *)val);
+ xmlFree (val);
+ val = xmlGetProp (n, (xmlChar *)"value");
+ fds->value = atoi ((gchar *)val);
+ xmlFree (val);
+ break;
+ }
+ n = n->next;
+ }
+
+ return 0;
+}
+
static GtkWidget *
-get_widget (FilterElement *fe)
+filter_datespec_get_widget (EFilterElement *element)
{
- FilterDatespec *fds = (FilterDatespec *)fe;
+ EFilterDatespec *fds = E_FILTER_DATESPEC (element);
GtkWidget *button;
fds->priv->label_button = gtk_label_new ("");
@@ -486,15 +402,10 @@ get_widget (FilterElement *fe)
}
static void
-build_code (FilterElement *fe, GString *out, struct _FilterPart *fp)
-{
- return;
-}
-
-static void
-format_sexp (FilterElement *fe, GString *out)
+filter_datespec_format_sexp (EFilterElement *element,
+ GString *out)
{
- FilterDatespec *fds = (FilterDatespec *)fe;
+ EFilterDatespec *fds = E_FILTER_DATESPEC (element);
switch (fds->type) {
case FDST_UNKNOWN:
@@ -507,10 +418,75 @@ format_sexp (FilterElement *fe, GString *out)
g_string_append_printf (out, "%d", (gint) fds->value);
break;
case FDST_X_AGO:
- g_string_append_printf (out, "(- (get-current-date) %d)", (gint) fds->value);
+ g_string_append_printf (
+ out, "(- (get-current-date) %d)", (gint) fds->value);
break;
case FDST_X_FUTURE:
- g_string_append_printf (out, "(+ (get-current-date) %d)", (gint) fds->value);
+ g_string_append_printf (
+ out, "(+ (get-current-date) %d)", (gint) fds->value);
break;
}
}
+
+static void
+filter_datespec_class_init (EFilterDatespecClass *class)
+{
+ EFilterElementClass *filter_element_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EFilterDatespecPrivate));
+
+ filter_element_class = E_FILTER_ELEMENT_CLASS (class);
+ filter_element_class->validate = filter_datespec_validate;
+ filter_element_class->eq = filter_datespec_eq;
+ filter_element_class->xml_encode = filter_datespec_xml_encode;
+ filter_element_class->xml_decode = filter_datespec_xml_decode;
+ filter_element_class->get_widget = filter_datespec_get_widget;
+ filter_element_class->format_sexp = filter_datespec_format_sexp;
+}
+
+static void
+filter_datespec_init (EFilterDatespec *datespec)
+{
+ datespec->priv = E_FILTER_DATESPEC_GET_PRIVATE (datespec);
+ datespec->type = FDST_UNKNOWN;
+}
+
+GType
+e_filter_datespec_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFilterDatespecClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) filter_datespec_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFilterDatespec),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) filter_datespec_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ E_TYPE_FILTER_ELEMENT, "EFilterDatespec", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * filter_datespec_new:
+ *
+ * Create a new EFilterDatespec object.
+ *
+ * Return value: A new #EFilterDatespec object.
+ **/
+EFilterDatespec *
+e_filter_datespec_new (void)
+{
+ return g_object_new (E_TYPE_FILTER_DATESPEC, NULL);
+}
diff --git a/filter/e-filter-datespec.h b/filter/e-filter-datespec.h
new file mode 100644
index 0000000000..aed978a09a
--- /dev/null
+++ b/filter/e-filter-datespec.h
@@ -0,0 +1,87 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FILTER_DATESPEC_H
+#define E_FILTER_DATESPEC_H
+
+#include <time.h>
+#include "e-filter-element.h"
+
+/* Standard GObject types */
+#define E_TYPE_FILTER_DATESPEC \
+ (e_filter_datespec_get_type ())
+#define E_FILTER_DATESPEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILTER_DATESPEC, EFilterDatespec))
+#define E_FILTER_DATESPEC_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILTER_DATESPEC, EFilterDatespecClass))
+#define E_IS_FILTER_DATESPEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILTER_DATESPEC))
+#define E_IS_FILTER_DATESPEC_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILTER_DATESPEC))
+#define E_FILTER_DATESPEC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILTER_DATESPEC, EFilterDatespecClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EFilterDatespec EFilterDatespec;
+typedef struct _EFilterDatespecClass EFilterDatespecClass;
+typedef struct _EFilterDatespecPrivate EFilterDatespecPrivate;
+
+typedef enum {
+ FDST_UNKNOWN = -1,
+ FDST_NOW,
+ FDST_SPECIFIED,
+ FDST_X_AGO,
+ FDST_X_FUTURE
+} EFilterDatespecType;
+
+struct _EFilterDatespec {
+ EFilterElement parent;
+ EFilterDatespecPrivate *priv;
+
+ EFilterDatespecType type;
+
+ /* either a timespan, an absolute time, or 0
+ * depending on type -- the above mapping to
+ * (X_FUTURE, X_AGO, SPECIFIED, NOW)
+ */
+
+ time_t value;
+};
+
+struct _EFilterDatespecClass {
+ EFilterElementClass parent_class;
+};
+
+GType e_filter_datespec_get_type (void);
+EFilterDatespec *
+ e_filter_datespec_new (void);
+
+G_END_DECLS
+
+#endif /* E_FILTER_DATESPEC_H */
diff --git a/filter/e-filter-element.c b/filter/e-filter-element.c
new file mode 100644
index 0000000000..707692ec3f
--- /dev/null
+++ b/filter/e-filter-element.c
@@ -0,0 +1,472 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "e-filter-element.h"
+#include "e-filter-part.h"
+
+struct _element_type {
+ gchar *name;
+
+ EFilterElementFunc create;
+ gpointer data;
+};
+
+static gpointer parent_class;
+
+static gboolean
+filter_element_validate (EFilterElement *element,
+ GtkWindow *error_parent)
+{
+ return TRUE;
+}
+
+static gint
+filter_element_eq (EFilterElement *element_a,
+ EFilterElement *element_b)
+{
+ return (g_strcmp0 (element_a->name, element_b->name) == 0);
+}
+
+static void
+filter_element_xml_create (EFilterElement *element,
+ xmlNodePtr node)
+{
+ element->name = (gchar *)xmlGetProp (node, (xmlChar *) "name");
+}
+
+static EFilterElement *
+filter_element_clone (EFilterElement *element)
+{
+ EFilterElement *clone;
+ xmlNodePtr node;
+
+ clone = g_object_new (G_OBJECT_TYPE (element), NULL);
+
+ node = e_filter_element_xml_encode (element);
+ e_filter_element_xml_decode (clone, node);
+ xmlFreeNodeList (node);
+
+ return clone;
+}
+
+/* This is somewhat hackish, implement all the base cases in here */
+#include "e-filter-input.h"
+#include "e-filter-option.h"
+#include "e-filter-code.h"
+#include "e-filter-color.h"
+#include "e-filter-datespec.h"
+#include "e-filter-int.h"
+#include "e-filter-file.h"
+
+static void
+filter_element_copy_value (EFilterElement *dst_element,
+ EFilterElement *src_element)
+{
+ if (E_IS_FILTER_INPUT (src_element)) {
+ EFilterInput *src_input;
+
+ src_input = E_FILTER_INPUT (src_element);
+
+ if (E_IS_FILTER_INPUT (dst_element)) {
+ EFilterInput *dst_input;
+
+ dst_input = E_FILTER_INPUT (dst_element);
+
+ if (src_input->values)
+ e_filter_input_set_value (
+ dst_input,
+ src_input->values->data);
+
+ } else if (E_IS_FILTER_INT (dst_element)) {
+ EFilterInt *dst_int;
+
+ dst_int = E_FILTER_INT (dst_element);
+
+ dst_int->val = atoi (src_input->values->data);
+ }
+
+ } else if (E_IS_FILTER_COLOR (src_element)) {
+ EFilterColor *src_color;
+
+ src_color = E_FILTER_COLOR (src_element);
+
+ if (E_IS_FILTER_COLOR (dst_element)) {
+ EFilterColor *dst_color;
+
+ dst_color = E_FILTER_COLOR (dst_element);
+
+ dst_color->color = src_color->color;
+ }
+
+ } else if (E_IS_FILTER_DATESPEC (src_element)) {
+ EFilterDatespec *src_datespec;
+
+ src_datespec = E_FILTER_DATESPEC (src_element);
+
+ if (E_IS_FILTER_DATESPEC (dst_element)) {
+ EFilterDatespec *dst_datespec;
+
+ dst_datespec = E_FILTER_DATESPEC (dst_element);
+
+ dst_datespec->type = src_datespec->type;
+ dst_datespec->value = src_datespec->value;
+ }
+
+ } else if (E_IS_FILTER_INT (src_element)) {
+ EFilterInt *src_int;
+
+ src_int = E_FILTER_INT (src_element);
+
+ if (E_IS_FILTER_INT (dst_element)) {
+ EFilterInt *dst_int;
+
+ dst_int = E_FILTER_INT (dst_element);
+
+ dst_int->val = src_int->val;
+
+ } else if (E_IS_FILTER_INPUT (dst_element)) {
+ EFilterInput *dst_input;
+ gchar *values;
+
+ dst_input = E_FILTER_INPUT (dst_element);
+
+ values = g_strdup_printf ("%d", src_int->val);
+ e_filter_input_set_value (dst_input, values);
+ g_free (values);
+ }
+
+ } else if (E_IS_FILTER_OPTION (src_element)) {
+ EFilterOption *src_option;
+
+ src_option = E_FILTER_OPTION (src_element);
+
+ if (E_IS_FILTER_OPTION (dst_element)) {
+ EFilterOption *dst_option;
+
+ dst_option = E_FILTER_OPTION (dst_element);
+
+ if (src_option->current)
+ e_filter_option_set_current (
+ dst_option,
+ src_option->current->value);
+ }
+ }
+}
+
+static void
+filter_element_finalize (GObject *object)
+{
+ EFilterElement *element = E_FILTER_ELEMENT (object);
+
+ xmlFree (element->name);
+
+ /* Chain up to parent's finalize () method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+filter_element_class_init (EFilterElementClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = filter_element_finalize;
+
+ class->validate = filter_element_validate;
+ class->eq = filter_element_eq;
+ class->xml_create = filter_element_xml_create;
+ class->clone = filter_element_clone;
+ class->copy_value = filter_element_copy_value;
+}
+
+GType
+e_filter_element_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFilterElementClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) filter_element_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFilterElement),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ G_TYPE_OBJECT, "EFilterElement", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * filter_element_new:
+ *
+ * Create a new EFilterElement object.
+ *
+ * Return value: A new #EFilterElement object.
+ **/
+EFilterElement *
+e_filter_element_new (void)
+{
+ return g_object_new (E_TYPE_FILTER_ELEMENT, NULL);
+}
+
+gboolean
+e_filter_element_validate (EFilterElement *element,
+ GtkWindow *error_parent)
+{
+ EFilterElementClass *class;
+
+ g_return_val_if_fail (E_IS_FILTER_ELEMENT (element), FALSE);
+
+ /* Warn but proceed if no parent window was given. */
+ if (error_parent != NULL)
+ g_return_val_if_fail (GTK_IS_WINDOW (error_parent), FALSE);
+ else
+ g_warning ("%s() called with no parent window", G_STRFUNC);
+
+ class = E_FILTER_ELEMENT_GET_CLASS (element);
+ g_return_val_if_fail (class->validate != NULL, FALSE);
+
+ return class->validate (element, error_parent);
+}
+
+gint
+e_filter_element_eq (EFilterElement *element_a,
+ EFilterElement *element_b)
+{
+ EFilterElementClass *class;
+
+ g_return_val_if_fail (E_IS_FILTER_ELEMENT (element_a), FALSE);
+ g_return_val_if_fail (E_IS_FILTER_ELEMENT (element_b), FALSE);
+
+ /* The elements must be the same type. */
+ if (G_OBJECT_TYPE (element_a) != G_OBJECT_TYPE (element_b))
+ return FALSE;
+
+ class = E_FILTER_ELEMENT_GET_CLASS (element_a);
+ g_return_val_if_fail (class->eq != NULL, FALSE);
+
+ return class->eq (element_a, element_b);
+}
+
+/**
+ * filter_element_xml_create:
+ * @fe: filter element
+ * @node: xml node
+ *
+ * Create a new filter element based on an xml definition of
+ * that element.
+ **/
+void
+e_filter_element_xml_create (EFilterElement *element,
+ xmlNodePtr node)
+{
+ EFilterElementClass *class;
+
+ g_return_if_fail (E_IS_FILTER_ELEMENT (element));
+ g_return_if_fail (node != NULL);
+
+ class = E_FILTER_ELEMENT_GET_CLASS (element);
+ g_return_if_fail (class->xml_create != NULL);
+
+ class->xml_create (element, node);
+}
+
+/**
+ * filter_element_xml_encode:
+ * @fe: filter element
+ *
+ * Encode the values of a filter element into xml format.
+ *
+ * Return value:
+ **/
+xmlNodePtr
+e_filter_element_xml_encode (EFilterElement *element)
+{
+ EFilterElementClass *class;
+
+ g_return_val_if_fail (E_IS_FILTER_ELEMENT (element), NULL);
+
+ class = E_FILTER_ELEMENT_GET_CLASS (element);
+ g_return_val_if_fail (class->xml_encode != NULL, NULL);
+
+ return class->xml_encode (element);
+}
+
+/**
+ * filter_element_xml_decode:
+ * @fe: filter element
+ * @node: xml node
+ *
+ * Decode the values of a fitler element from xml format.
+ *
+ * Return value:
+ **/
+gint
+e_filter_element_xml_decode (EFilterElement *element,
+ xmlNodePtr node)
+{
+ EFilterElementClass *class;
+
+ g_return_val_if_fail (E_IS_FILTER_ELEMENT (element), FALSE);
+ g_return_val_if_fail (node != NULL, FALSE);
+
+ class = E_FILTER_ELEMENT_GET_CLASS (element);
+ g_return_val_if_fail (class->xml_decode != NULL, FALSE);
+
+ return class->xml_decode (element, node);
+}
+
+/**
+ * filter_element_clone:
+ * @fe: filter element
+ *
+ * Clones the EFilterElement @fe.
+ *
+ * Return value:
+ **/
+EFilterElement *
+e_filter_element_clone (EFilterElement *element)
+{
+ EFilterElementClass *class;
+
+ g_return_val_if_fail (E_IS_FILTER_ELEMENT (element), NULL);
+
+ class = E_FILTER_ELEMENT_GET_CLASS (element);
+ g_return_val_if_fail (class->clone != NULL, NULL);
+
+ return class->clone (element);
+}
+
+/**
+ * filter_element_get_widget:
+ * @fe: filter element
+ * @node: xml node
+ *
+ * Create a widget to represent this element.
+ *
+ * Return value:
+ **/
+GtkWidget *
+e_filter_element_get_widget (EFilterElement *element)
+{
+ EFilterElementClass *class;
+
+ g_return_val_if_fail (E_IS_FILTER_ELEMENT (element), NULL);
+
+ class = E_FILTER_ELEMENT_GET_CLASS (element);
+ g_return_val_if_fail (class->get_widget != NULL, NULL);
+
+ return class->get_widget (element);
+}
+
+/**
+ * filter_element_build_code:
+ * @fe: filter element
+ * @out: output buffer
+ * @ff:
+ *
+ * Add the code representing this element to the output string @out.
+ **/
+void
+e_filter_element_build_code (EFilterElement *element,
+ GString *out,
+ EFilterPart *part)
+{
+ EFilterElementClass *class;
+
+ g_return_if_fail (E_IS_FILTER_ELEMENT (element));
+ g_return_if_fail (out != NULL);
+ g_return_if_fail (E_IS_FILTER_PART (part));
+
+ class = E_FILTER_ELEMENT_GET_CLASS (element);
+
+ /* This method is optional. */
+ if (class->build_code != NULL)
+ class->build_code (element, out, part);
+}
+
+/**
+ * filter_element_format_sexp:
+ * @fe: filter element
+ * @out: output buffer
+ *
+ * Format the value(s) of this element in a method suitable for the context of
+ * sexp where it is used. Usually as space separated, double-quoted strings.
+ **/
+void
+e_filter_element_format_sexp (EFilterElement *element,
+ GString *out)
+{
+ EFilterElementClass *class;
+
+ g_return_if_fail (E_IS_FILTER_ELEMENT (element));
+ g_return_if_fail (out != NULL);
+
+ class = E_FILTER_ELEMENT_GET_CLASS (element);
+ g_return_if_fail (class->format_sexp != NULL);
+
+ class->format_sexp (element, out);
+}
+
+void
+e_filter_element_set_data (EFilterElement *element,
+ gpointer data)
+{
+ g_return_if_fail (E_IS_FILTER_ELEMENT (element));
+
+ element->data = data;
+}
+
+/* only copies the value, not the name/type */
+void
+e_filter_element_copy_value (EFilterElement *dst_element,
+ EFilterElement *src_element)
+{
+ EFilterElementClass *class;
+
+ g_return_if_fail (E_IS_FILTER_ELEMENT (dst_element));
+ g_return_if_fail (E_IS_FILTER_ELEMENT (src_element));
+
+ class = E_FILTER_ELEMENT_GET_CLASS (dst_element);
+ g_return_if_fail (class->copy_value != NULL);
+
+ class->copy_value (dst_element, src_element);
+}
diff --git a/filter/e-filter-element.h b/filter/e-filter-element.h
new file mode 100644
index 0000000000..589d3a48ca
--- /dev/null
+++ b/filter/e-filter-element.h
@@ -0,0 +1,118 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FILTER_ELEMENT_H
+#define E_FILTER_ELEMENT_H
+
+#include <gtk/gtk.h>
+#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
+
+#define E_TYPE_FILTER_ELEMENT \
+ (e_filter_element_get_type ())
+#define E_FILTER_ELEMENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILTER_ELEMENT, EFilterElement))
+#define E_FILTER_ELEMENT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILTER_ELEMENT, EFilterElementClass))
+#define E_IS_FILTER_ELEMENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILTER_ELEMENT))
+#define E_IS_FILTER_ELEMENT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILTER_ELEMENT))
+#define E_FILTER_ELEMENT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILTER_ELEMENT, EFilterElementClass))
+
+G_BEGIN_DECLS
+
+struct _EFilterPart;
+
+typedef struct _EFilterElement EFilterElement;
+typedef struct _EFilterElementClass EFilterElementClass;
+typedef struct _EFilterElementPrivate EFilterElementPrivate;
+
+typedef EFilterElement * (*EFilterElementFunc) (gpointer data);
+
+struct _EFilterElement {
+ GObject parent;
+ EFilterElementPrivate *priv;
+
+ gchar *name;
+ gpointer data;
+};
+
+struct _EFilterElementClass {
+ GObjectClass parent_class;
+
+ gboolean (*validate) (EFilterElement *element,
+ GtkWindow *error_parent);
+ gint (*eq) (EFilterElement *element_a,
+ EFilterElement *element_b);
+
+ void (*xml_create) (EFilterElement *element,
+ xmlNodePtr node);
+ xmlNodePtr (*xml_encode) (EFilterElement *element);
+ gint (*xml_decode) (EFilterElement *element,
+ xmlNodePtr node);
+
+ EFilterElement *(*clone) (EFilterElement *element);
+ void (*copy_value) (EFilterElement *dst_element,
+ EFilterElement *src_element);
+
+ GtkWidget * (*get_widget) (EFilterElement *element);
+ void (*build_code) (EFilterElement *element,
+ GString *out,
+ struct _EFilterPart *part);
+ void (*format_sexp) (EFilterElement *element,
+ GString *out);
+};
+
+GType e_filter_element_get_type (void);
+EFilterElement *e_filter_element_new (void);
+void e_filter_element_set_data (EFilterElement *element,
+ gpointer data);
+gboolean e_filter_element_validate (EFilterElement *element,
+ GtkWindow *error_parent);
+gint e_filter_element_eq (EFilterElement *element_a,
+ EFilterElement *element_b);
+void e_filter_element_xml_create (EFilterElement *element,
+ xmlNodePtr node);
+xmlNodePtr e_filter_element_xml_encode (EFilterElement *element);
+gint e_filter_element_xml_decode (EFilterElement *element,
+ xmlNodePtr node);
+EFilterElement *e_filter_element_clone (EFilterElement *element);
+void e_filter_element_copy_value (EFilterElement *dst_element,
+ EFilterElement *src_element);
+GtkWidget * e_filter_element_get_widget (EFilterElement *element);
+void e_filter_element_build_code (EFilterElement *element,
+ GString *out,
+ struct _EFilterPart *part);
+void e_filter_element_format_sexp (EFilterElement *element,
+ GString *out);
+
+G_END_DECLS
+
+#endif /* E_FILTER_ELEMENT_H */
diff --git a/filter/e-filter-file.c b/filter/e-filter-file.c
new file mode 100644
index 0000000000..6364475a2e
--- /dev/null
+++ b/filter/e-filter-file.c
@@ -0,0 +1,278 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/types.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+
+#include <libedataserver/e-sexp.h>
+
+#include "e-util/e-error.h"
+
+#include "e-filter-file.h"
+#include "e-filter-part.h"
+
+static gpointer parent_class;
+
+static void
+filter_file_filename_changed (GtkFileChooser *file_chooser,
+ EFilterElement *element)
+{
+ EFilterFile *file = E_FILTER_FILE (element);
+ const gchar *path;
+
+ path = gtk_file_chooser_get_filename (file_chooser);
+
+ g_free (file->path);
+ file->path = g_strdup (path);
+}
+
+static void
+filter_file_finalize (GObject *object)
+{
+ EFilterFile *file = E_FILTER_FILE (object);
+
+ xmlFree (file->type);
+ g_free (file->path);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+filter_file_validate (EFilterElement *element,
+ GtkWindow *error_parent)
+{
+ EFilterFile *file = E_FILTER_FILE (element);
+
+ if (!file->path) {
+ e_error_run (error_parent, "filter:no-file", NULL);
+ return FALSE;
+ }
+
+ /* FIXME: do more to validate command-lines? */
+
+ if (g_strcmp0 (file->type, "file") == 0) {
+ if (!g_file_test (file->path, G_FILE_TEST_IS_REGULAR)) {
+ e_error_run (
+ error_parent, "filter:bad-file",
+ file->path, NULL);
+ return FALSE;
+ }
+ } else if (g_strcmp0 (file->type, "command") == 0) {
+ /* Only requirements so far is that the
+ * command can't be an empty string. */
+ return (file->path[0] != '\0');
+ }
+
+ return TRUE;
+}
+
+static gint
+filter_file_eq (EFilterElement *element_a,
+ EFilterElement *element_b)
+{
+ EFilterFile *file_a = E_FILTER_FILE (element_a);
+ EFilterFile *file_b = E_FILTER_FILE (element_b);
+
+ /* Chain up to parent's eq() method. */
+ if (!E_FILTER_ELEMENT_CLASS (parent_class)->eq (element_a, element_b))
+ return FALSE;
+
+ if (g_strcmp0 (file_a->path, file_b->path) != 0)
+ return FALSE;
+
+ if (g_strcmp0 (file_a->type, file_b->type) != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static xmlNodePtr
+filter_file_xml_encode (EFilterElement *element)
+{
+ EFilterFile *file = E_FILTER_FILE (element);
+ xmlNodePtr cur, value;
+ const gchar *type;
+
+ type = file->type ? file->type : "file";
+
+ value = xmlNewNode (NULL, (xmlChar *)"value");
+ xmlSetProp (value, (xmlChar *) "name", (xmlChar *) element->name);
+ xmlSetProp (value, (xmlChar *) "type", (xmlChar *) type);
+
+ cur = xmlNewChild (value, NULL, (xmlChar *)type, NULL);
+ xmlNodeSetContent (cur, (xmlChar *)file->path);
+
+ return value;
+}
+
+static gint
+filter_file_xml_decode (EFilterElement *element,
+ xmlNodePtr node)
+{
+ EFilterFile *file = E_FILTER_FILE (element);
+ gchar *name, *str, *type;
+ xmlNodePtr child;
+
+ name = (gchar *)xmlGetProp (node, (xmlChar *) "name");
+ type = (gchar *)xmlGetProp (node, (xmlChar *) "type");
+
+ xmlFree (element->name);
+ element->name = name;
+
+ xmlFree (file->type);
+ file->type = type;
+
+ g_free (file->path);
+ file->path = NULL;
+
+ child = node->children;
+ while (child != NULL) {
+ if (!strcmp ((gchar *)child->name, type)) {
+ str = (gchar *)xmlNodeGetContent (child);
+ file->path = g_strdup (str ? str : "");
+ xmlFree (str);
+
+ break;
+ } else if (child->type == XML_ELEMENT_NODE) {
+ g_warning (
+ "Unknown node type '%s' encountered "
+ "decoding a %s\n", child->name, type);
+ }
+
+ child = child->next;
+ }
+
+ return 0;
+}
+
+static GtkWidget *
+filter_file_get_widget (EFilterElement *element)
+{
+ EFilterFile *file = E_FILTER_FILE (element);
+ GtkWidget *widget;
+
+ widget = gtk_file_chooser_button_new (
+ _("Choose a File"), GTK_FILE_CHOOSER_ACTION_OPEN);
+ gtk_file_chooser_set_filename (
+ GTK_FILE_CHOOSER (widget), file->path);
+ g_signal_connect (
+ widget, "selection-changed",
+ G_CALLBACK (filter_file_filename_changed), element);
+
+ return widget;
+}
+
+static void
+filter_file_format_sexp (EFilterElement *element,
+ GString *out)
+{
+ EFilterFile *file = E_FILTER_FILE (element);
+
+ e_sexp_encode_string (out, file->path);
+}
+
+static void
+filter_file_class_init (EFilterFileClass *class)
+{
+ GObjectClass *object_class;
+ EFilterElementClass *filter_element_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = filter_file_finalize;
+
+ filter_element_class = E_FILTER_ELEMENT_CLASS (class);
+ filter_element_class->validate = filter_file_validate;
+ filter_element_class->eq = filter_file_eq;
+ filter_element_class->xml_encode = filter_file_xml_encode;
+ filter_element_class->xml_decode = filter_file_xml_decode;
+ filter_element_class->get_widget = filter_file_get_widget;
+ filter_element_class->format_sexp = filter_file_format_sexp;
+}
+
+GType
+e_filter_file_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFilterFileClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) filter_file_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFilterFile),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ E_TYPE_FILTER_ELEMENT, "EFilterFile", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * filter_file_new:
+ *
+ * Create a new EFilterFile object.
+ *
+ * Return value: A new #EFilterFile object.
+ **/
+EFilterFile *
+e_filter_file_new (void)
+{
+ return g_object_new (E_TYPE_FILTER_FILE, NULL);
+}
+
+EFilterFile *
+e_filter_file_new_type_name (const gchar *type)
+{
+ EFilterFile *file;
+
+ file = e_filter_file_new ();
+ file->type = (gchar *) xmlStrdup ((xmlChar *)type);
+
+ return file;
+}
+
+void
+e_filter_file_set_path (EFilterFile *file,
+ const gchar *path)
+{
+ g_return_if_fail (E_IS_FILTER_FILE (file));
+
+ g_free (file->path);
+ file->path = g_strdup (path);
+}
diff --git a/filter/e-filter-file.h b/filter/e-filter-file.h
new file mode 100644
index 0000000000..6f7946e8e7
--- /dev/null
+++ b/filter/e-filter-file.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FILTER_FILE_H
+#define E_FILTER_FILE_H
+
+#include "e-filter-element.h"
+
+/* Standard GObject macros */
+#define E_TYPE_FILTER_FILE \
+ (e_filter_file_get_type ())
+#define E_FILTER_FILE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILTER_FILE, EFilterFile))
+#define E_FILTER_FILE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILTER_FILE, EFilterFileClass))
+#define E_IS_FILTER_FILE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILTER_FILE))
+#define E_IS_FILTER_FILE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILTER_FILE))
+#define E_FILTER_FILE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILTER_FILE, EFilterFileClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EFilterFile EFilterFile;
+typedef struct _EFilterFileClass EFilterFileClass;
+typedef struct _EFilterFilePrivate EFilterFilePrivate;
+
+struct _EFilterFile {
+ EFilterElement parent;
+ EFilterFilePrivate *priv;
+
+ gchar *type;
+ gchar *path;
+};
+
+struct _EFilterFileClass {
+ EFilterElementClass parent_class;
+};
+
+GType e_filter_file_get_type (void);
+EFilterFile * e_filter_file_new (void);
+EFilterFile * e_filter_file_new_type_name (const gchar *type);
+void e_filter_file_set_path (EFilterFile *file,
+ const gchar *path);
+
+G_END_DECLS
+
+#endif /* E_FILTER_FILE_H */
diff --git a/filter/e-filter-input.c b/filter/e-filter-input.c
new file mode 100644
index 0000000000..a8d6123905
--- /dev/null
+++ b/filter/e-filter-input.c
@@ -0,0 +1,322 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+#include <regex.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include <libedataserver/e-sexp.h>
+
+#include "e-util/e-error.h"
+
+#include "e-filter-input.h"
+
+static gpointer parent_class;
+
+static void
+filter_input_entry_changed (GtkEntry *entry,
+ EFilterElement *element)
+{
+ EFilterInput *input = E_FILTER_INPUT (element);
+ const gchar *text;
+
+ g_list_foreach (input->values, (GFunc) g_free, NULL);
+ g_list_free (input->values);
+
+ text = gtk_entry_get_text (entry);
+ input->values = g_list_append (NULL, g_strdup (text));
+}
+
+static void
+filter_input_finalize (GObject *object)
+{
+ EFilterInput *input = E_FILTER_INPUT (object);
+
+ xmlFree (input->type);
+
+ g_list_foreach (input->values, (GFunc)g_free, NULL);
+ g_list_free (input->values);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+filter_input_validate (EFilterElement *element,
+ GtkWindow *error_parent)
+{
+ EFilterInput *input = E_FILTER_INPUT (element);
+ gboolean valid = TRUE;
+
+ if (input->values && !strcmp (input->type, "regex")) {
+ const gchar *pattern;
+ regex_t regexpat;
+ gint regerr;
+
+ pattern = input->values->data;
+
+ if ((regerr = regcomp (&regexpat, pattern, REG_EXTENDED | REG_NEWLINE | REG_ICASE))) {
+ gsize reglen;
+ gchar *regmsg;
+
+ /* regerror gets called twice to get the full error string
+ length to do proper posix error reporting */
+ reglen = regerror (regerr, &regexpat, 0, 0);
+ regmsg = g_malloc0 (reglen + 1);
+ regerror (regerr, &regexpat, regmsg, reglen);
+
+ e_error_run (error_parent, "filter:bad-regexp", pattern, regmsg, NULL);
+ g_free (regmsg);
+
+ valid = FALSE;
+ }
+
+ regfree (&regexpat);
+ }
+
+ return valid;
+}
+
+static gint
+filter_input_eq (EFilterElement *element_a,
+ EFilterElement *element_b)
+{
+ EFilterInput *input_a = E_FILTER_INPUT (element_a);
+ EFilterInput *input_b = E_FILTER_INPUT (element_b);
+ GList *link_a;
+ GList *link_b;
+
+ /* Chain up to parent's eq() method. */
+ if (!E_FILTER_ELEMENT_CLASS (parent_class)->eq (element_a, element_b))
+ return FALSE;
+
+ if (g_strcmp0 (input_a->type, input_b->type) != 0)
+ return FALSE;
+
+ link_a = input_a->values;
+ link_b = input_b->values;
+
+ while (link_a != NULL && link_b != NULL) {
+ if (g_strcmp0 (link_a->data, link_b->data) != 0)
+ return FALSE;
+
+ link_a = g_list_next (link_a);
+ link_b = g_list_next (link_b);
+ }
+
+ if (link_a != NULL || link_b != NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static xmlNodePtr
+filter_input_xml_encode (EFilterElement *element)
+{
+ EFilterInput *input = E_FILTER_INPUT (element);
+ xmlNodePtr value;
+ GList *link;
+ const gchar *type;
+
+ type = input->type ? input->type : "string";
+
+ value = xmlNewNode (NULL, (xmlChar *) "value");
+ xmlSetProp (value, (xmlChar *) "name", (xmlChar *) element->name);
+ xmlSetProp (value, (xmlChar *) "type", (xmlChar *) type);
+
+ for (link = input->values; link != NULL; link = g_list_next (link)) {
+ xmlChar *str = link->data;
+ xmlNodePtr cur;
+
+ cur = xmlNewChild (value, NULL, (xmlChar *)type, NULL);
+
+ str = xmlEncodeEntitiesReentrant (NULL, str);
+ xmlNodeSetContent (cur, str);
+ xmlFree (str);
+ }
+
+ return value;
+}
+
+static gint
+filter_input_xml_decode (EFilterElement *element, xmlNodePtr node)
+{
+ EFilterInput *input = (EFilterInput *)element;
+ gchar *name, *str, *type;
+ xmlNodePtr child;
+
+ g_list_foreach (input->values, (GFunc) g_free, NULL);
+ g_list_free (input->values);
+ input->values = NULL;
+
+ name = (gchar *) xmlGetProp (node, (xmlChar *) "name");
+ type = (gchar *) xmlGetProp (node, (xmlChar *) "type");
+
+ xmlFree (element->name);
+ element->name = name;
+
+ xmlFree (input->type);
+ input->type = type;
+
+ child = node->children;
+ while (child != NULL) {
+ if (!strcmp ((gchar *)child->name, type)) {
+ if (!(str = (gchar *)xmlNodeGetContent (child)))
+ str = (gchar *)xmlStrdup ((xmlChar *)"");
+
+ input->values = g_list_append (input->values, g_strdup (str));
+ xmlFree (str);
+ } else if (child->type == XML_ELEMENT_NODE) {
+ g_warning (
+ "Unknown node type '%s' encountered "
+ "decoding a %s\n", child->name, type);
+ }
+ child = child->next;
+ }
+
+ return 0;
+}
+
+static GtkWidget *
+filter_input_get_widget (EFilterElement *element)
+{
+ EFilterInput *input = E_FILTER_INPUT (element);
+ GtkWidget *entry;
+
+ entry = gtk_entry_new ();
+ if (input->values && input->values->data)
+ gtk_entry_set_text (
+ GTK_ENTRY (entry), input->values->data);
+
+ g_signal_connect (
+ entry, "changed",
+ G_CALLBACK (filter_input_entry_changed), element);
+
+ return entry;
+}
+
+static void
+filter_input_format_sexp (EFilterElement *element,
+ GString *out)
+{
+ EFilterInput *input = E_FILTER_INPUT (element);
+ GList *link;
+
+ for (link = input->values; link != NULL; link = g_list_next (link))
+ e_sexp_encode_string (out, link->data);
+}
+
+static void
+filter_input_class_init (EFilterInputClass *class)
+{
+ GObjectClass *object_class;
+ EFilterElementClass *filter_element_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = filter_input_finalize;
+
+ filter_element_class = E_FILTER_ELEMENT_CLASS (class);
+ filter_element_class->validate = filter_input_validate;
+ filter_element_class->eq = filter_input_eq;
+ filter_element_class->xml_encode = filter_input_xml_encode;
+ filter_element_class->xml_decode = filter_input_xml_decode;
+ filter_element_class->get_widget = filter_input_get_widget;
+ filter_element_class->format_sexp = filter_input_format_sexp;
+}
+
+static void
+filter_input_init (EFilterInput *input)
+{
+ input->values = g_list_prepend (NULL, g_strdup (""));
+}
+
+GType
+e_filter_input_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFilterInputClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) filter_input_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFilterInput),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) filter_input_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ E_TYPE_FILTER_ELEMENT, "EFilterInput", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * filter_input_new:
+ *
+ * Create a new EFilterInput object.
+ *
+ * Return value: A new #EFilterInput object.
+ **/
+EFilterInput *
+e_filter_input_new (void)
+{
+ return g_object_new (E_TYPE_FILTER_INPUT, NULL);
+}
+
+EFilterInput *
+e_filter_input_new_type_name (const gchar *type)
+{
+ EFilterInput *input;
+
+ input = e_filter_input_new ();
+ input->type = (gchar *) xmlStrdup ((xmlChar *) type);
+
+ return input;
+}
+
+void
+e_filter_input_set_value (EFilterInput *input,
+ const gchar *value)
+{
+ g_return_if_fail (E_IS_FILTER_INPUT (input));
+
+ g_list_foreach (input->values, (GFunc) g_free, NULL);
+ g_list_free (input->values);
+
+ input->values = g_list_append (NULL, g_strdup (value));
+}
diff --git a/filter/e-filter-input.h b/filter/e-filter-input.h
new file mode 100644
index 0000000000..07239c92cb
--- /dev/null
+++ b/filter/e-filter-input.h
@@ -0,0 +1,74 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FILTER_INPUT_H
+#define E_FILTER_INPUT_H
+
+#include "e-filter-element.h"
+
+/* Standard GObject macros */
+#define E_TYPE_FILTER_INPUT \
+ (e_filter_input_get_type ())
+#define E_FILTER_INPUT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILTER_INPUT, EFilterInput))
+#define E_FILTER_INPUT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILTER_INPUT, EFilterInputClass))
+#define E_IS_FILTER_INPUT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILTER_INPUT))
+#define E_IS_FILTER_INPUT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILTER_INPUT))
+#define E_FILTER_INPUT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILTER_INPUT, EFilterInputClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EFilterInput EFilterInput;
+typedef struct _EFilterInputClass EFilterInputClass;
+typedef struct _EFilterInputPrivate EFilterInputPrivate;
+
+struct _EFilterInput {
+ EFilterElement parent;
+ EFilterInputPrivate *priv;
+
+ gchar *type; /* name of type */
+ GList *values; /* strings */
+};
+
+struct _EFilterInputClass {
+ EFilterElementClass parent_class;
+};
+
+GType e_filter_input_get_type (void);
+EFilterInput * e_filter_input_new (void);
+EFilterInput * e_filter_input_new_type_name (const gchar *type);
+void e_filter_input_set_value (EFilterInput *input,
+ const gchar *value);
+
+G_END_DECLS
+
+#endif /* E_FILTER_INPUT_H */
diff --git a/filter/e-filter-int.c b/filter/e-filter-int.c
new file mode 100644
index 0000000000..f3fef9dc89
--- /dev/null
+++ b/filter/e-filter-int.c
@@ -0,0 +1,261 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <gtk/gtk.h>
+
+#include <libedataserver/e-sexp.h>
+
+#include "e-filter-int.h"
+
+static gpointer parent_class;
+
+static void
+filter_int_spin_changed (GtkSpinButton *spin_button,
+ EFilterElement *element)
+{
+ EFilterInt *filter_int = E_FILTER_INT (element);
+
+ filter_int->val = gtk_spin_button_get_value_as_int (spin_button);
+}
+
+static void
+filter_int_finalize (GObject *object)
+{
+ EFilterInt *filter_int = E_FILTER_INT (object);
+
+ g_free (filter_int->type);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gint
+filter_int_eq (EFilterElement *element_a,
+ EFilterElement *element_b)
+{
+ EFilterInt *filter_int_a = E_FILTER_INT (element_a);
+ EFilterInt *filter_int_b = E_FILTER_INT (element_b);
+
+ /* Chain up to parent's eq() method. */
+ if (!E_FILTER_ELEMENT_CLASS (parent_class)->eq (element_a, element_b))
+ return FALSE;
+
+ return (filter_int_a->val == filter_int_b->val);
+}
+
+static EFilterElement *
+filter_int_clone (EFilterElement *element)
+{
+ EFilterInt *filter_int = E_FILTER_INT (element);
+ EFilterInt *clone;
+
+ clone = e_filter_int_new_type (
+ filter_int->type, filter_int->min, filter_int->max);
+ clone->val = filter_int->val;
+
+ E_FILTER_ELEMENT (clone)->name = g_strdup (element->name);
+
+ return E_FILTER_ELEMENT (clone);
+}
+
+static xmlNodePtr
+filter_int_xml_encode (EFilterElement *element)
+{
+ EFilterInt *filter_int = E_FILTER_INT (element);
+ xmlNodePtr value;
+ gchar intval[32];
+ const gchar *type;
+
+ type = filter_int->type ? filter_int->type : "integer";
+
+ value = xmlNewNode (NULL, (xmlChar *)"value");
+ xmlSetProp (value, (xmlChar *) "name", (xmlChar *) element->name);
+ xmlSetProp (value, (xmlChar *) "type", (xmlChar *) type);
+
+ sprintf (intval, "%d", filter_int->val);
+ xmlSetProp (value, (xmlChar *)type, (xmlChar *)intval);
+
+ return value;
+}
+
+static gint
+filter_int_xml_decode (EFilterElement *element,
+ xmlNodePtr node)
+{
+ EFilterInt *filter_int = E_FILTER_INT (element);
+ gchar *name, *type;
+ gchar *intval;
+
+ name = (gchar *)xmlGetProp (node, (xmlChar *)"name");
+ xmlFree (element->name);
+ element->name = name;
+
+ type = (gchar *)xmlGetProp (node, (xmlChar *)"type");
+ g_free (filter_int->type);
+ filter_int->type = g_strdup (type);
+ xmlFree (type);
+
+ intval = (gchar *)xmlGetProp (node, (xmlChar *)(filter_int->type ? filter_int->type : "integer"));
+ if (intval) {
+ filter_int->val = atoi (intval);
+ xmlFree (intval);
+ } else {
+ filter_int->val = 0;
+ }
+
+ return 0;
+}
+
+static GtkWidget *
+filter_int_get_widget (EFilterElement *element)
+{
+ EFilterInt *filter_int = E_FILTER_INT (element);
+ GtkWidget *widget;
+ GtkObject *adjustment;
+
+ adjustment = gtk_adjustment_new (
+ 0.0, (gfloat) filter_int->min,
+ (gfloat) filter_int->max, 1.0, 1.0, 0);
+ widget = gtk_spin_button_new (
+ GTK_ADJUSTMENT (adjustment),
+ filter_int->max > filter_int->min + 1000 ? 5.0 : 1.0, 0);
+ gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (widget), TRUE);
+
+ if (filter_int->val)
+ gtk_spin_button_set_value (
+ GTK_SPIN_BUTTON (widget), (gfloat) filter_int->val);
+
+ g_signal_connect (
+ widget, "value-changed",
+ G_CALLBACK (filter_int_spin_changed), element);
+
+ return widget;
+}
+
+static void
+filter_int_format_sexp (EFilterElement *element,
+ GString *out)
+{
+ EFilterInt *filter_int = E_FILTER_INT (element);
+
+ if (filter_int->val < 0)
+ /* See #364731 #457523 C6*/
+ g_string_append_printf (out, "(- %d)", (filter_int->val * -1));
+ else
+ g_string_append_printf (out, "%d", filter_int->val);
+}
+
+static void
+filter_int_class_init (EFilterIntClass *class)
+{
+ GObjectClass *object_class;
+ EFilterElementClass *filter_element_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = filter_int_finalize;
+
+ filter_element_class = E_FILTER_ELEMENT_CLASS (class);
+ filter_element_class->eq = filter_int_eq;
+ filter_element_class->clone = filter_int_clone;
+ filter_element_class->xml_encode = filter_int_xml_encode;
+ filter_element_class->xml_decode = filter_int_xml_decode;
+ filter_element_class->get_widget = filter_int_get_widget;
+ filter_element_class->format_sexp = filter_int_format_sexp;
+}
+
+static void
+filter_int_init (EFilterInt *filter_int)
+{
+ filter_int->min = 0;
+ filter_int->max = G_MAXINT;
+}
+
+GType
+e_filter_int_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFilterIntClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) filter_int_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFilterInt),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) filter_int_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ E_TYPE_FILTER_ELEMENT, "EFilterInt", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * filter_int_new:
+ *
+ * Create a new EFilterInt object.
+ *
+ * Return value: A new #EFilterInt object.
+ **/
+EFilterInt *
+e_filter_int_new (void)
+{
+ return g_object_new (E_TYPE_FILTER_INT, NULL);
+}
+
+EFilterInt *
+e_filter_int_new_type (const gchar *type,
+ gint min,
+ gint max)
+{
+ EFilterInt *filter_int;
+
+ filter_int = e_filter_int_new ();
+
+ filter_int->type = g_strdup (type);
+ filter_int->min = min;
+ filter_int->max = max;
+
+ return filter_int;
+}
+
+void
+e_filter_int_set_value (EFilterInt *filter_int,
+ gint value)
+{
+ g_return_if_fail (E_IS_FILTER_INT (filter_int));
+
+ filter_int->val = value;
+}
diff --git a/filter/e-filter-int.h b/filter/e-filter-int.h
new file mode 100644
index 0000000000..c9f613c9a3
--- /dev/null
+++ b/filter/e-filter-int.h
@@ -0,0 +1,77 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FILTER_INT_H
+#define E_FILTER_INT_H
+
+#include "e-filter-element.h"
+
+/* Standard GObject macros */
+#define E_TYPE_FILTER_INT \
+ (e_filter_int_get_type ())
+#define E_FILTER_INT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILTER_INT, EFilterInt))
+#define E_FILTER_INT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILTER_INT, EFilterIntClass))
+#define E_IS_FILTER_INT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILTER_INT))
+#define E_IS_FILTER_INT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILTER_INT))
+#define E_FILTER_INT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILTER_INT, EFilterIntClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EFilterInt EFilterInt;
+typedef struct _EFilterIntClass EFilterIntClass;
+typedef struct _EFilterIntPrivate EFilterIntPrivate;
+
+struct _EFilterInt {
+ EFilterElement parent;
+ EFilterIntPrivate *priv;
+
+ gchar *type;
+ gint val;
+ gint min;
+ gint max;
+};
+
+struct _EFilterIntClass {
+ EFilterElementClass parent_class;
+};
+
+GType e_filter_int_get_type (void);
+EFilterInt * e_filter_int_new (void);
+EFilterInt * e_filter_int_new_type (const gchar *type,
+ gint min,
+ gint max);
+void e_filter_int_set_value (EFilterInt *f_int,
+ gint value);
+
+G_END_DECLS
+
+#endif /* E_FILTER_INT_H */
diff --git a/filter/e-filter-option.c b/filter/e-filter-option.c
new file mode 100644
index 0000000000..3765238a80
--- /dev/null
+++ b/filter/e-filter-option.c
@@ -0,0 +1,514 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <gmodule.h>
+
+#include <libedataserver/e-sexp.h>
+
+#include "e-filter-option.h"
+#include "e-filter-part.h"
+
+static gpointer parent_class;
+
+static void
+free_option (struct _filter_option *opt)
+{
+ g_free (opt->title);
+ g_free (opt->value);
+ g_free (opt->code);
+ g_free (opt);
+}
+
+static struct _filter_option *
+find_option (EFilterOption *option,
+ const gchar *name)
+{
+ GList *link;
+
+ for (link = option->options; link != NULL; link = g_list_next (link)) {
+ struct _filter_option *opt = link->data;
+
+ if (strcmp (name, opt->value) == 0)
+ return opt;
+ }
+
+ return NULL;
+}
+
+static void
+filter_option_combobox_changed (GtkComboBox *combo_box,
+ EFilterElement *element)
+{
+ EFilterOption *option = E_FILTER_OPTION (element);
+ gint active;
+
+ active = gtk_combo_box_get_active (combo_box);
+ option->current = g_list_nth_data (option->options, active);
+}
+
+static GSList *
+filter_option_get_dynamic_options (EFilterOption *option)
+{
+ GModule *module;
+ GSList *(*get_func)(void);
+ GSList *res = NULL;
+
+ if (!option || !option->dynamic_func)
+ return res;
+
+ module = g_module_open (NULL, G_MODULE_BIND_LAZY);
+
+ if (g_module_symbol (module, option->dynamic_func, (gpointer) &get_func)) {
+ res = get_func ();
+ } else {
+ g_warning ("optionlist dynamic fill function '%s' not found", option->dynamic_func);
+ }
+
+ g_module_close (module);
+
+ return res;
+}
+
+static void
+filter_option_finalize (GObject *object)
+{
+ EFilterOption *option = E_FILTER_OPTION (object);
+
+ g_list_foreach (option->options, (GFunc) free_option, NULL);
+ g_list_free (option->options);
+
+ g_free (option->dynamic_func);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gint
+filter_option_eq (EFilterElement *element_a,
+ EFilterElement *element_b)
+{
+ EFilterOption *option_a = E_FILTER_OPTION (element_a);
+ EFilterOption *option_b = E_FILTER_OPTION (element_b);
+
+ /* Chain up to parent's eq() method. */
+ if (!E_FILTER_ELEMENT_CLASS (parent_class)->eq (element_a, element_b))
+ return FALSE;
+
+ if (option_a->current == NULL && option_b->current == NULL)
+ return TRUE;
+
+ if (option_a->current == NULL || option_b->current == NULL)
+ return FALSE;
+
+ return (g_strcmp0 (option_a->current->value, option_b->current->value) == 0);
+}
+
+static void
+filter_option_xml_create (EFilterElement *element,
+ xmlNodePtr node)
+{
+ EFilterOption *option = E_FILTER_OPTION (element);
+ xmlNodePtr n, work;
+
+ /* Chain up to parent's xml_create() method. */
+ E_FILTER_ELEMENT_CLASS (parent_class)->xml_create (element, node);
+
+ n = node->children;
+ while (n) {
+ if (!strcmp ((gchar *)n->name, "option")) {
+ gchar *tmp, *value, *title = NULL, *code = NULL;
+
+ value = (gchar *)xmlGetProp (n, (xmlChar *)"value");
+ work = n->children;
+ while (work) {
+ if (!strcmp ((gchar *)work->name, "title") || !strcmp ((gchar *)work->name, "_title")) {
+ if (!title) {
+ if (!(tmp = (gchar *)xmlNodeGetContent (work)))
+ tmp = (gchar *)xmlStrdup ((xmlChar *)"");
+
+ title = g_strdup (tmp);
+ xmlFree (tmp);
+ }
+ } else if (!strcmp ((gchar *)work->name, "code")) {
+ if (!code) {
+ if (!(tmp = (gchar *)xmlNodeGetContent (work)))
+ tmp = (gchar *)xmlStrdup ((xmlChar *)"");
+
+ code = g_strdup (tmp);
+ xmlFree (tmp);
+ }
+ }
+ work = work->next;
+ }
+
+ e_filter_option_add (option, value, title, code, FALSE);
+ xmlFree (value);
+ g_free (title);
+ g_free (code);
+ } else if (g_str_equal ((gchar *)n->name, "dynamic")) {
+ if (option->dynamic_func) {
+ g_warning ("Only one 'dynamic' node is acceptable in the optionlist '%s'", element->name);
+ } else {
+ /* Expecting only one <dynamic func="cb" /> in the option list,
+ The 'cb' should be of this prototype:
+ GSList *cb (void);
+ returning GSList of struct _filter_option, all newly allocated, because it'll
+ be freed with g_free and g_slist_free. 'is_dynamic' member is ignored here.
+ */
+ xmlChar *fn;
+
+ fn = xmlGetProp (n, (xmlChar *)"func");
+ if (fn && *fn) {
+ GSList *items, *i;
+ struct _filter_option *op;
+
+ option->dynamic_func = g_strdup ((const gchar *)fn);
+
+ /* get options now, to have them available when reading saved rules */
+ items = filter_option_get_dynamic_options (option);
+ for (i = items; i; i = i->next) {
+ op = i->data;
+
+ if (op) {
+ e_filter_option_add (option, op->value, op->title, op->code, TRUE);
+ free_option (op);
+ }
+ }
+
+ g_slist_free (items);
+ } else {
+ g_warning ("Missing 'func' attribute within '%s' node in optionlist '%s'", n->name, element->name);
+ }
+
+ xmlFree (fn);
+ }
+ } else if (n->type == XML_ELEMENT_NODE) {
+ g_warning ("Unknown xml node within optionlist: %s\n", n->name);
+ }
+ n = n->next;
+ }
+}
+
+static xmlNodePtr
+filter_option_xml_encode (EFilterElement *element)
+{
+ EFilterOption *option = E_FILTER_OPTION (element);
+ xmlNodePtr value;
+
+ value = xmlNewNode (NULL, (xmlChar *) "value");
+ xmlSetProp (value, (xmlChar *) "name", (xmlChar *) element->name);
+ xmlSetProp (value, (xmlChar *) "type", (xmlChar *) option->type);
+ if (option->current)
+ xmlSetProp (value, (xmlChar *) "value", (xmlChar *)option->current->value);
+
+ return value;
+}
+
+static gint
+filter_option_xml_decode (EFilterElement *element,
+ xmlNodePtr node)
+{
+ EFilterOption *option = E_FILTER_OPTION (element);
+ gchar *value;
+
+ xmlFree (element->name);
+ element->name = (gchar *)xmlGetProp (node, (xmlChar *)"name");
+
+ value = (gchar *)xmlGetProp (node, (xmlChar *)"value");
+ if (value) {
+ option->current = find_option (option, value);
+ xmlFree (value);
+ } else {
+ option->current = NULL;
+ }
+
+ return 0;
+}
+
+static EFilterElement *
+filter_option_clone (EFilterElement *element)
+{
+ EFilterOption *option = E_FILTER_OPTION (element);
+ EFilterOption *clone_option;
+ EFilterElement *clone;
+ GList *link;
+
+ /* Chain up to parent's clone() method. */
+ clone = E_FILTER_ELEMENT_CLASS (parent_class)->clone (element);
+
+ clone_option = E_FILTER_OPTION (clone);
+
+ for (link = option->options; link != NULL; link = g_list_next (link)) {
+ struct _filter_option *op = link->data;
+ struct _filter_option *newop;
+
+ newop = e_filter_option_add (
+ clone_option, op->value,
+ op->title, op->code, op->is_dynamic);
+ if (option->current == op)
+ clone_option->current = newop;
+ }
+
+ clone_option->dynamic_func = g_strdup (option->dynamic_func);
+
+ return clone;
+}
+
+static GtkWidget *
+filter_option_get_widget (EFilterElement *element)
+{
+ EFilterOption *option = E_FILTER_OPTION (element);
+ GtkWidget *combobox;
+ GList *l;
+ struct _filter_option *op;
+ gint index = 0, current = 0;
+
+ if (option->dynamic_func) {
+ /* it is dynamically filled, thus remove all dynamics and put there the fresh ones */
+ GSList *items, *i;
+ GList *old_ops;
+ struct _filter_option *old_cur;
+
+ old_ops = option->options;
+ old_cur = option->current;
+ l = old_ops;
+
+ /* start with an empty list */
+ option->current = NULL;
+ option->options = NULL;
+
+ for (l = option->options; l; l = l->next) {
+ op = l->data;
+
+ if (op->is_dynamic) {
+ break;
+ } else {
+ e_filter_option_add (option, op->value, op->title, op->code, FALSE);
+ }
+ }
+
+ items = filter_option_get_dynamic_options (option);
+ for (i = items; i; i = i->next) {
+ op = i->data;
+
+ if (op) {
+ e_filter_option_add (option, op->value, op->title, op->code, TRUE);
+ free_option (op);
+ }
+ }
+
+ g_slist_free (items);
+
+ /* maybe some static left after those dynamic, add them too */
+ for (; l; l = l->next) {
+ op = l->data;
+
+ if (!op->is_dynamic)
+ e_filter_option_add (option, op->value, op->title, op->code, FALSE);
+ }
+
+ if (old_cur)
+ e_filter_option_set_current (option, old_cur->value);
+
+ /* free old list */
+ g_list_foreach (old_ops, (GFunc)free_option, NULL);
+ g_list_free (old_ops);
+ }
+
+ combobox = gtk_combo_box_new_text ();
+ l = option->options;
+ while (l) {
+ op = l->data;
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combobox), _(op->title));
+
+ if (op == option->current)
+ current = index;
+
+ l = g_list_next (l);
+ index++;
+ }
+
+ g_signal_connect (
+ combobox, "changed",
+ G_CALLBACK (filter_option_combobox_changed), element);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), current);
+
+ return combobox;
+}
+
+static void
+filter_option_build_code (EFilterElement *element,
+ GString *out,
+ EFilterPart *part)
+{
+ EFilterOption *option = E_FILTER_OPTION (element);
+
+ if (option->current && option->current->code)
+ e_filter_part_expand_code (part, option->current->code, out);
+}
+
+static void
+filter_option_format_sexp (EFilterElement *element,
+ GString *out)
+{
+ EFilterOption *option = E_FILTER_OPTION (element);
+
+ if (option->current)
+ e_sexp_encode_string (out, option->current->value);
+}
+
+static void
+filter_option_class_init (EFilterOptionClass *class)
+{
+ GObjectClass *object_class;
+ EFilterElementClass *filter_element_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = filter_option_finalize;
+
+ filter_element_class = E_FILTER_ELEMENT_CLASS (class);
+ filter_element_class->eq = filter_option_eq;
+ filter_element_class->xml_create = filter_option_xml_create;
+ filter_element_class->xml_encode = filter_option_xml_encode;
+ filter_element_class->xml_decode = filter_option_xml_decode;
+ filter_element_class->clone = filter_option_clone;
+ filter_element_class->get_widget = filter_option_get_widget;
+ filter_element_class->build_code = filter_option_build_code;
+ filter_element_class->format_sexp = filter_option_format_sexp;
+}
+
+static void
+filter_option_init (EFilterOption *option)
+{
+ option->type = "option";
+ option->dynamic_func = NULL;
+}
+
+GType
+e_filter_option_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFilterOptionClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) filter_option_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFilterOption),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) filter_option_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ E_TYPE_FILTER_ELEMENT, "EFilterOption", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * filter_option_new:
+ *
+ * Create a new EFilterOption object.
+ *
+ * Return value: A new #EFilterOption object.
+ **/
+EFilterOption *
+e_filter_option_new (void)
+{
+ return g_object_new (E_TYPE_FILTER_OPTION, NULL);
+}
+
+void
+e_filter_option_set_current (EFilterOption *option,
+ const gchar *name)
+{
+ g_return_if_fail (E_IS_FILTER_OPTION (option));
+
+ option->current = find_option (option, name);
+}
+
+/* used by implementers to add additional options */
+struct _filter_option *
+e_filter_option_add (EFilterOption *option,
+ const gchar *value,
+ const gchar *title,
+ const gchar *code,
+ gboolean is_dynamic)
+{
+ struct _filter_option *op;
+
+ g_return_val_if_fail (E_IS_FILTER_OPTION (option), NULL);
+ g_return_val_if_fail (find_option (option, value) == NULL, NULL);
+
+ op = g_malloc (sizeof (*op));
+ op->title = g_strdup (title);
+ op->value = g_strdup (value);
+ op->code = g_strdup (code);
+ op->is_dynamic = is_dynamic;
+
+ option->options = g_list_append (option->options, op);
+
+ if (option->current == NULL)
+ option->current = op;
+
+ return op;
+}
+
+const gchar *
+e_filter_option_get_current (EFilterOption *option)
+{
+ g_return_val_if_fail (E_IS_FILTER_OPTION (option), NULL);
+
+ if (option->current == NULL)
+ return NULL;
+
+ return option->current->value;
+}
+
+void
+e_filter_option_remove_all (EFilterOption *option)
+{
+ g_return_if_fail (E_IS_FILTER_OPTION (option));
+
+ g_list_foreach (option->options, (GFunc) free_option, NULL);
+ g_list_free (option->options);
+
+ option->options = NULL;
+ option->current = NULL;
+}
diff --git a/filter/e-filter-option.h b/filter/e-filter-option.h
new file mode 100644
index 0000000000..c42efe2fe3
--- /dev/null
+++ b/filter/e-filter-option.h
@@ -0,0 +1,92 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FILTER_OPTION_H
+#define E_FILTER_OPTION_H
+
+#include "e-filter-element.h"
+
+/* Standard GObject macros */
+#define E_TYPE_FILTER_OPTION \
+ (e_filter_option_get_type ())
+#define E_FILTER_OPTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILTER_OPTION, EFilterOption))
+#define E_FILTER_OPTION_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILTER_OPTION, EFilterOptionClass))
+#define E_IS_FILTER_OPTION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILTER_OPTION))
+#define E_IS_FILTER_OPTION_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILTER_OPTION))
+#define E_FILTER_OPTION_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILTER_OPTION, EFilterOptionClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EFilterOption EFilterOption;
+typedef struct _EFilterOptionClass EFilterOptionClass;
+typedef struct _EFilterOptionPrivate EFilterOptionPrivate;
+
+struct _filter_option {
+ gchar *title; /* button title */
+ gchar *value; /* value, if it has one */
+ gchar *code; /* used to string code segments together */
+
+ gboolean is_dynamic; /* whether is the option dynamic, FALSE if static */
+};
+
+struct _EFilterOption {
+ EFilterElement parent;
+ EFilterOptionPrivate *priv;
+
+ const gchar *type; /* static memory, type name written to xml */
+
+ GList *options;
+ struct _filter_option *current;
+ gchar *dynamic_func; /* name of the dynamic fill func, called in get_widget */
+};
+
+struct _EFilterOptionClass {
+ EFilterElementClass parent_class;
+};
+
+GType e_filter_option_get_type (void);
+EFilterOption * e_filter_option_new (void);
+void e_filter_option_set_current (EFilterOption *option,
+ const gchar *name);
+const gchar * e_filter_option_get_current (EFilterOption *option);
+struct _filter_option *
+ e_filter_option_add (EFilterOption *option,
+ const gchar *name,
+ const gchar *title,
+ const gchar *code,
+ gboolean is_dynamic);
+void e_filter_option_remove_all (EFilterOption *option);
+
+G_END_DECLS
+
+#endif /* E_FILTER_OPTION_H */
diff --git a/filter/e-filter-part.c b/filter/e-filter-part.c
new file mode 100644
index 0000000000..37e2bf61df
--- /dev/null
+++ b/filter/e-filter-part.c
@@ -0,0 +1,532 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jepartrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "e-filter-file.h"
+#include "e-filter-part.h"
+#include "e-rule-context.h"
+
+static gpointer parent_class;
+
+static void
+filter_part_finalize (GObject *object)
+{
+ EFilterPart *part = E_FILTER_PART (object);
+
+ g_list_foreach (part->elements, (GFunc) g_object_unref, NULL);
+ g_list_free (part->elements);
+
+ g_free (part->name);
+ g_free (part->title);
+ g_free (part->code);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+filter_part_class_init (EFilterPartClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = filter_part_finalize;
+}
+
+GType
+e_filter_part_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFilterPartClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) filter_part_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFilterPart),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ G_TYPE_OBJECT, "EFilterPart", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * e_filter_part_new:
+ *
+ * Create a new EFilterPart object.
+ *
+ * Return value: A new #EFilterPart object.
+ **/
+EFilterPart *
+e_filter_part_new (void)
+{
+ return g_object_new (E_TYPE_FILTER_PART, NULL);
+}
+
+gboolean
+e_filter_part_validate (EFilterPart *part,
+ GtkWindow *error_parent)
+{
+ GList *link;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), FALSE);
+
+ /* The part is valid if all of its elements are valid. */
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+
+ if (!e_filter_element_validate (element, error_parent))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gint
+e_filter_part_eq (EFilterPart *part_a,
+ EFilterPart *part_b)
+{
+ GList *link_a, *link_b;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part_a), FALSE);
+ g_return_val_if_fail (E_IS_FILTER_PART (part_b), FALSE);
+
+ if (g_strcmp0 (part_a->name, part_b->name) != 0)
+ return FALSE;
+
+ if (g_strcmp0 (part_a->title, part_b->title) != 0)
+ return FALSE;
+
+ if (g_strcmp0 (part_a->code, part_b->code) != 0)
+ return FALSE;
+
+ link_a = part_a->elements;
+ link_b = part_b->elements;
+
+ while (link_a != NULL && link_b != NULL) {
+ EFilterElement *element_a = link_a->data;
+ EFilterElement *element_b = link_b->data;
+
+ if (!e_filter_element_eq (element_a, element_b))
+ return FALSE;
+
+ link_a = g_list_next (link_a);
+ link_b = g_list_next (link_b);
+ }
+
+ if (link_a != NULL || link_b != NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+gint
+e_filter_part_xml_create (EFilterPart *part,
+ xmlNodePtr node,
+ ERuleContext *context)
+{
+ xmlNodePtr n;
+ gchar *type, *str;
+ EFilterElement *el;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), FALSE);
+ g_return_val_if_fail (node != NULL, FALSE);
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), FALSE);
+
+ str = (gchar *)xmlGetProp (node, (xmlChar *)"name");
+ part->name = g_strdup (str);
+ if (str)
+ xmlFree (str);
+
+ n = node->children;
+ while (n) {
+ if (!strcmp ((gchar *)n->name, "input")) {
+ type = (gchar *)xmlGetProp (n, (xmlChar *)"type");
+ if (type != NULL
+ && (el = e_rule_context_new_element (context, type)) != NULL) {
+ e_filter_element_xml_create (el, n);
+ xmlFree (type);
+ part->elements = g_list_append (part->elements, el);
+ } else {
+ g_warning ("Invalid xml format, missing/unknown input type");
+ }
+ } else if (!strcmp ((gchar *)n->name, "title") || !strcmp ((gchar *)n->name, "_title")) {
+ if (!part->title) {
+ str = (gchar *)xmlNodeGetContent (n);
+ part->title = g_strdup (str);
+ if (str)
+ xmlFree (str);
+ }
+ } else if (!strcmp ((gchar *)n->name, "code")) {
+ if (!part->code) {
+ str = (gchar *)xmlNodeGetContent (n);
+ part->code = g_strdup (str);
+ if (str)
+ xmlFree (str);
+ }
+ } else if (n->type == XML_ELEMENT_NODE) {
+ g_warning ("Unknown part element in xml: %s\n", n->name);
+ }
+ n = n->next;
+ }
+
+ return 0;
+}
+
+xmlNodePtr
+e_filter_part_xml_encode (EFilterPart *part)
+{
+ xmlNodePtr node;
+ GList *link;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), NULL);
+
+ node = xmlNewNode (NULL, (xmlChar *)"part");
+ xmlSetProp (node, (xmlChar *)"name", (xmlChar *)part->name);
+
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+ xmlNodePtr value;
+
+ value = e_filter_element_xml_encode (element);
+ xmlAddChild (node, value);
+ }
+
+ return node;
+}
+
+gint
+e_filter_part_xml_decode (EFilterPart *part,
+ xmlNodePtr node)
+{
+ xmlNodePtr child;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), -1);
+ g_return_val_if_fail (node != NULL, -1);
+
+ for (child = node->children; child != NULL; child = child->next) {
+ EFilterElement *element;
+ xmlChar *name;
+
+ if (strcmp ((gchar *) child->name, "value") != 0)
+ continue;
+
+ name = xmlGetProp (child, (xmlChar *) "name");
+ element = e_filter_part_find_element (part, (gchar *) name);
+ xmlFree (name);
+
+ if (element != NULL)
+ e_filter_element_xml_decode (element, child);
+ }
+
+ return 0;
+}
+
+EFilterPart *
+e_filter_part_clone (EFilterPart *part)
+{
+ EFilterPart *clone;
+ GList *link;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), NULL);
+
+ clone = g_object_new (G_OBJECT_TYPE (part), NULL, NULL);
+ clone->name = g_strdup (part->name);
+ clone->title = g_strdup (part->title);
+ clone->code = g_strdup (part->code);
+
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+ EFilterElement *clone_element;
+
+ clone_element = e_filter_element_clone (element);
+ clone->elements = g_list_append (clone->elements, clone_element);
+ }
+
+ return clone;
+}
+
+/* only copies values of matching parts in the right order */
+void
+e_filter_part_copy_values (EFilterPart *dst_part,
+ EFilterPart *src_part)
+{
+ GList *dst_link, *src_link;
+
+ g_return_if_fail (E_IS_FILTER_PART (dst_part));
+ g_return_if_fail (E_IS_FILTER_PART (src_part));
+
+ /* NOTE: we go backwards, it just works better that way */
+
+ /* for each source type, search the dest type for
+ a matching type in the same order */
+ src_link = g_list_last (src_part->elements);
+ dst_link = g_list_last (dst_part->elements);
+
+ while (src_link != NULL && dst_link != NULL) {
+ EFilterElement *src_element = src_link->data;
+ GList *link = dst_link;
+
+ while (link != NULL) {
+ EFilterElement *dst_element = link->data;
+ GType dst_type = G_OBJECT_TYPE (dst_element);
+ GType src_type = G_OBJECT_TYPE (src_element);
+
+ if (dst_type == src_type) {
+ e_filter_element_copy_value (
+ dst_element, src_element);
+ dst_link = g_list_previous (link);
+ break;
+ }
+
+ link = g_list_previous (link);
+ }
+
+ src_link = g_list_previous (src_link);
+ }
+}
+
+EFilterElement *
+e_filter_part_find_element (EFilterPart *part,
+ const gchar *name)
+{
+ GList *link;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), NULL);
+
+ if (name == NULL)
+ return NULL;
+
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+
+ if (g_strcmp0 (element->name, name) == 0)
+ return element;
+ }
+
+ return NULL;
+}
+
+GtkWidget *
+e_filter_part_get_widget (EFilterPart *part)
+{
+ GtkWidget *hbox;
+ GList *link;
+
+ g_return_val_if_fail (E_IS_FILTER_PART (part), NULL);
+
+ hbox = gtk_hbox_new (FALSE, 3);
+
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+ GtkWidget *widget;
+
+ widget = e_filter_element_get_widget (element);
+ if (widget != NULL)
+ gtk_box_pack_start (
+ GTK_BOX (hbox), widget,
+ E_IS_FILTER_FILE (element),
+ E_IS_FILTER_FILE (element), 3);
+ }
+
+ gtk_widget_show_all (hbox);
+
+ return hbox;
+}
+
+/**
+ * e_filter_part_build_code:
+ * @part:
+ * @out:
+ *
+ * Outputs the code of a part.
+ **/
+void
+e_filter_part_build_code (EFilterPart *part,
+ GString *out)
+{
+ GList *link;
+
+ g_return_if_fail (E_IS_FILTER_PART (part));
+ g_return_if_fail (out != NULL);
+
+ if (part->code != NULL)
+ e_filter_part_expand_code (part, part->code, out);
+
+ for (link = part->elements; link != NULL; link = g_list_next (link)) {
+ EFilterElement *element = link->data;
+ e_filter_element_build_code (element, out, part);
+ }
+}
+
+/**
+ * e_filter_part_build_code_list:
+ * @l:
+ * @out:
+ *
+ * Construct a list of the filter parts code into
+ * a single string.
+ **/
+void
+e_filter_part_build_code_list (GList *list,
+ GString *out)
+{
+ GList *link;
+
+ g_return_if_fail (out != NULL);
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ EFilterPart *part = link->data;
+
+ e_filter_part_build_code (part, out);
+ g_string_append (out, "\n ");
+ }
+}
+
+/**
+ * e_filter_part_find_list:
+ * @l:
+ * @name:
+ *
+ * Find a filter part stored in a list.
+ *
+ * Return value:
+ **/
+EFilterPart *
+e_filter_part_find_list (GList *list,
+ const gchar *name)
+{
+ GList *link;
+
+ g_return_val_if_fail (name != NULL, NULL);
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ EFilterPart *part = link->data;
+
+ if (!g_strcmp0 (part->name, name) == 0)
+ return part;
+ }
+
+ return NULL;
+}
+
+/**
+ * e_filter_part_next_list:
+ * @l:
+ * @last: The last item retrieved, or NULL to start
+ * from the beginning of the list.
+ *
+ * Iterate through a filter part list.
+ *
+ * Return value: The next value in the list, or NULL if the
+ * list is expired.
+ **/
+EFilterPart *
+e_filter_part_next_list (GList *list,
+ EFilterPart *last)
+{
+ GList *link = list;
+
+ if (last != NULL) {
+ link = g_list_find (list, last);
+ if (link == NULL)
+ link = list;
+ else
+ link = link->next;
+ }
+
+ return (link != NULL) ? link->data : NULL;
+}
+
+/**
+ * e_filter_part_expand_code:
+ * @part:
+ * @str:
+ * @out:
+ *
+ * Expands the variables in string @str based on the values of the part.
+ **/
+void
+e_filter_part_expand_code (EFilterPart *part,
+ const gchar *source,
+ GString *out)
+{
+ const gchar *newstart, *start, *end;
+ gchar *name = alloca (32);
+ gint len, namelen = 32;
+
+ g_return_if_fail (E_IS_FILTER_PART (part));
+ g_return_if_fail (source != NULL);
+ g_return_if_fail (out != NULL);
+
+ start = source;
+
+ while (start && (newstart = strstr (start, "${"))
+ && (end = strstr (newstart+2, "}")) ) {
+ EFilterElement *element;
+
+ len = end - newstart - 2;
+ if (len + 1 > namelen) {
+ namelen = (len + 1) * 2;
+ name = g_alloca (namelen);
+ }
+ memcpy (name, newstart+2, len);
+ name[len] = 0;
+
+ element = e_filter_part_find_element (part, name);
+ if (element != NULL) {
+ g_string_append_printf (out, "%.*s", (gint)(newstart-start), start);
+ e_filter_element_format_sexp (element, out);
+#if 0
+ } else if ((val = g_hash_table_lookup (part->globals, name))) {
+ g_string_append_printf (out, "%.*s", newstart-start, start);
+ e_sexp_encode_string (out, val);
+#endif
+ } else {
+ g_string_append_printf (out, "%.*s", (gint)(end-start+1), start);
+ }
+ start = end + 1;
+ }
+
+ g_string_append (out, start);
+}
diff --git a/filter/e-filter-part.h b/filter/e-filter-part.h
new file mode 100644
index 0000000000..697cf8f787
--- /dev/null
+++ b/filter/e-filter-part.h
@@ -0,0 +1,104 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FILTER_PART_H
+#define E_FILTER_PART_H
+
+#include <gtk/gtk.h>
+#include "e-filter-input.h"
+
+/* Standard GObject macros */
+#define E_TYPE_FILTER_PART \
+ (e_filter_part_get_type ())
+#define E_FILTER_PART(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILTER_PART, EFilterPart))
+#define E_FILTER_PART_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILTER_PART, EFilterPartClass))
+#define E_IS_FILTER_PART(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILTER_PART))
+#define E_IS_FILTER_PART_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILTER_PART))
+#define E_FILTER_PART_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILTER_PART, EFilterPartClass))
+
+G_BEGIN_DECLS
+
+struct _ERuleContext;
+
+typedef struct _EFilterPart EFilterPart;
+typedef struct _EFilterPartClass EFilterPartClass;
+typedef struct _EFilterPartPrivate EFilterPartPrivate;
+
+struct _EFilterPart {
+ GObject parent;
+ EFilterPartPrivate *priv;
+
+ gchar *name;
+ gchar *title;
+ gchar *code;
+ GList *elements;
+};
+
+struct _EFilterPartClass {
+ GObjectClass parent_class;
+};
+
+GType e_filter_part_get_type (void);
+EFilterPart * e_filter_part_new (void);
+gboolean e_filter_part_validate (EFilterPart *part,
+ GtkWindow *error_parent);
+gint e_filter_part_eq (EFilterPart *part_a,
+ EFilterPart *part_b);
+gint e_filter_part_xml_create (EFilterPart *part,
+ xmlNodePtr node,
+ struct _ERuleContext *rc);
+xmlNodePtr e_filter_part_xml_encode (EFilterPart *fe);
+gint e_filter_part_xml_decode (EFilterPart *fe,
+ xmlNodePtr node);
+EFilterPart * e_filter_part_clone (EFilterPart *part);
+void e_filter_part_copy_values (EFilterPart *dst_part,
+ EFilterPart *src_part);
+EFilterElement *e_filter_part_find_element (EFilterPart *part,
+ const gchar *name);
+GtkWidget * e_filter_part_get_widget (EFilterPart *part);
+void e_filter_part_build_code (EFilterPart *part,
+ GString *out);
+void e_filter_part_expand_code (EFilterPart *part,
+ const gchar *str,
+ GString *out);
+
+void e_filter_part_build_code_list (GList *list,
+ GString *out);
+EFilterPart * e_filter_part_find_list (GList *list,
+ const gchar *name);
+EFilterPart * e_filter_part_next_list (GList *list,
+ EFilterPart *last);
+
+G_END_DECLS
+
+#endif /* E_FILTER_PART_H */
diff --git a/filter/e-filter-rule.c b/filter/e-filter-rule.c
new file mode 100644
index 0000000000..f60230dc31
--- /dev/null
+++ b/filter/e-filter-rule.c
@@ -0,0 +1,1116 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "e-util/e-error.h"
+
+#include "e-filter-rule.h"
+#include "e-rule-context.h"
+
+#define E_FILTER_RULE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_FILTER_RULE, EFilterRulePrivate))
+
+typedef struct _FilterPartData FilterPartData;
+typedef struct _FilterRuleData FilterRuleData;
+
+struct _EFilterRulePrivate {
+ gint frozen;
+};
+
+struct _FilterPartData {
+ EFilterRule *rule;
+ ERuleContext *context;
+ EFilterPart *part;
+ GtkWidget *partwidget;
+ GtkWidget *container;
+};
+
+struct _FilterRuleData {
+ EFilterRule *rule;
+ ERuleContext *context;
+ GtkWidget *parts;
+};
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+static void
+filter_rule_grouping_changed_cb (GtkComboBox *combo_box,
+ EFilterRule *rule)
+{
+ rule->grouping = gtk_combo_box_get_active (combo_box);
+}
+
+static void
+filter_rule_threading_changed_cb (GtkComboBox *combo_box,
+ EFilterRule *rule)
+{
+ rule->threading = gtk_combo_box_get_active (combo_box);
+}
+
+static void
+part_combobox_changed (GtkComboBox *combobox,
+ FilterPartData *data)
+{
+ EFilterPart *part = NULL;
+ EFilterPart *newpart;
+ gint index, i;
+
+ index = gtk_combo_box_get_active (combobox);
+ for (i = 0, part = e_rule_context_next_part (data->context, part); part && i < index; i++, part = e_rule_context_next_part (data->context, part)) {
+ /* traverse until reached index */
+ }
+
+ g_return_if_fail (part != NULL);
+ g_return_if_fail (i == index);
+
+ /* dont update if we haven't changed */
+ if (!strcmp (part->title, data->part->title))
+ return;
+
+ /* here we do a widget shuffle, throw away the old widget/rulepart,
+ and create another */
+ if (data->partwidget)
+ gtk_container_remove (GTK_CONTAINER (data->container), data->partwidget);
+
+ newpart = e_filter_part_clone (part);
+ e_filter_part_copy_values (newpart, data->part);
+ e_filter_rule_replace_part (data->rule, data->part, newpart);
+ g_object_unref (data->part);
+ data->part = newpart;
+ data->partwidget = e_filter_part_get_widget (newpart);
+ if (data->partwidget)
+ gtk_box_pack_start (GTK_BOX (data->container), data->partwidget, TRUE, TRUE, 0);
+}
+
+static GtkWidget *
+get_rule_part_widget (ERuleContext *context,
+ EFilterPart *newpart,
+ EFilterRule *rule)
+{
+ EFilterPart *part = NULL;
+ GtkWidget *combobox;
+ GtkWidget *hbox;
+ GtkWidget *p;
+ gint index = 0, current = 0;
+ FilterPartData *data;
+
+ data = g_malloc0 (sizeof (*data));
+ data->rule = rule;
+ data->context = context;
+ data->part = newpart;
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ /* only set to automatically clean up the memory */
+ g_object_set_data_full ((GObject *) hbox, "data", data, g_free);
+
+ p = e_filter_part_get_widget (newpart);
+
+ data->partwidget = p;
+ data->container = hbox;
+
+ combobox = gtk_combo_box_new_text ();
+
+ /* sigh, this is a little ugly */
+ while ((part = e_rule_context_next_part (context, part))) {
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combobox), _(part->title));
+
+ if (!strcmp (newpart->title, part->title))
+ current = index;
+
+ index++;
+ }
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), current);
+ g_signal_connect (combobox, "changed", G_CALLBACK (part_combobox_changed), data);
+ gtk_widget_show (combobox);
+
+ gtk_box_pack_start (GTK_BOX (hbox), combobox, FALSE, FALSE, 0);
+ if (p)
+ gtk_box_pack_start (GTK_BOX (hbox), p, TRUE, TRUE, 0);
+
+ gtk_widget_show_all (hbox);
+
+ return hbox;
+}
+
+static void
+less_parts (GtkWidget *button,
+ FilterRuleData *data)
+{
+ EFilterPart *part;
+ GtkWidget *rule;
+ FilterPartData *part_data;
+
+ if (g_list_length (data->rule->parts) < 1)
+ return;
+
+ rule = g_object_get_data ((GObject *) button, "rule");
+ part_data = g_object_get_data ((GObject *) rule, "data");
+
+ g_return_if_fail (part_data != NULL);
+
+ part = part_data->part;
+
+ /* remove the part from the list */
+ e_filter_rule_remove_part (data->rule, part);
+ g_object_unref (part);
+
+ /* and from the display */
+ gtk_container_remove (GTK_CONTAINER (data->parts), rule);
+ gtk_container_remove (GTK_CONTAINER (data->parts), button);
+}
+
+static void
+attach_rule (GtkWidget *rule,
+ FilterRuleData *data,
+ EFilterPart *part, gint row)
+{
+ GtkWidget *remove;
+
+ gtk_table_attach (GTK_TABLE (data->parts), rule, 0, 1, row, row + 1,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+
+ remove = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
+ g_object_set_data ((GObject *) remove, "rule", rule);
+ g_signal_connect (remove, "clicked", G_CALLBACK (less_parts), data);
+ gtk_table_attach (GTK_TABLE (data->parts), remove, 1, 2, row, row + 1,
+ 0, 0, 0, 0);
+
+ gtk_widget_show (remove);
+}
+
+static void
+do_grab_focus_cb (GtkWidget *widget,
+ gpointer data)
+{
+ gboolean *done = (gboolean *) data;
+
+ if (*done)
+ return;
+
+ if (widget && GTK_WIDGET_CAN_FOCUS (widget)) {
+ *done = TRUE;
+ gtk_widget_grab_focus (widget);
+ }
+}
+
+static void
+more_parts (GtkWidget *button,
+ FilterRuleData *data)
+{
+ EFilterPart *new;
+
+ /* first make sure that the last part is ok */
+ if (data->rule->parts) {
+ EFilterPart *part;
+ GList *l;
+
+ l = g_list_last (data->rule->parts);
+ part = l->data;
+ if (!e_filter_part_validate (part, GTK_WINDOW (gtk_widget_get_toplevel (button))))
+ return;
+ }
+
+ /* create a new rule entry, use the first type of rule */
+ new = e_rule_context_next_part (data->context, NULL);
+ if (new) {
+ GtkWidget *w;
+ gint rows;
+
+ new = e_filter_part_clone (new);
+ e_filter_rule_add_part (data->rule, new);
+ w = get_rule_part_widget (data->context, new, data->rule);
+
+ rows = GTK_TABLE (data->parts)->nrows;
+ gtk_table_resize (GTK_TABLE (data->parts), rows + 1, 2);
+ attach_rule (w, data, new, rows);
+
+ if (GTK_IS_CONTAINER (w)) {
+ gboolean done = FALSE;
+
+ gtk_container_foreach (GTK_CONTAINER (w), do_grab_focus_cb, &done);
+ } else
+ gtk_widget_grab_focus (w);
+
+ /* also scroll down to see new part */
+ w = (GtkWidget*) g_object_get_data (G_OBJECT (button), "scrolled-window");
+ if (w) {
+ GtkAdjustment *adjustment;
+
+ adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (w));
+ if (adjustment) {
+ gdouble upper;
+
+ upper = gtk_adjustment_get_upper (adjustment);
+ gtk_adjustment_set_value (adjustment, upper);
+ }
+
+ }
+ }
+}
+
+static void
+name_changed (GtkEntry *entry,
+ EFilterRule *rule)
+{
+ g_free (rule->name);
+ rule->name = g_strdup (gtk_entry_get_text (entry));
+}
+
+GtkWidget *
+e_filter_rule_get_widget (EFilterRule *rule,
+ ERuleContext *context)
+{
+ EFilterRuleClass *class;
+
+ g_return_val_if_fail (E_IS_FILTER_RULE (rule), NULL);
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), NULL);
+
+ class = E_FILTER_RULE_GET_CLASS (rule);
+ g_return_val_if_fail (class->get_widget != NULL, NULL);
+
+ return class->get_widget (rule, context);
+}
+
+static void
+filter_rule_load_set (xmlNodePtr node,
+ EFilterRule *rule,
+ ERuleContext *context)
+{
+ xmlNodePtr work;
+ gchar *rulename;
+ EFilterPart *part;
+
+ work = node->children;
+ while (work) {
+ if (!strcmp ((gchar *)work->name, "part")) {
+ rulename = (gchar *)xmlGetProp (work, (xmlChar *)"name");
+ part = e_rule_context_find_part (context, rulename);
+ if (part) {
+ part = e_filter_part_clone (part);
+ e_filter_part_xml_decode (part, work);
+ e_filter_rule_add_part (rule, part);
+ } else {
+ g_warning ("cannot find rule part '%s'\n", rulename);
+ }
+ xmlFree (rulename);
+ } else if (work->type == XML_ELEMENT_NODE) {
+ g_warning ("Unknown xml node in part: %s", work->name);
+ }
+ work = work->next;
+ }
+}
+
+static void
+filter_rule_finalize (GObject *object)
+{
+ EFilterRule *rule = E_FILTER_RULE (object);
+
+ g_free (rule->name);
+ g_free (rule->source);
+
+ g_list_foreach (rule->parts, (GFunc) g_object_unref, NULL);
+ g_list_free (rule->parts);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gint
+filter_rule_validate (EFilterRule *rule,
+ GtkWindow *error_parent)
+{
+ gint valid = TRUE;
+ GList *parts;
+
+ if (!rule->name || !*rule->name) {
+ e_error_run (error_parent, "filter:no-name", NULL);
+
+ return FALSE;
+ }
+
+ /* validate rule parts */
+ parts = rule->parts;
+ valid = parts != NULL;
+ while (parts && valid) {
+ valid = e_filter_part_validate ((EFilterPart *) parts->data, error_parent);
+ parts = parts->next;
+ }
+
+ return valid;
+}
+
+static gint
+filter_rule_eq (EFilterRule *rule_a,
+ EFilterRule *rule_b)
+{
+ GList *link_a;
+ GList *link_b;
+
+ if (rule_a->enabled != rule_b->enabled)
+ return FALSE;
+
+ if (rule_a->grouping != rule_b->grouping)
+ return FALSE;
+
+ if (rule_a->threading != rule_b->threading)
+ return FALSE;
+
+ if (g_strcmp0 (rule_a->name, rule_b->name) != 0)
+ return FALSE;
+
+ if (g_strcmp0 (rule_a->source, rule_b->source) != 0)
+ return FALSE;
+
+ link_a = rule_a->parts;
+ link_b = rule_b->parts;
+
+ while (link_a != NULL && link_b != NULL) {
+ EFilterPart *part_a = link_a->data;
+ EFilterPart *part_b = link_b->data;
+
+ if (!e_filter_part_eq (part_a, part_b))
+ return FALSE;
+
+ link_a = g_list_next (link_a);
+ link_b = g_list_next (link_b);
+ }
+
+ if (link_a != NULL || link_b != NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static xmlNodePtr
+filter_rule_xml_encode (EFilterRule *rule)
+{
+ xmlNodePtr node, set, work;
+ GList *l;
+
+ node = xmlNewNode (NULL, (xmlChar *)"rule");
+
+ xmlSetProp (node, (xmlChar *)"enabled", (xmlChar *)(rule->enabled ? "true" : "false"));
+
+ switch (rule->grouping) {
+ case E_FILTER_GROUP_ALL:
+ xmlSetProp (node, (xmlChar *)"grouping", (xmlChar *)"all");
+ break;
+ case E_FILTER_GROUP_ANY:
+ xmlSetProp (node, (xmlChar *)"grouping", (xmlChar *)"any");
+ break;
+ }
+
+ switch (rule->threading) {
+ case E_FILTER_THREAD_NONE:
+ break;
+ case E_FILTER_THREAD_ALL:
+ xmlSetProp (node, (xmlChar *)"threading", (xmlChar *)"all");
+ break;
+ case E_FILTER_THREAD_REPLIES:
+ xmlSetProp (node, (xmlChar *)"threading", (xmlChar *)"replies");
+ break;
+ case E_FILTER_THREAD_REPLIES_PARENTS:
+ xmlSetProp (node, (xmlChar *)"threading", (xmlChar *)"replies_parents");
+ break;
+ case E_FILTER_THREAD_SINGLE:
+ xmlSetProp (node, (xmlChar *)"threading", (xmlChar *)"single");
+ break;
+ }
+
+ if (rule->source) {
+ xmlSetProp (node, (xmlChar *)"source", (xmlChar *)rule->source);
+ } else {
+ /* set to the default filter type */
+ xmlSetProp (node, (xmlChar *)"source", (xmlChar *)"incoming");
+ }
+
+ if (rule->name) {
+ gchar *escaped = g_markup_escape_text (rule->name, -1);
+
+ work = xmlNewNode (NULL, (xmlChar *)"title");
+ xmlNodeSetContent (work, (xmlChar *)escaped);
+ xmlAddChild (node, work);
+
+ g_free (escaped);
+ }
+
+ set = xmlNewNode (NULL, (xmlChar *)"partset");
+ xmlAddChild (node, set);
+ l = rule->parts;
+ while (l) {
+ work = e_filter_part_xml_encode ((EFilterPart *) l->data);
+ xmlAddChild (set, work);
+ l = l->next;
+ }
+
+ return node;
+}
+
+static gint
+filter_rule_xml_decode (EFilterRule *rule,
+ xmlNodePtr node,
+ ERuleContext *context)
+{
+ xmlNodePtr work;
+ gchar *grouping;
+ gchar *source;
+
+ g_free (rule->name);
+ rule->name = NULL;
+
+ grouping = (gchar *)xmlGetProp (node, (xmlChar *)"enabled");
+ if (!grouping)
+ rule->enabled = TRUE;
+ else {
+ rule->enabled = strcmp (grouping, "false") != 0;
+ xmlFree (grouping);
+ }
+
+ grouping = (gchar *)xmlGetProp (node, (xmlChar *)"grouping");
+ if (!strcmp (grouping, "any"))
+ rule->grouping = E_FILTER_GROUP_ANY;
+ else
+ rule->grouping = E_FILTER_GROUP_ALL;
+ xmlFree (grouping);
+
+ rule->threading = E_FILTER_THREAD_NONE;
+ if (context->flags & E_RULE_CONTEXT_THREADING
+ && (grouping = (gchar *)xmlGetProp (node, (xmlChar *)"threading"))) {
+ if (!strcmp (grouping, "all"))
+ rule->threading = E_FILTER_THREAD_ALL;
+ else if (!strcmp (grouping, "replies"))
+ rule->threading = E_FILTER_THREAD_REPLIES;
+ else if (!strcmp (grouping, "replies_parents"))
+ rule->threading = E_FILTER_THREAD_REPLIES_PARENTS;
+ else if (!strcmp (grouping, "single"))
+ rule->threading = E_FILTER_THREAD_SINGLE;
+ xmlFree (grouping);
+ }
+
+ g_free (rule->source);
+ source = (gchar *)xmlGetProp (node, (xmlChar *)"source");
+ if (source) {
+ rule->source = g_strdup (source);
+ xmlFree (source);
+ } else {
+ /* default filter type */
+ rule->source = g_strdup ("incoming");
+ }
+
+ work = node->children;
+ while (work) {
+ if (!strcmp ((gchar *)work->name, "partset")) {
+ filter_rule_load_set (work, rule, context);
+ } else if (!strcmp ((gchar *)work->name, "title") || !strcmp ((gchar *)work->name, "_title")) {
+ if (!rule->name) {
+ gchar *str, *decstr = NULL;
+
+ str = (gchar *)xmlNodeGetContent (work);
+ if (str) {
+ decstr = g_strdup (_(str));
+ xmlFree (str);
+ }
+ rule->name = decstr;
+ }
+ }
+ work = work->next;
+ }
+
+ return 0;
+}
+
+static void
+filter_rule_build_code (EFilterRule *rule,
+ GString *out)
+{
+ switch (rule->threading) {
+ case E_FILTER_THREAD_NONE:
+ break;
+ case E_FILTER_THREAD_ALL:
+ g_string_append (out, " (match-threads \"all\" ");
+ break;
+ case E_FILTER_THREAD_REPLIES:
+ g_string_append (out, " (match-threads \"replies\" ");
+ break;
+ case E_FILTER_THREAD_REPLIES_PARENTS:
+ g_string_append (out, " (match-threads \"replies_parents\" ");
+ break;
+ case E_FILTER_THREAD_SINGLE:
+ g_string_append (out, " (match-threads \"single\" ");
+ break;
+ }
+
+ switch (rule->grouping) {
+ case E_FILTER_GROUP_ALL:
+ g_string_append (out, " (and\n ");
+ break;
+ case E_FILTER_GROUP_ANY:
+ g_string_append (out, " (or\n ");
+ break;
+ default:
+ g_warning ("Invalid grouping");
+ }
+
+ e_filter_part_build_code_list (rule->parts, out);
+ g_string_append (out, ")\n");
+
+ if (rule->threading != E_FILTER_THREAD_NONE)
+ g_string_append (out, ")\n");
+}
+
+static void
+filter_rule_copy (EFilterRule *dest, EFilterRule *src)
+{
+ GList *node;
+
+ dest->enabled = src->enabled;
+
+ g_free (dest->name);
+ dest->name = g_strdup (src->name);
+
+ g_free (dest->source);
+ 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);
+ dest->parts = NULL;
+ }
+
+ node = src->parts;
+ while (node) {
+ EFilterPart *part;
+
+ part = e_filter_part_clone (node->data);
+ dest->parts = g_list_append (dest->parts, part);
+ node = node->next;
+ }
+}
+
+static GtkWidget *
+filter_rule_get_widget (EFilterRule *rule,
+ ERuleContext *context)
+{
+ GtkWidget *hbox, *vbox, *parts, *inruleame;
+ GtkWidget *add, *label, *name, *w;
+ GtkWidget *combobox;
+ GtkWidget *scrolledwindow;
+ GtkObject *hadj, *vadj;
+ GList *l;
+ gchar *text;
+ EFilterPart *part;
+ FilterRuleData *data;
+ gint rows, i;
+
+ /* this stuff should probably be a table, but the
+ rule parts need to be a vbox */
+ vbox = gtk_vbox_new (FALSE, 6);
+
+ label = gtk_label_new_with_mnemonic (_("R_ule name:"));
+ name = gtk_entry_new ();
+ gtk_label_set_mnemonic_widget ((GtkLabel *)label, name);
+
+ if (!rule->name) {
+ rule->name = g_strdup (_("Untitled"));
+ gtk_entry_set_text (GTK_ENTRY (name), rule->name);
+ /* FIXME: do we want the following code in the future? */
+ /*gtk_editable_select_region (GTK_EDITABLE (name), 0, -1);*/
+ } else {
+ gtk_entry_set_text (GTK_ENTRY (name), rule->name);
+ }
+
+ g_signal_connect (
+ name, "realize",
+ G_CALLBACK (gtk_widget_grab_focus), name);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), name, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ g_signal_connect (name, "changed", G_CALLBACK (name_changed), rule);
+ gtk_widget_show (label);
+ gtk_widget_show (hbox);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ gtk_widget_show (hbox);
+
+ text = g_strdup_printf ("<b>%s</b>", _("Find items that meet the following conditions"));
+ label = gtk_label_new (text);
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+ g_free (text);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
+ gtk_widget_show (hbox);
+
+ label = gtk_label_new ("");
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ inruleame = gtk_vbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), inruleame, TRUE, TRUE, 0);
+
+ /* this is the parts table, it should probably be inside a scrolling list */
+ rows = g_list_length (rule->parts);
+ parts = gtk_table_new (rows, 2, FALSE);
+
+ /* data for the parts part of the display */
+ data = g_malloc0 (sizeof (*data));
+ data->context = context;
+ data->rule = rule;
+ data->parts = parts;
+
+ /* only set to automatically clean up the memory */
+ g_object_set_data_full ((GObject *) vbox, "data", data, g_free);
+
+ hbox = gtk_hbox_new (FALSE, 3);
+
+ add = gtk_button_new_with_mnemonic (_("A_dd Condition"));
+ gtk_button_set_image (GTK_BUTTON (add), gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (add, "clicked", G_CALLBACK (more_parts), data);
+ gtk_box_pack_start (GTK_BOX (hbox), add, FALSE, FALSE, 0);
+
+ if (context->flags & E_RULE_CONTEXT_GROUPING) {
+ const gchar *thread_types[] = { N_("If all conditions are met"), N_("If any conditions are met") };
+
+ label = gtk_label_new_with_mnemonic (_("_Find items:"));
+ combobox = gtk_combo_box_new_text ();
+
+ for (i=0;i<2;i++) {
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combobox), _(thread_types[i]));
+ }
+
+ gtk_label_set_mnemonic_widget ((GtkLabel *)label, combobox);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), rule->grouping);
+ gtk_widget_show (combobox);
+
+ gtk_box_pack_end (GTK_BOX (hbox), combobox, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+ g_signal_connect (
+ combobox, "changed",
+ G_CALLBACK (filter_rule_grouping_changed_cb), rule);
+ }
+
+ if (context->flags & E_RULE_CONTEXT_THREADING) {
+ const gchar *thread_types[] = { N_("None"), N_("All related"), N_("Replies"), N_("Replies and parents"), N_("No reply or parent") };
+
+ label = gtk_label_new_with_mnemonic (_("I_nclude threads"));
+ combobox = gtk_combo_box_new_text ();
+
+ for (i=0;i<5;i++) {
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combobox), _(thread_types[i]));
+ }
+
+ gtk_label_set_mnemonic_widget ((GtkLabel *)label, combobox);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), rule->threading);
+ gtk_widget_show (combobox);
+
+ gtk_box_pack_end (GTK_BOX (hbox), combobox, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+ g_signal_connect (
+ combobox, "changed",
+ G_CALLBACK (filter_rule_threading_changed_cb), rule);
+ }
+
+ gtk_box_pack_start (GTK_BOX (inruleame), hbox, FALSE, FALSE, 3);
+
+ l = rule->parts;
+ i = 0;
+ while (l) {
+ part = l->data;
+ w = get_rule_part_widget (context, part, rule);
+ attach_rule (w, data, part, i++);
+ l = g_list_next (l);
+ }
+
+ hadj = gtk_adjustment_new (0.0, 0.0, 1.0, 1.0, 1.0, 1.0);
+ vadj = gtk_adjustment_new (0.0, 0.0, 1.0, 1.0, 1.0, 1.0);
+ scrolledwindow = gtk_scrolled_window_new (GTK_ADJUSTMENT (hadj), GTK_ADJUSTMENT (vadj));
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolledwindow), parts);
+
+ gtk_box_pack_start (GTK_BOX (inruleame), scrolledwindow, TRUE, TRUE, 3);
+
+ gtk_widget_show_all (vbox);
+
+ g_object_set_data (G_OBJECT (add), "scrolled-window", scrolledwindow);
+
+ return vbox;
+}
+
+static void
+filter_rule_class_init (EFilterRuleClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EFilterRulePrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = filter_rule_finalize;
+
+ class->validate = filter_rule_validate;
+ class->eq = filter_rule_eq;
+ class->xml_encode = filter_rule_xml_encode;
+ class->xml_decode = filter_rule_xml_decode;
+ class->build_code = filter_rule_build_code;
+ class->copy = filter_rule_copy;
+ class->get_widget = filter_rule_get_widget;
+
+ signals[CHANGED] = g_signal_new (
+ "changed",
+ E_TYPE_FILTER_RULE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EFilterRuleClass, changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+filter_rule_init (EFilterRule *rule)
+{
+ rule->priv = E_FILTER_RULE_GET_PRIVATE (rule);
+ rule->enabled = TRUE;
+}
+
+GType
+e_filter_rule_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFilterRuleClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) filter_rule_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFilterRule),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) filter_rule_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ G_TYPE_OBJECT, "EFilterRule", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * filter_rule_new:
+ *
+ * Create a new EFilterRule object.
+ *
+ * Return value: A new #EFilterRule object.
+ **/
+EFilterRule *
+e_filter_rule_new (void)
+{
+ return g_object_new (E_TYPE_FILTER_RULE, NULL);
+}
+
+EFilterRule *
+e_filter_rule_clone (EFilterRule *rule)
+{
+ EFilterRule *clone;
+
+ g_return_val_if_fail (E_IS_FILTER_RULE (rule), NULL);
+
+ clone = g_object_new (G_OBJECT_TYPE (rule), NULL);
+ e_filter_rule_copy (clone, rule);
+
+ return clone;
+}
+
+void
+e_filter_rule_set_name (EFilterRule *rule,
+ const gchar *name)
+{
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+
+ if (g_strcmp0 (rule->name, name) == 0)
+ return;
+
+ g_free (rule->name);
+ rule->name = g_strdup (name);
+
+ e_filter_rule_emit_changed (rule);
+}
+
+void
+e_filter_rule_set_source (EFilterRule *rule,
+ const gchar *source)
+{
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+
+ if (g_strcmp0 (rule->source, source) == 0)
+ return;
+
+ g_free (rule->source);
+ rule->source = g_strdup (source);
+
+ e_filter_rule_emit_changed (rule);
+}
+
+gint
+e_filter_rule_validate (EFilterRule *rule,
+ GtkWindow *error_parent)
+{
+ EFilterRuleClass *class;
+
+ g_return_val_if_fail (E_IS_FILTER_RULE (rule), FALSE);
+
+ class = E_FILTER_RULE_GET_CLASS (rule);
+ g_return_val_if_fail (class->validate != NULL, FALSE);
+
+ return class->validate (rule, error_parent);
+}
+
+gint
+e_filter_rule_eq (EFilterRule *rule_a,
+ EFilterRule *rule_b)
+{
+ EFilterRuleClass *class;
+
+ g_return_val_if_fail (E_IS_FILTER_RULE (rule_a), FALSE);
+ g_return_val_if_fail (E_IS_FILTER_RULE (rule_b), FALSE);
+
+ class = E_FILTER_RULE_GET_CLASS (rule_a);
+ g_return_val_if_fail (class->eq != NULL, FALSE);
+
+ if (G_OBJECT_TYPE (rule_a) != G_OBJECT_TYPE (rule_b))
+ return FALSE;
+
+ return class->eq (rule_a, rule_b);
+}
+
+xmlNodePtr
+e_filter_rule_xml_encode (EFilterRule *rule)
+{
+ EFilterRuleClass *class;
+
+ g_return_val_if_fail (E_IS_FILTER_RULE (rule), NULL);
+
+ class = E_FILTER_RULE_GET_CLASS (rule);
+ g_return_val_if_fail (class->xml_encode != NULL, NULL);
+
+ return class->xml_encode (rule);
+}
+
+gint
+e_filter_rule_xml_decode (EFilterRule *rule,
+ xmlNodePtr node,
+ ERuleContext *context)
+{
+ EFilterRuleClass *class;
+ gint result;
+
+ g_return_val_if_fail (E_IS_FILTER_RULE (rule), FALSE);
+ g_return_val_if_fail (node != NULL, FALSE);
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), FALSE);
+
+ class = E_FILTER_RULE_GET_CLASS (rule);
+ g_return_val_if_fail (class->xml_decode != NULL, FALSE);
+
+ rule->priv->frozen++;
+ result = class->xml_decode (rule, node, context);
+ rule->priv->frozen--;
+
+ e_filter_rule_emit_changed (rule);
+
+ return result;
+}
+
+void
+e_filter_rule_copy (EFilterRule *dst_rule,
+ EFilterRule *src_rule)
+{
+ EFilterRuleClass *class;
+
+ g_return_if_fail (E_IS_FILTER_RULE (dst_rule));
+ g_return_if_fail (E_IS_FILTER_RULE (src_rule));
+
+ class = E_FILTER_RULE_GET_CLASS (dst_rule);
+ g_return_if_fail (class->copy != NULL);
+
+ class->copy (dst_rule, src_rule);
+
+ e_filter_rule_emit_changed (dst_rule);
+}
+
+void
+e_filter_rule_add_part (EFilterRule *rule,
+ EFilterPart *part)
+{
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+ g_return_if_fail (E_IS_FILTER_PART (part));
+
+ rule->parts = g_list_append (rule->parts, part);
+
+ e_filter_rule_emit_changed (rule);
+}
+
+void
+e_filter_rule_remove_part (EFilterRule *rule,
+ EFilterPart *part)
+{
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+ g_return_if_fail (E_IS_FILTER_PART (part));
+
+ rule->parts = g_list_remove (rule->parts, part);
+
+ e_filter_rule_emit_changed (rule);
+}
+
+void
+e_filter_rule_replace_part (EFilterRule *rule,
+ EFilterPart *old_part,
+ EFilterPart *new_part)
+{
+ GList *link;
+
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+ g_return_if_fail (E_IS_FILTER_PART (old_part));
+ g_return_if_fail (E_IS_FILTER_PART (new_part));
+
+ link = g_list_find (rule->parts, old_part);
+ if (link != NULL)
+ link->data = new_part;
+ else
+ rule->parts = g_list_append (rule->parts, new_part);
+
+ e_filter_rule_emit_changed (rule);
+}
+
+void
+e_filter_rule_build_code (EFilterRule *rule,
+ GString *out)
+{
+ EFilterRuleClass *class;
+
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+ g_return_if_fail (out != NULL);
+
+ class = E_FILTER_RULE_GET_CLASS (rule);
+ g_return_if_fail (class->build_code != NULL);
+
+ class->build_code (rule, out);
+}
+
+void
+e_filter_rule_emit_changed (EFilterRule *rule)
+{
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+
+ if (rule->priv->frozen == 0)
+ g_signal_emit (rule, signals[CHANGED], 0);
+}
+
+EFilterRule *
+e_filter_rule_next_list (GList *list,
+ EFilterRule *last,
+ const gchar *source)
+{
+ GList *link = list;
+
+ if (last != NULL) {
+ link = g_list_find (link, last);
+ if (link == NULL)
+ link = list;
+ else
+ link = g_list_next (link);
+ }
+
+ if (source != NULL) {
+ while (link != NULL) {
+ EFilterRule *rule = link->data;
+
+ if (g_strcmp0 (rule->source, source) == 0)
+ break;
+
+ link = g_list_next (link);
+ }
+ }
+
+ return (link != NULL) ? link->data : NULL;
+}
+
+EFilterRule *
+e_filter_rule_find_list (GList * list,
+ const gchar *name,
+ const gchar *source)
+{
+ GList *link;
+
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ EFilterRule *rule = link->data;
+
+ if (strcmp (rule->name, name) == 0)
+ if (source == NULL || (rule->source != NULL && strcmp (rule->source, source) == 0))
+ return rule;
+ }
+
+ return NULL;
+}
+
+#ifdef FOR_TRANSLATIONS_ONLY
+
+static gchar *list[] = {
+ N_("Incoming"), N_("Outgoing")
+};
+#endif
diff --git a/filter/e-filter-rule.h b/filter/e-filter-rule.h
new file mode 100644
index 0000000000..c84cdefb0e
--- /dev/null
+++ b/filter/e-filter-rule.h
@@ -0,0 +1,161 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FILTER_RULE_H
+#define E_FILTER_RULE_H
+
+#include <glib-object.h>
+
+#include "e-filter-part.h"
+
+/* Standard GObject macros */
+#define E_TYPE_FILTER_RULE \
+ (e_filter_rule_get_type ())
+#define E_FILTER_RULE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FILTER_RULE, EFilterRule))
+#define E_FILTER_RULE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FILTER_RULE, EFilterRuleClass))
+#define E_IS_FILTER_RULE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FILTER_RULE))
+#define E_IS_FILTER_RULE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FILTER_RULE))
+#define E_FILTER_RULE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FILTER_RULE, EFilterRuleClass))
+
+G_BEGIN_DECLS
+
+struct _RuleContext;
+
+typedef struct _EFilterRule EFilterRule;
+typedef struct _EFilterRuleClass EFilterRuleClass;
+typedef struct _EFilterRulePrivate EFilterRulePrivate;
+
+enum _filter_grouping_t {
+ E_FILTER_GROUP_ALL, /* all rules must match */
+ E_FILTER_GROUP_ANY /* any rule must match */
+};
+
+/* threading, if the context supports it */
+enum _filter_threading_t {
+ E_FILTER_THREAD_NONE, /* don't add any thread matching */
+ E_FILTER_THREAD_ALL, /* add all possible threads */
+ E_FILTER_THREAD_REPLIES, /* add only replies */
+ E_FILTER_THREAD_REPLIES_PARENTS, /* replies plus parents */
+ E_FILTER_THREAD_SINGLE /* messages with no replies or parents */
+};
+
+#define E_FILTER_SOURCE_INCOMING "incoming" /* performed on incoming email */
+#define E_FILTER_SOURCE_DEMAND "demand" /* performed on the selected folder
+ * when the user asks for it */
+#define E_FILTER_SOURCE_OUTGOING "outgoing"/* performed on outgoing mail */
+#define E_FILTER_SOURCE_JUNKTEST "junktest"/* perform only junktest on incoming mail */
+
+struct _EFilterRule {
+ GObject parent_object;
+ EFilterRulePrivate *priv;
+
+ gchar *name;
+ gchar *source;
+
+ enum _filter_grouping_t grouping;
+ enum _filter_threading_t threading;
+
+ guint system:1; /* this is a system rule, cannot be edited/deleted */
+ GList *parts;
+
+ gboolean enabled;
+};
+
+struct _EFilterRuleClass {
+ GObjectClass parent_class;
+
+ /* virtual methods */
+ gint (*validate) (EFilterRule *rule,
+ GtkWindow *error_parent);
+ gint (*eq) (EFilterRule *rule_a,
+ EFilterRule *rule_b);
+
+ xmlNodePtr (*xml_encode) (EFilterRule *rule);
+ gint (*xml_decode) (EFilterRule *rule,
+ xmlNodePtr node,
+ struct _ERuleContext *context);
+
+ void (*build_code) (EFilterRule *rule,
+ GString *out);
+
+ void (*copy) (EFilterRule *dst_rule,
+ EFilterRule *src_rule);
+
+ GtkWidget * (*get_widget) (EFilterRule *rule,
+ struct _ERuleContext *context);
+
+ /* signals */
+ void (*changed) (EFilterRule *rule);
+};
+
+GType e_filter_rule_get_type (void);
+EFilterRule * e_filter_rule_new (void);
+EFilterRule * e_filter_rule_clone (EFilterRule *rule);
+void e_filter_rule_set_name (EFilterRule *rule,
+ const gchar *name);
+void e_filter_rule_set_source (EFilterRule *rule,
+ const gchar *source);
+gint e_filter_rule_validate (EFilterRule *rule,
+ GtkWindow *error_parent);
+gint e_filter_rule_eq (EFilterRule *rule_a,
+ EFilterRule *rule_b);
+xmlNodePtr e_filter_rule_xml_encode (EFilterRule *rule);
+gint e_filter_rule_xml_decode (EFilterRule *rule,
+ xmlNodePtr node,
+ struct _ERuleContext *context);
+void e_filter_rule_copy (EFilterRule *dst_rule,
+ EFilterRule *src_rule);
+void e_filter_rule_add_part (EFilterRule *rule,
+ EFilterPart *part);
+void e_filter_rule_remove_part (EFilterRule *rule,
+ EFilterPart *part);
+void e_filter_rule_replace_part (EFilterRule *rule,
+ EFilterPart *old_part,
+ EFilterPart *new_part);
+GtkWidget * e_filter_rule_get_widget (EFilterRule *rule,
+ struct _ERuleContext *context);
+void e_filter_rule_build_code (EFilterRule *rule,
+ GString *out);
+void e_filter_rule_emit_changed (EFilterRule *rule);
+
+/* static functions */
+EFilterRule * e_filter_rule_next_list (GList *list,
+ EFilterRule *last,
+ const gchar *source);
+EFilterRule * e_filter_rule_find_list (GList *list,
+ const gchar *name,
+ const gchar *source);
+
+G_END_DECLS
+
+#endif /* E_FILTER_RULE_H */
diff --git a/filter/e-rule-context.c b/filter/e-rule-context.c
new file mode 100644
index 0000000000..648011b8e5
--- /dev/null
+++ b/filter/e-rule-context.c
@@ -0,0 +1,988 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <gtk/gtk.h>
+
+#include <glib/gi18n.h>
+
+#include <libedataserver/e-xml-utils.h>
+
+#include "e-util/e-error.h"
+#include "e-util/e-xml-utils.h"
+
+#include "e-filter-code.h"
+#include "e-filter-color.h"
+#include "e-filter-datespec.h"
+#include "e-filter-file.h"
+#include "e-filter-input.h"
+#include "e-filter-int.h"
+#include "e-filter-option.h"
+#include "e-filter-rule.h"
+#include "e-rule-context.h"
+
+#define E_RULE_CONTEXT_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_RULE_CONTEXT, ERuleContextPrivate))
+
+struct _ERuleContextPrivate {
+ gint frozen;
+};
+
+enum {
+ RULE_ADDED,
+ RULE_REMOVED,
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+struct _revert_data {
+ GHashTable *rules;
+ gint rank;
+};
+
+static void
+rule_context_set_error (ERuleContext *context,
+ gchar *error)
+{
+ g_free (context->error);
+ context->error = error;
+}
+
+static void
+new_rule_response (GtkWidget *dialog,
+ gint button,
+ ERuleContext *context)
+{
+ if (button == GTK_RESPONSE_OK) {
+ EFilterRule *rule = g_object_get_data ((GObject *) dialog, "rule");
+ gchar *user = g_object_get_data ((GObject *) dialog, "path");
+
+ if (!e_filter_rule_validate (rule, GTK_WINDOW (dialog))) {
+ /* no need to popup a dialog because the validate code does that. */
+ return;
+ }
+
+ if (e_rule_context_find_rule (context, rule->name, rule->source)) {
+ e_error_run ((GtkWindow *)dialog, "filter:bad-name-notunique", rule->name, NULL);
+
+ return;
+ }
+
+ g_object_ref (rule);
+ e_rule_context_add_rule (context, rule);
+ if (user)
+ e_rule_context_save (context, user);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+revert_rule_remove (gpointer key,
+ EFilterRule *rule,
+ ERuleContext *context)
+{
+ e_rule_context_remove_rule (context, rule);
+ g_object_unref (rule);
+}
+
+static void
+revert_source_remove (gpointer key,
+ struct _revert_data *rest_data,
+ ERuleContext *context)
+{
+ g_hash_table_foreach (
+ rest_data->rules, (GHFunc) revert_rule_remove, context);
+ g_hash_table_destroy (rest_data->rules);
+ g_free (rest_data);
+}
+
+static guint
+source_hashf (const gchar *a)
+{
+ return (a != NULL) ? g_str_hash (a) : 0;
+}
+
+static gint
+source_eqf (const gchar *a,
+ const gchar *b)
+{
+ return (g_strcmp0 (a, b) == 0);
+}
+
+static void
+free_part_set (struct _part_set_map *map)
+{
+ g_free (map->name);
+ g_free (map);
+}
+
+static void
+free_rule_set (struct _rule_set_map *map)
+{
+ g_free (map->name);
+ g_free (map);
+}
+
+static void
+rule_context_finalize (GObject *obj)
+{
+ ERuleContext *context =(ERuleContext *) obj;
+
+ g_list_foreach (context->rule_set_list, (GFunc)free_rule_set, NULL);
+ g_list_free (context->rule_set_list);
+ g_hash_table_destroy (context->rule_set_map);
+
+ g_list_foreach (context->part_set_list, (GFunc)free_part_set, NULL);
+ g_list_free (context->part_set_list);
+ g_hash_table_destroy (context->part_set_map);
+
+ g_free (context->error);
+
+ g_list_foreach (context->parts, (GFunc)g_object_unref, NULL);
+ g_list_free (context->parts);
+
+ g_list_foreach (context->rules, (GFunc)g_object_unref, NULL);
+ g_list_free (context->rules);
+
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+static gint
+rule_context_load (ERuleContext *context,
+ const gchar *system,
+ const gchar *user)
+{
+ xmlNodePtr set, rule, root;
+ xmlDocPtr systemdoc, userdoc;
+ struct _part_set_map *part_map;
+ struct _rule_set_map *rule_map;
+
+ rule_context_set_error (context, NULL);
+
+ systemdoc = e_xml_parse_file (system);
+ if (systemdoc == NULL) {
+ rule_context_set_error (context, g_strdup_printf ("Unable to load system rules '%s': %s",
+ system, g_strerror (errno)));
+ return -1;
+ }
+
+ root = xmlDocGetRootElement (systemdoc);
+ if (root == NULL || strcmp ((gchar *)root->name, "filterdescription")) {
+ rule_context_set_error (context, g_strdup_printf ("Unable to load system rules '%s': Invalid format", system));
+ xmlFreeDoc (systemdoc);
+ return -1;
+ }
+ /* doesn't matter if this doens't exist */
+ userdoc = NULL;
+ if (g_file_test (user, G_FILE_TEST_IS_REGULAR))
+ userdoc = e_xml_parse_file (user);
+
+ /* now parse structure */
+ /* get rule parts */
+ set = root->children;
+ while (set) {
+ part_map = g_hash_table_lookup (context->part_set_map, set->name);
+ if (part_map) {
+ rule = set->children;
+ while (rule) {
+ if (!strcmp ((gchar *)rule->name, "part")) {
+ EFilterPart *part = E_FILTER_PART (g_object_new (part_map->type, NULL, NULL));
+
+ if (e_filter_part_xml_create (part, rule, context) == 0) {
+ part_map->append (context, part);
+ } else {
+ g_object_unref (part);
+ g_warning ("Cannot load filter part");
+ }
+ }
+ rule = rule->next;
+ }
+ } else if ((rule_map = g_hash_table_lookup (context->rule_set_map, set->name))) {
+ rule = set->children;
+ while (rule) {
+ if (!strcmp ((gchar *)rule->name, "rule")) {
+ EFilterRule *part = E_FILTER_RULE (g_object_new (rule_map->type, NULL, NULL));
+
+ if (e_filter_rule_xml_decode (part, rule, context) == 0) {
+ part->system = TRUE;
+ rule_map->append (context, part);
+ } else {
+ g_object_unref (part);
+ g_warning ("Cannot load filter part");
+ }
+ }
+ rule = rule->next;
+ }
+ }
+ set = set->next;
+ }
+
+ /* now load actual rules */
+ if (userdoc) {
+ root = xmlDocGetRootElement (userdoc);
+ set = root?root->children:NULL;
+ while (set) {
+ rule_map = g_hash_table_lookup (context->rule_set_map, set->name);
+ if (rule_map) {
+ rule = set->children;
+ while (rule) {
+ if (!strcmp ((gchar *)rule->name, "rule")) {
+ EFilterRule *part = E_FILTER_RULE (g_object_new (rule_map->type, NULL, NULL));
+
+ if (e_filter_rule_xml_decode (part, rule, context) == 0) {
+ rule_map->append (context, part);
+ } else {
+ g_object_unref (part);
+ g_warning ("Cannot load filter part");
+ }
+ }
+ rule = rule->next;
+ }
+ }
+ set = set->next;
+ }
+ }
+
+ xmlFreeDoc (userdoc);
+ xmlFreeDoc (systemdoc);
+
+ return 0;
+}
+
+static gint
+rule_context_save (ERuleContext *context,
+ const gchar *user)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root, rules, work;
+ GList *l;
+ EFilterRule *rule;
+ struct _rule_set_map *map;
+ gint ret;
+
+ doc = xmlNewDoc ((xmlChar *)"1.0");
+ /* FIXME: set character encoding to UTF-8? */
+ root = xmlNewDocNode (doc, NULL, (xmlChar *)"filteroptions", NULL);
+ xmlDocSetRootElement (doc, root);
+ l = context->rule_set_list;
+ while (l) {
+ map = l->data;
+ rules = xmlNewDocNode (doc, NULL, (xmlChar *)map->name, NULL);
+ xmlAddChild (root, rules);
+ rule = NULL;
+ while ((rule = map->next (context, rule, NULL))) {
+ if (!rule->system) {
+ work = e_filter_rule_xml_encode (rule);
+ xmlAddChild (rules, work);
+ }
+ }
+ l = g_list_next (l);
+ }
+
+ ret = e_xml_save_file (user, doc);
+
+ xmlFreeDoc (doc);
+
+ return ret;
+}
+
+static gint
+rule_context_revert (ERuleContext *context,
+ const gchar *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;
+ EFilterRule *frule;
+
+ rule_context_set_error (context, NULL);
+
+ userdoc = e_xml_parse_file (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 = e_rule_context_next_rule (context, 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 = xmlDocGetRootElement (userdoc);
+ set = set?set->children:NULL;
+ while (set) {
+ rule_map = g_hash_table_lookup (context->rule_set_map, set->name);
+ if (rule_map) {
+ rule = set->children;
+ while (rule) {
+ if (!strcmp ((gchar *)rule->name, "rule")) {
+ EFilterRule *part = E_FILTER_RULE (g_object_new (rule_map->type, NULL, NULL));
+
+ if (e_filter_rule_xml_decode (part, rule, context) == 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 (context->priv->frozen == 0 && !e_filter_rule_eq (frule, part))
+ e_filter_rule_copy (frule, part);
+
+ g_object_unref (part);
+ e_rule_context_rank_rule (context, frule, frule->source, rest_data->rank);
+ g_hash_table_remove (rest_data->rules, frule->name);
+ } else {
+ e_rule_context_add_rule (context, part);
+ e_rule_context_rank_rule (context, part, part->source, rest_data->rank);
+ }
+ rest_data->rank++;
+ } else {
+ g_object_unref (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, context);
+ g_hash_table_destroy (source_hash);
+
+ return 0;
+}
+
+static EFilterElement *
+rule_context_new_element (ERuleContext *context,
+ const gchar *type)
+{
+ if (!strcmp (type, "string")) {
+ return (EFilterElement *) e_filter_input_new ();
+ } else if (!strcmp (type, "address")) {
+ /* FIXME: temporary ... need real address type */
+ return (EFilterElement *) e_filter_input_new_type_name (type);
+ } else if (!strcmp (type, "code")) {
+ return (EFilterElement *) e_filter_code_new (FALSE);
+ } else if (!strcmp (type, "rawcode")) {
+ return (EFilterElement *) e_filter_code_new (TRUE);
+ } else if (!strcmp (type, "colour")) {
+ return (EFilterElement *) e_filter_color_new ();
+ } else if (!strcmp (type, "optionlist")) {
+ return (EFilterElement *) e_filter_option_new ();
+ } else if (!strcmp (type, "datespec")) {
+ return (EFilterElement *) e_filter_datespec_new ();
+ } else if (!strcmp (type, "command")) {
+ return (EFilterElement *) e_filter_file_new_type_name (type);
+ } else if (!strcmp (type, "file")) {
+ return (EFilterElement *) e_filter_file_new_type_name (type);
+ } else if (!strcmp (type, "integer")) {
+ return (EFilterElement *) e_filter_int_new ();
+ } else if (!strcmp (type, "regex")) {
+ return (EFilterElement *) e_filter_input_new_type_name (type);
+ }else if (!strcmp (type, "completedpercent")) {
+ return (EFilterElement *) e_filter_int_new_type ("completedpercent", 0,100);
+
+ } else {
+ g_warning ("Unknown filter type '%s'", type);
+ return NULL;
+ }
+}
+
+static void
+rule_context_class_init (ERuleContextClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (ERuleContextPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = rule_context_finalize;
+
+ class->load = rule_context_load;
+ class->save = rule_context_save;
+ class->revert = rule_context_revert;
+ class->new_element = rule_context_new_element;
+
+ signals[RULE_ADDED] = g_signal_new (
+ "rule-added",
+ E_TYPE_RULE_CONTEXT,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ERuleContextClass, rule_added),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+
+ signals[RULE_REMOVED] = g_signal_new (
+ "rule-removed",
+ E_TYPE_RULE_CONTEXT,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ERuleContextClass, rule_removed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+
+ signals[CHANGED] = g_signal_new (
+ "changed",
+ E_TYPE_RULE_CONTEXT,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ERuleContextClass, changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+rule_context_init (ERuleContext *context)
+{
+ context->priv = E_RULE_CONTEXT_GET_PRIVATE (context);
+
+ context->part_set_map = g_hash_table_new (g_str_hash, g_str_equal);
+ context->rule_set_map = g_hash_table_new (g_str_hash, g_str_equal);
+
+ context->flags = E_RULE_CONTEXT_GROUPING;
+}
+
+GType
+e_rule_context_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (ERuleContextClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) rule_context_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (ERuleContext),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) rule_context_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ G_TYPE_OBJECT, "ERuleContext", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * e_rule_context_new:
+ *
+ * Create a new ERuleContext object.
+ *
+ * Return value: A new #ERuleContext object.
+ **/
+ERuleContext *
+e_rule_context_new (void)
+{
+ return g_object_new (E_TYPE_RULE_CONTEXT, NULL);
+}
+
+void
+e_rule_context_add_part_set (ERuleContext *context,
+ const gchar *setname,
+ GType part_type,
+ ERuleContextPartFunc append,
+ ERuleContextNextPartFunc next)
+{
+ struct _part_set_map *map;
+
+ g_return_if_fail (E_IS_RULE_CONTEXT (context));
+ g_return_if_fail (setname != NULL);
+ g_return_if_fail (append != NULL);
+ g_return_if_fail (next != NULL);
+
+ g_return_if_fail (g_hash_table_lookup (context->part_set_map, setname) == NULL);
+
+ map = g_malloc0 (sizeof (*map));
+ map->type = part_type;
+ map->append = append;
+ map->next = next;
+ map->name = g_strdup (setname);
+ g_hash_table_insert (context->part_set_map, map->name, map);
+ context->part_set_list = g_list_append (context->part_set_list, map);
+}
+
+void
+e_rule_context_add_rule_set (ERuleContext *context,
+ const gchar *setname,
+ GType rule_type,
+ ERuleContextRuleFunc append,
+ ERuleContextNextRuleFunc next)
+{
+ struct _rule_set_map *map;
+
+ g_return_if_fail (E_IS_RULE_CONTEXT (context));
+ g_return_if_fail (setname != NULL);
+ g_return_if_fail (append != NULL);
+ g_return_if_fail (next != NULL);
+
+ g_return_if_fail (g_hash_table_lookup (context->rule_set_map, setname) == NULL);
+
+ map = g_malloc0 (sizeof (*map));
+ map->type = rule_type;
+ map->append = append;
+ map->next = next;
+ map->name = g_strdup (setname);
+ g_hash_table_insert (context->rule_set_map, map->name, map);
+ context->rule_set_list = g_list_append (context->rule_set_list, map);
+}
+
+/**
+ * e_rule_context_load:
+ * @f:
+ * @system:
+ * @user:
+ *
+ * Load a rule context from a system and user description file.
+ *
+ * Return value:
+ **/
+gint
+e_rule_context_load (ERuleContext *context,
+ const gchar *system,
+ const gchar *user)
+{
+ ERuleContextClass *class;
+ gint result;
+
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), -1);
+ g_return_val_if_fail (system != NULL, -1);
+ g_return_val_if_fail (user != NULL, -1);
+
+ class = E_RULE_CONTEXT_GET_CLASS (context);
+ g_return_val_if_fail (class->load != NULL, -1);
+
+ context->priv->frozen++;
+ result = class->load (context, system, user);
+ context->priv->frozen--;
+
+ return result;
+}
+
+/**
+ * e_rule_context_save:
+ * @f:
+ * @user:
+ *
+ * Save a rule context to disk.
+ *
+ * Return value:
+ **/
+gint
+e_rule_context_save (ERuleContext *context,
+ const gchar *user)
+{
+ ERuleContextClass *class;
+
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), -1);
+ g_return_val_if_fail (user != NULL, -1);
+
+ class = E_RULE_CONTEXT_GET_CLASS (context);
+ g_return_val_if_fail (class->save != NULL, -1);
+
+ return class->save (context, user);
+}
+
+/**
+ * e_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:
+ **/
+gint
+e_rule_context_revert (ERuleContext *context,
+ const gchar *user)
+{
+ ERuleContextClass *class;
+
+ g_return_val_if_fail (E_RULE_CONTEXT (context), 0);
+ g_return_val_if_fail (user != NULL, 0);
+
+ class = E_RULE_CONTEXT_GET_CLASS (context);
+ g_return_val_if_fail (class->revert != NULL, 0);
+
+ return class->revert (context, user);
+}
+
+EFilterPart *
+e_rule_context_find_part (ERuleContext *context,
+ const gchar *name)
+{
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ return e_filter_part_find_list (context->parts, name);
+}
+
+EFilterPart *
+e_rule_context_create_part (ERuleContext *context,
+ const gchar *name)
+{
+ EFilterPart *part;
+
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ part = e_rule_context_find_part (context, name);
+
+ if (part == NULL)
+ return NULL;
+
+ return e_filter_part_clone (part);
+}
+
+EFilterPart *
+e_rule_context_next_part (ERuleContext *context,
+ EFilterPart *last)
+{
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), NULL);
+
+ return e_filter_part_next_list (context->parts, last);
+}
+
+EFilterRule *
+e_rule_context_next_rule (ERuleContext *context,
+ EFilterRule *last,
+ const gchar *source)
+{
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), NULL);
+
+ return e_filter_rule_next_list (context->rules, last, source);
+}
+
+EFilterRule *
+e_rule_context_find_rule (ERuleContext *context,
+ const gchar *name,
+ const gchar *source)
+{
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ return e_filter_rule_find_list (context->rules, name, source);
+}
+
+void
+e_rule_context_add_part (ERuleContext *context,
+ EFilterPart *part)
+{
+ g_return_if_fail (E_IS_RULE_CONTEXT (context));
+ g_return_if_fail (E_IS_FILTER_PART (part));
+
+ context->parts = g_list_append (context->parts, part);
+}
+
+void
+e_rule_context_add_rule (ERuleContext *context,
+ EFilterRule *rule)
+{
+ g_return_if_fail (E_IS_RULE_CONTEXT (context));
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+
+ context->rules = g_list_append (context->rules, rule);
+
+ if (context->priv->frozen == 0) {
+ g_signal_emit (context, signals[RULE_ADDED], 0, rule);
+ g_signal_emit (context, signals[CHANGED], 0);
+ }
+}
+
+/* add a rule, with a gui, asking for confirmation first ... optionally save to path */
+void
+e_rule_context_add_rule_gui (ERuleContext *context,
+ EFilterRule *rule,
+ const gchar *title,
+ const gchar *path)
+{
+ GtkDialog *dialog;
+ GtkWidget *widget;
+ GtkWidget *content_area;
+
+ g_return_if_fail (E_IS_RULE_CONTEXT (context));
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+
+ widget = e_filter_rule_get_widget (rule, context);
+ gtk_widget_show (widget);
+
+ dialog =(GtkDialog *) gtk_dialog_new ();
+ gtk_dialog_add_buttons (dialog,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_has_separator (dialog, FALSE);
+
+ gtk_window_set_title ((GtkWindow *) dialog, title);
+ gtk_window_set_default_size ((GtkWindow *) dialog, 600, 400);
+ gtk_window_set_resizable ((GtkWindow *) dialog, TRUE);
+
+ content_area = gtk_dialog_get_content_area (dialog);
+ gtk_box_pack_start (GTK_BOX (content_area), widget, TRUE, TRUE, 0);
+
+ g_object_set_data_full ((GObject *) dialog, "rule", rule, g_object_unref);
+ if (path)
+ g_object_set_data_full ((GObject *) dialog, "path", g_strdup (path), g_free);
+
+ g_signal_connect (dialog, "response", G_CALLBACK (new_rule_response), context);
+
+ g_object_ref (context);
+
+ g_object_set_data_full ((GObject *) dialog, "context", context, g_object_unref);
+
+ gtk_widget_show ((GtkWidget *) dialog);
+}
+
+void
+e_rule_context_remove_rule (ERuleContext *context,
+ EFilterRule *rule)
+{
+ g_return_if_fail (E_IS_RULE_CONTEXT (context));
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+
+ context->rules = g_list_remove (context->rules, rule);
+
+ if (context->priv->frozen == 0) {
+ g_signal_emit (context, signals[RULE_REMOVED], 0, rule);
+ g_signal_emit (context, signals[CHANGED], 0);
+ }
+}
+
+void
+e_rule_context_rank_rule (ERuleContext *context,
+ EFilterRule *rule,
+ const gchar *source,
+ gint rank)
+{
+ GList *node;
+ gint i = 0, index = 0;
+
+ g_return_if_fail (E_IS_RULE_CONTEXT (context));
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+
+ if (e_rule_context_get_rank_rule (context, rule, source) == rank)
+ return;
+
+ context->rules = g_list_remove (context->rules, rule);
+ node = context->rules;
+ while (node) {
+ EFilterRule *r = node->data;
+
+ if (i == rank) {
+ context->rules = g_list_insert (context->rules, rule, index);
+ if (context->priv->frozen == 0)
+ g_signal_emit (context, signals[CHANGED], 0);
+
+ return;
+ }
+
+ index++;
+ if (source == NULL || (r->source && strcmp (r->source, source) == 0))
+ i++;
+
+ node = node->next;
+ }
+
+ context->rules = g_list_append (context->rules, rule);
+ if (context->priv->frozen == 0)
+ g_signal_emit (context, signals[CHANGED], 0);
+}
+
+gint
+e_rule_context_get_rank_rule (ERuleContext *context,
+ EFilterRule *rule,
+ const gchar *source)
+{
+ GList *node;
+ gint i = 0;
+
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), -1);
+ g_return_val_if_fail (E_IS_FILTER_RULE (rule), -1);
+
+ node = context->rules;
+ while (node) {
+ EFilterRule *r = node->data;
+
+ if (r == rule)
+ return i;
+
+ if (source == NULL || (r->source && strcmp (r->source, source) == 0))
+ i++;
+
+ node = node->next;
+ }
+
+ return -1;
+}
+
+EFilterRule *
+e_rule_context_find_rank_rule (ERuleContext *context,
+ gint rank,
+ const gchar *source)
+{
+ GList *node;
+ gint i = 0;
+
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), NULL);
+
+ node = context->rules;
+ while (node) {
+ EFilterRule *r = node->data;
+
+ if (source == NULL || (r->source && strcmp (r->source, source) == 0)) {
+ if (rank == i)
+ return r;
+ i++;
+ }
+
+ node = node->next;
+ }
+
+ return NULL;
+}
+
+GList *
+e_rule_context_rename_uri (ERuleContext *context,
+ const gchar *old_uri,
+ const gchar *new_uri,
+ GCompareFunc compare)
+{
+ ERuleContextClass *class;
+
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), NULL);
+ g_return_val_if_fail (old_uri != NULL, NULL);
+ g_return_val_if_fail (new_uri != NULL, NULL);
+ g_return_val_if_fail (compare != NULL, NULL);
+
+ class = E_RULE_CONTEXT_GET_CLASS (context);
+
+ /* This method is optional. */
+ if (class->rename_uri == NULL)
+ return NULL;
+
+ return class->rename_uri (context, old_uri, new_uri, compare);
+}
+
+GList *
+e_rule_context_delete_uri (ERuleContext *context,
+ const gchar *uri,
+ GCompareFunc compare)
+{
+ ERuleContextClass *class;
+
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), NULL);
+ g_return_val_if_fail (uri != NULL, NULL);
+ g_return_val_if_fail (compare != NULL, NULL);
+
+ class = E_RULE_CONTEXT_GET_CLASS (context);
+
+ /* This method is optional. */
+ if (class->delete_uri == NULL)
+ return NULL;
+
+ return class->delete_uri (context, uri, compare);
+}
+
+void
+e_rule_context_free_uri_list (ERuleContext *context,
+ GList *uris)
+{
+ g_return_if_fail (E_IS_RULE_CONTEXT (context));
+
+ /* TODO: should be virtual */
+
+ g_list_foreach (uris, (GFunc) g_free, NULL);
+ g_list_free (uris);
+}
+
+/**
+ * e_rule_context_new_element:
+ * @context:
+ * @name:
+ *
+ * create a new filter element based on name.
+ *
+ * Return value:
+ **/
+EFilterElement *
+e_rule_context_new_element (ERuleContext *context,
+ const gchar *name)
+{
+ ERuleContextClass *class;
+
+ g_return_val_if_fail (E_IS_RULE_CONTEXT (context), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ class = E_RULE_CONTEXT_GET_CLASS (context);
+ g_return_val_if_fail (class->new_element != NULL, NULL);
+
+ return class->new_element (context, name);
+}
diff --git a/filter/e-rule-context.h b/filter/e-rule-context.h
new file mode 100644
index 0000000000..102faef1b6
--- /dev/null
+++ b/filter/e-rule-context.h
@@ -0,0 +1,215 @@
+/*
+ *
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_RULE_CONTEXT_H
+#define E_RULE_CONTEXT_H
+
+#include <glib-object.h>
+#include <libxml/parser.h>
+
+#include "e-filter-part.h"
+#include "e-filter-rule.h"
+
+/* Standard GObject macros */
+#define E_TYPE_RULE_CONTEXT \
+ (e_rule_context_get_type ())
+#define E_RULE_CONTEXT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_RULE_CONTEXT, ERuleContext))
+#define E_RULE_CONTEXT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_RULE_CONTEXT, ERuleContextClass))
+#define E_IS_RULE_CONTEXT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_RULE_CONTEXT))
+#define E_IS_RULE_CONTEXT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_RULE_CONTEXT))
+#define E_RULE_CONTEXT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_RULE_CONTEXT, ERuleContextClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ERuleContext ERuleContext;
+typedef struct _ERuleContextClass ERuleContextClass;
+typedef struct _ERuleContextPrivate ERuleContextPrivate;
+
+/* backend capabilities, this is a hack since we don't support nested rules */
+enum {
+ E_RULE_CONTEXT_GROUPING = 1 << 0,
+ E_RULE_CONTEXT_THREADING = 1 << 1
+};
+
+typedef void (*ERuleContextRegisterFunc) (ERuleContext *context,
+ EFilterRule *rule,
+ gpointer user_data);
+typedef void (*ERuleContextPartFunc) (ERuleContext *context,
+ EFilterPart *part);
+typedef void (*ERuleContextRuleFunc) (ERuleContext *context,
+ EFilterRule *part);
+typedef EFilterPart *
+ (*ERuleContextNextPartFunc) (ERuleContext *context,
+ EFilterPart *part);
+typedef EFilterRule *
+ (*ERuleContextNextRuleFunc) (ERuleContext *context,
+ EFilterRule *rule,
+ const gchar *source);
+
+struct _ERuleContext {
+ GObject parent;
+ ERuleContextPrivate *priv;
+
+ gchar *error; /* string version of error */
+
+ guint32 flags; /* capability flags */
+
+ GList *parts;
+ GList *rules;
+
+ GHashTable *part_set_map; /* map set types to part types */
+ GList *part_set_list;
+ GHashTable *rule_set_map; /* map set types to rule types */
+ GList *rule_set_list;
+};
+
+struct _ERuleContextClass {
+ GObjectClass parent_class;
+
+ /* methods */
+ gint (*load) (ERuleContext *context,
+ const gchar *system,
+ const gchar *user);
+ gint (*save) (ERuleContext *context,
+ const gchar *user);
+ gint (*revert) (ERuleContext *context,
+ const gchar *user);
+
+ GList * (*delete_uri) (ERuleContext *context,
+ const gchar *uri,
+ GCompareFunc compare_func);
+ GList * (*rename_uri) (ERuleContext *context,
+ const gchar *old_uri,
+ const gchar *new_uri,
+ GCompareFunc compare_func);
+
+ EFilterElement *(*new_element) (ERuleContext *context,
+ const gchar *name);
+
+ /* signals */
+ void (*rule_added) (ERuleContext *context,
+ EFilterRule *rule);
+ void (*rule_removed) (ERuleContext *context,
+ EFilterRule *rule);
+ void (*changed) (ERuleContext *context);
+};
+
+struct _part_set_map {
+ gchar *name;
+ GType type;
+ ERuleContextPartFunc append;
+ ERuleContextNextPartFunc next;
+};
+
+struct _rule_set_map {
+ gchar *name;
+ GType type;
+ ERuleContextRuleFunc append;
+ ERuleContextNextRuleFunc next;
+};
+
+GType e_rule_context_get_type (void);
+ERuleContext * e_rule_context_new (void);
+
+gint e_rule_context_load (ERuleContext *context,
+ const gchar *system,
+ const gchar *user);
+gint e_rule_context_save (ERuleContext *context,
+ const gchar *user);
+gint e_rule_context_revert (ERuleContext *context,
+ const gchar *user);
+
+void e_rule_context_add_part (ERuleContext *context,
+ EFilterPart *part);
+EFilterPart * e_rule_context_find_part (ERuleContext *context,
+ const gchar *name);
+EFilterPart * e_rule_context_create_part (ERuleContext *context,
+ const gchar *name);
+EFilterPart * e_rule_context_next_part (ERuleContext *context,
+ EFilterPart *last);
+
+EFilterRule * e_rule_context_next_rule (ERuleContext *context,
+ EFilterRule *last,
+ const gchar *source);
+EFilterRule * e_rule_context_find_rule (ERuleContext *context,
+ const gchar *name,
+ const gchar *source);
+EFilterRule * e_rule_context_find_rank_rule (ERuleContext *context,
+ gint rank,
+ const gchar *source);
+void e_rule_context_add_rule (ERuleContext *context,
+ EFilterRule *rule);
+void e_rule_context_add_rule_gui (ERuleContext *context,
+ EFilterRule *rule,
+ const gchar *title,
+ const gchar *path);
+void e_rule_context_remove_rule (ERuleContext *context,
+ EFilterRule *rule);
+
+void e_rule_context_rank_rule (ERuleContext *context,
+ EFilterRule *rule,
+ const gchar *source,
+ gint rank);
+gint e_rule_context_get_rank_rule (ERuleContext *context,
+ EFilterRule *rule,
+ const gchar *source);
+
+void e_rule_context_add_part_set (ERuleContext *context,
+ const gchar *setname,
+ GType part_type,
+ ERuleContextPartFunc append,
+ ERuleContextNextPartFunc next);
+void e_rule_context_add_rule_set (ERuleContext *context,
+ const gchar *setname,
+ GType rule_type,
+ ERuleContextRuleFunc append,
+ ERuleContextNextRuleFunc next);
+
+EFilterElement *e_rule_context_new_element (ERuleContext *context,
+ const gchar *name);
+
+GList * e_rule_context_delete_uri (ERuleContext *context,
+ const gchar *uri,
+ GCompareFunc compare);
+GList * e_rule_context_rename_uri (ERuleContext *context,
+ const gchar *old_uri,
+ const gchar *new_uri,
+ GCompareFunc compare);
+
+void e_rule_context_free_uri_list (ERuleContext *context,
+ GList *uris);
+
+G_END_DECLS
+
+#endif /* E_RULE_CONTEXT_H */
diff --git a/filter/e-rule-editor.c b/filter/e-rule-editor.c
new file mode 100644
index 0000000000..59b0d5de07
--- /dev/null
+++ b/filter/e-rule-editor.c
@@ -0,0 +1,912 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* for getenv only, remove when getenv need removed */
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include "e-util/e-error.h"
+#include "e-util/e-util-private.h"
+
+#include "e-rule-editor.h"
+
+#define E_RULE_EDITOR_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_RULE_EDITOR, ERuleEditorPrivate))
+
+static gint enable_undo = 0;
+
+enum {
+ BUTTON_ADD,
+ BUTTON_EDIT,
+ BUTTON_DELETE,
+ BUTTON_TOP,
+ BUTTON_UP,
+ BUTTON_DOWN,
+ BUTTON_BOTTOM,
+ BUTTON_LAST
+};
+
+struct _ERuleEditorPrivate {
+ GtkButton *buttons[BUTTON_LAST];
+};
+
+static gpointer parent_class;
+
+static void
+rule_editor_add_undo (ERuleEditor *editor,
+ gint type,
+ EFilterRule *rule,
+ gint rank,
+ gint newrank)
+{
+ ERuleEditorUndo *undo;
+
+ if (!editor->undo_active && enable_undo) {
+ undo = g_malloc0 (sizeof (*undo));
+ undo->rule = rule;
+ undo->type = type;
+ undo->rank = rank;
+ undo->newrank = newrank;
+
+ undo->next = editor->undo_log;
+ editor->undo_log = undo;
+ } else {
+ g_object_unref (rule);
+ }
+}
+
+static void
+rule_editor_play_undo (ERuleEditor *editor)
+{
+ ERuleEditorUndo *undo, *next;
+ EFilterRule *rule;
+
+ editor->undo_active = TRUE;
+ undo = editor->undo_log;
+ editor->undo_log = NULL;
+ while (undo) {
+ next = undo->next;
+ switch (undo->type) {
+ case E_RULE_EDITOR_LOG_EDIT:
+ rule = e_rule_context_find_rank_rule (editor->context, undo->rank, undo->rule->source);
+ if (rule) {
+ e_filter_rule_copy (rule, undo->rule);
+ } else {
+ g_warning ("Could not find the right rule to undo against?");
+ }
+ break;
+ case E_RULE_EDITOR_LOG_ADD:
+ rule = e_rule_context_find_rank_rule (editor->context, undo->rank, undo->rule->source);
+ if (rule)
+ e_rule_context_remove_rule (editor->context, rule);
+ break;
+ case E_RULE_EDITOR_LOG_REMOVE:
+ g_object_ref (undo->rule);
+ e_rule_context_add_rule (editor->context, undo->rule);
+ e_rule_context_rank_rule (editor->context, undo->rule, editor->source, undo->rank);
+ break;
+ case E_RULE_EDITOR_LOG_RANK:
+ rule = e_rule_context_find_rank_rule (editor->context, undo->newrank, undo->rule->source);
+ if (rule)
+ e_rule_context_rank_rule (editor->context, rule, editor->source, undo->rank);
+ break;
+ }
+
+ g_object_unref (undo->rule);
+ g_free (undo);
+ undo = next;
+ }
+ editor->undo_active = FALSE;
+}
+
+static void
+dialog_rule_changed (EFilterRule *fr, GtkWidget *dialog)
+{
+ g_return_if_fail (dialog != NULL);
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, fr && fr->parts);
+}
+
+static void
+add_editor_response (GtkWidget *dialog, gint button, ERuleEditor *editor)
+{
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ if (button == GTK_RESPONSE_OK) {
+ if (!e_filter_rule_validate (editor->edit, GTK_WINDOW (dialog))) {
+ /* no need to popup a dialog because the validate code does that. */
+ return;
+ }
+
+ if (e_rule_context_find_rule (editor->context, editor->edit->name, editor->edit->source)) {
+ e_error_run ((GtkWindow *)dialog, "filter:bad-name-notunique", editor->edit->name, NULL);
+ return;
+ }
+
+ g_object_ref (editor->edit);
+
+ gtk_list_store_append (editor->model, &iter);
+ gtk_list_store_set (editor->model, &iter, 0, editor->edit->name, 1, editor->edit, 2, editor->edit->enabled, -1);
+ selection = gtk_tree_view_get_selection (editor->list);
+ gtk_tree_selection_select_iter (selection, &iter);
+
+ /* scroll to the newly added row */
+ path = gtk_tree_model_get_path ((GtkTreeModel *) editor->model, &iter);
+ gtk_tree_view_scroll_to_cell (editor->list, path, NULL, TRUE, 1.0, 0.0);
+ gtk_tree_path_free (path);
+
+ editor->current = editor->edit;
+ e_rule_context_add_rule (editor->context, editor->current);
+
+ g_object_ref (editor->current);
+ rule_editor_add_undo (editor, E_RULE_EDITOR_LOG_ADD, editor->current,
+ e_rule_context_get_rank_rule (editor->context, editor->current, editor->current->source), 0);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+editor_destroy (ERuleEditor *editor,
+ GObject *deadbeef)
+{
+ if (editor->edit) {
+ g_object_unref (editor->edit);
+ editor->edit = NULL;
+ }
+
+ editor->dialog = NULL;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (editor), TRUE);
+ e_rule_editor_set_sensitive (editor);
+}
+
+static gboolean
+update_selected_rule (ERuleEditor *editor)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ selection = gtk_tree_view_get_selection (editor->list);
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ gtk_tree_model_get (GTK_TREE_MODEL (editor->model), &iter, 1, &editor->current, -1);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+cursor_changed (GtkTreeView *treeview, ERuleEditor *editor)
+{
+ if (update_selected_rule(editor)) {
+ g_return_if_fail (editor->current);
+
+ e_rule_editor_set_sensitive (editor);
+ }
+}
+
+static void
+editor_response (GtkWidget *dialog, gint button, ERuleEditor *editor)
+{
+ if (button == GTK_RESPONSE_CANCEL) {
+ if (enable_undo)
+ rule_editor_play_undo (editor);
+ else {
+ ERuleEditorUndo *undo, *next;
+
+ undo = editor->undo_log;
+ editor->undo_log = NULL;
+ while (undo) {
+ next = undo->next;
+ g_object_unref (undo->rule);
+ g_free (undo);
+ undo = next;
+ }
+ }
+ }
+}
+
+static void
+rule_add (GtkWidget *widget, ERuleEditor *editor)
+{
+ GtkWidget *rules;
+ GtkWidget *content_area;
+
+ if (editor->edit != NULL)
+ return;
+
+ editor->edit = e_rule_editor_create_rule (editor);
+ e_filter_rule_set_source (editor->edit, editor->source);
+ rules = e_filter_rule_get_widget (editor->edit, editor->context);
+
+ editor->dialog = gtk_dialog_new ();
+ gtk_dialog_add_buttons ((GtkDialog *) editor->dialog,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_has_separator ((GtkDialog *) editor->dialog, FALSE);
+
+ gtk_window_set_title ((GtkWindow *) editor->dialog, _("Add Rule"));
+ gtk_window_set_default_size (GTK_WINDOW (editor->dialog), 650, 400);
+ gtk_window_set_resizable (GTK_WINDOW (editor->dialog), TRUE);
+ gtk_window_set_transient_for ((GtkWindow *) editor->dialog, (GtkWindow *) editor);
+ gtk_container_set_border_width ((GtkContainer *) editor->dialog, 6);
+
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (editor->dialog));
+ gtk_box_pack_start (GTK_BOX (content_area), rules, TRUE, TRUE, 3);
+
+ g_signal_connect (editor->dialog, "response", G_CALLBACK (add_editor_response), editor);
+ g_object_weak_ref ((GObject *) editor->dialog, (GWeakNotify) editor_destroy, editor);
+
+ g_signal_connect (editor->edit, "changed", G_CALLBACK (dialog_rule_changed), editor->dialog);
+ dialog_rule_changed (editor->edit, editor->dialog);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE);
+
+ gtk_widget_show (editor->dialog);
+}
+
+static void
+edit_editor_response (GtkWidget *dialog, gint button, ERuleEditor *editor)
+{
+ EFilterRule *rule;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gint pos;
+
+ if (button == GTK_RESPONSE_OK) {
+ if (!e_filter_rule_validate (editor->edit, GTK_WINDOW (dialog))) {
+ /* no need to popup a dialog because the validate code does that. */
+ return;
+ }
+
+ rule = e_rule_context_find_rule (editor->context, editor->edit->name, editor->edit->source);
+ if (rule != NULL && rule != editor->current) {
+ e_error_run ((GtkWindow *)dialog, "filter:bad-name-notunique", rule->name, NULL);
+
+ return;
+ }
+
+ pos = e_rule_context_get_rank_rule (editor->context, editor->current, editor->source);
+ if (pos != -1) {
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, pos);
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (editor->model), &iter, path);
+ gtk_tree_path_free (path);
+
+ gtk_list_store_set (editor->model, &iter, 0, editor->edit->name, -1);
+
+ rule_editor_add_undo (editor, E_RULE_EDITOR_LOG_EDIT, e_filter_rule_clone (editor->current),
+ pos, 0);
+
+ /* replace the old rule with the new rule */
+ e_filter_rule_copy (editor->current, editor->edit);
+ }
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+rule_edit (GtkWidget *widget, ERuleEditor *editor)
+{
+ GtkWidget *rules;
+ GtkWidget *content_area;
+
+ update_selected_rule(editor);
+
+ if (editor->current == NULL || editor->edit != NULL)
+ return;
+
+ editor->edit = e_filter_rule_clone (editor->current);
+
+ rules = e_filter_rule_get_widget (editor->edit, editor->context);
+
+ editor->dialog = gtk_dialog_new ();
+ gtk_dialog_add_buttons ((GtkDialog *) editor->dialog,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_has_separator ((GtkDialog *) editor->dialog, FALSE);
+
+ gtk_window_set_title ((GtkWindow *) editor->dialog, _("Edit Rule"));
+ gtk_window_set_default_size (GTK_WINDOW (editor->dialog), 650, 400);
+ gtk_window_set_resizable (GTK_WINDOW (editor->dialog), TRUE);
+ gtk_widget_set_parent_window (GTK_WIDGET (editor->dialog), GTK_WIDGET (editor)->window);
+ gtk_container_set_border_width ((GtkContainer *) editor->dialog, 6);
+
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (editor->dialog));
+ gtk_box_pack_start (GTK_BOX (content_area), rules, TRUE, TRUE, 3);
+
+ g_signal_connect (editor->dialog, "response", G_CALLBACK (edit_editor_response), editor);
+ g_object_weak_ref ((GObject *) editor->dialog, (GWeakNotify) editor_destroy, editor);
+
+ g_signal_connect (editor->edit, "changed", G_CALLBACK (dialog_rule_changed), editor->dialog);
+ dialog_rule_changed (editor->edit, editor->dialog);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE);
+
+ gtk_widget_show (editor->dialog);
+}
+
+static void
+rule_delete (GtkWidget *widget, ERuleEditor *editor)
+{
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gint pos, len;
+
+ update_selected_rule(editor);
+
+ pos = e_rule_context_get_rank_rule (editor->context, editor->current, editor->source);
+ if (pos != -1) {
+ e_rule_context_remove_rule (editor->context, editor->current);
+
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, pos);
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (editor->model), &iter, path);
+ gtk_list_store_remove (editor->model, &iter);
+ gtk_tree_path_free (path);
+
+ rule_editor_add_undo (editor, E_RULE_EDITOR_LOG_REMOVE, editor->current,
+ e_rule_context_get_rank_rule (editor->context, editor->current, editor->current->source), 0);
+#if 0
+ g_object_unref (editor->current);
+#endif
+ editor->current = NULL;
+
+ /* now select the next rule */
+ len = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (editor->model), NULL);
+ pos = pos >= len ? len - 1 : pos;
+
+ if (pos >= 0) {
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, pos);
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (editor->model), &iter, path);
+ gtk_tree_path_free (path);
+
+ /* select the new row */
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (editor->list));
+ gtk_tree_selection_select_iter (selection, &iter);
+
+ /* scroll to the selected row */
+ path = gtk_tree_model_get_path ((GtkTreeModel *) editor->model, &iter);
+ gtk_tree_view_scroll_to_cell (editor->list, path, NULL, FALSE, 0.0, 0.0);
+ gtk_tree_path_free (path);
+
+ /* update our selection state */
+ cursor_changed (editor->list, editor);
+ return;
+ }
+ }
+
+ e_rule_editor_set_sensitive (editor);
+}
+
+static void
+rule_move (ERuleEditor *editor, gint from, gint to)
+{
+ GtkTreeSelection *selection;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ EFilterRule *rule;
+
+ rule_editor_add_undo (
+ editor, E_RULE_EDITOR_LOG_RANK,
+ g_object_ref (editor->current),
+ e_rule_context_get_rank_rule (editor->context,
+ editor->current, editor->source), to);
+
+ e_rule_context_rank_rule (
+ editor->context, editor->current, editor->source, to);
+
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, from);
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (editor->model), &iter, path);
+ gtk_tree_path_free (path);
+
+ gtk_tree_model_get (GTK_TREE_MODEL (editor->model), &iter, 1, &rule, -1);
+ g_return_if_fail (rule != NULL);
+
+ /* remove and then re-insert the row at the new location */
+ gtk_list_store_remove (editor->model, &iter);
+ gtk_list_store_insert (editor->model, &iter, to);
+
+ /* set the data on the row */
+ gtk_list_store_set (editor->model, &iter, 0, rule->name, 1, rule, 2, rule->enabled, -1);
+
+ /* select the row */
+ selection = gtk_tree_view_get_selection (editor->list);
+ gtk_tree_selection_select_iter (selection, &iter);
+
+ /* scroll to the selected row */
+ path = gtk_tree_model_get_path ((GtkTreeModel *) editor->model, &iter);
+ gtk_tree_view_scroll_to_cell (editor->list, path, NULL, FALSE, 0.0, 0.0);
+ gtk_tree_path_free (path);
+
+ e_rule_editor_set_sensitive (editor);
+}
+
+static void
+rule_top (GtkWidget *widget, ERuleEditor *editor)
+{
+ gint pos;
+
+ update_selected_rule(editor);
+
+ pos = e_rule_context_get_rank_rule (
+ editor->context, editor->current, editor->source);
+ if (pos > 0)
+ rule_move (editor, pos, 0);
+}
+
+static void
+rule_up (GtkWidget *widget, ERuleEditor *editor)
+{
+ gint pos;
+
+ update_selected_rule(editor);
+
+ pos = e_rule_context_get_rank_rule (
+ editor->context, editor->current, editor->source);
+ if (pos > 0)
+ rule_move (editor, pos, pos - 1);
+}
+
+static void
+rule_down (GtkWidget *widget, ERuleEditor *editor)
+{
+ gint pos;
+
+ update_selected_rule(editor);
+
+ pos = e_rule_context_get_rank_rule (
+ editor->context, editor->current, editor->source);
+ if (pos >= 0)
+ rule_move (editor, pos, pos + 1);
+}
+
+static void
+rule_bottom (GtkWidget *widget, ERuleEditor *editor)
+{
+ gint pos;
+ gint index = -1, count = 0;
+ EFilterRule *rule = NULL;
+
+ update_selected_rule(editor);
+
+ pos = e_rule_context_get_rank_rule (
+ editor->context, editor->current, editor->source);
+ /* There's probably a better/faster way to get the count of the list here */
+ while ((rule = e_rule_context_next_rule (editor->context, rule, editor->source))) {
+ if (rule == editor->current)
+ index = count;
+ count++;
+ }
+ count--;
+ if (pos >= 0)
+ rule_move (editor, pos, count);
+}
+
+static struct {
+ const gchar *name;
+ GCallback func;
+} edit_buttons[] = {
+ { "rule_add", G_CALLBACK (rule_add) },
+ { "rule_edit", G_CALLBACK (rule_edit) },
+ { "rule_delete", G_CALLBACK (rule_delete) },
+ { "rule_top", G_CALLBACK (rule_top) },
+ { "rule_up", G_CALLBACK (rule_up) },
+ { "rule_down", G_CALLBACK (rule_down) },
+ { "rule_bottom", G_CALLBACK (rule_bottom) },
+};
+
+static void
+rule_editor_finalize (GObject *object)
+{
+ ERuleEditor *editor = E_RULE_EDITOR (object);
+ ERuleEditorUndo *undo, *next;
+
+ g_object_unref (editor->context);
+
+ undo = editor->undo_log;
+ while (undo) {
+ next = undo->next;
+ g_object_unref (undo->rule);
+ g_free (undo);
+ undo = next;
+ }
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+rule_editor_destroy (GtkObject *gtk_object)
+{
+ ERuleEditor *editor = E_RULE_EDITOR (gtk_object);
+
+ if (editor->dialog != NULL) {
+ gtk_widget_destroy (GTK_WIDGET (editor->dialog));
+ editor->dialog = NULL;
+ }
+
+ /* Chain up to parent's destroy() method. */
+ GTK_OBJECT_CLASS (parent_class)->destroy (gtk_object);
+}
+
+static void
+rule_editor_set_source (ERuleEditor *editor,
+ const gchar *source)
+{
+ EFilterRule *rule = NULL;
+ GtkTreeIter iter;
+
+ gtk_list_store_clear (editor->model);
+
+ while ((rule = e_rule_context_next_rule (editor->context, rule, source)) != NULL) {
+ gtk_list_store_append (editor->model, &iter);
+ gtk_list_store_set (
+ editor->model, &iter,
+ 0, rule->name, 1, rule, 2, rule->enabled, -1);
+ }
+
+ g_free (editor->source);
+ editor->source = g_strdup (source);
+ editor->current = NULL;
+ e_rule_editor_set_sensitive (editor);
+}
+
+static void
+rule_editor_set_sensitive (ERuleEditor *editor)
+{
+ EFilterRule *rule = NULL;
+ gint index = -1, count = 0;
+
+ while ((rule = e_rule_context_next_rule (editor->context, rule, editor->source))) {
+ if (rule == editor->current)
+ index = count;
+ count++;
+ }
+
+ count--;
+
+ gtk_widget_set_sensitive (GTK_WIDGET (editor->priv->buttons[BUTTON_EDIT]), index != -1);
+ gtk_widget_set_sensitive (GTK_WIDGET (editor->priv->buttons[BUTTON_DELETE]), index != -1);
+ gtk_widget_set_sensitive (GTK_WIDGET (editor->priv->buttons[BUTTON_TOP]), index > 0);
+ gtk_widget_set_sensitive (GTK_WIDGET (editor->priv->buttons[BUTTON_UP]), index > 0);
+ gtk_widget_set_sensitive (GTK_WIDGET (editor->priv->buttons[BUTTON_DOWN]), index >= 0 && index < count);
+ gtk_widget_set_sensitive (GTK_WIDGET (editor->priv->buttons[BUTTON_BOTTOM]), index >= 0 && index < count);
+}
+
+static EFilterRule *
+rule_editor_create_rule (ERuleEditor *editor)
+{
+ EFilterRule *rule;
+ EFilterPart *part;
+
+ /* create a rule with 1 part in it */
+ rule = e_filter_rule_new ();
+ part = e_rule_context_next_part (editor->context, NULL);
+ e_filter_rule_add_part (rule, e_filter_part_clone (part));
+
+ return rule;
+}
+
+static void
+rule_editor_class_init (ERuleEditorClass *class)
+{
+ GObjectClass *object_class;
+ GtkObjectClass *gtk_object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (ERuleEditorPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = rule_editor_finalize;
+
+ gtk_object_class = GTK_OBJECT_CLASS (class);
+ gtk_object_class->destroy = rule_editor_destroy;
+
+ class->set_source = rule_editor_set_source;
+ class->set_sensitive = rule_editor_set_sensitive;
+ class->create_rule = rule_editor_create_rule;
+
+ /* TODO: Remove when it works (or never will) */
+ enable_undo = getenv ("EVOLUTION_RULE_UNDO") != NULL;
+}
+
+static void
+rule_editor_init (ERuleEditor *editor)
+{
+ editor->priv = E_RULE_EDITOR_GET_PRIVATE (editor);
+}
+
+GType
+e_rule_editor_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (ERuleEditorClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) rule_editor_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (ERuleEditor),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) rule_editor_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_DIALOG, "ERuleEditor", &type_info, 0);
+ }
+
+ return type;
+}
+
+/**
+ * rule_editor_new:
+ *
+ * Create a new ERuleEditor object.
+ *
+ * Return value: A new #ERuleEditor object.
+ **/
+ERuleEditor *
+e_rule_editor_new (ERuleContext *context,
+ const gchar *source,
+ const gchar *label)
+{
+ ERuleEditor *editor = (ERuleEditor *) g_object_new (E_TYPE_RULE_EDITOR, NULL);
+ GladeXML *gui;
+ gchar *filter_glade = g_build_filename (EVOLUTION_GLADEDIR,
+ "filter.glade",
+ NULL);
+
+ gui = glade_xml_new (filter_glade, "rule_editor", NULL);
+ g_free (filter_glade);
+ e_rule_editor_construct (editor, context, gui, source, label);
+ gtk_widget_hide (glade_xml_get_widget (gui, "label17"));
+ gtk_widget_hide (glade_xml_get_widget (gui, "filter_source_combobox"));
+ g_object_unref (gui);
+
+ return editor;
+}
+
+void
+e_rule_editor_set_sensitive (ERuleEditor *editor)
+{
+ ERuleEditorClass *class;
+
+ g_return_if_fail (E_IS_RULE_EDITOR (editor));
+
+ class = E_RULE_EDITOR_GET_CLASS (editor);
+ g_return_if_fail (class->set_sensitive != NULL);
+
+ class->set_sensitive (editor);
+}
+
+void
+e_rule_editor_set_source (ERuleEditor *editor,
+ const gchar *source)
+{
+ ERuleEditorClass *class;
+
+ g_return_if_fail (E_IS_RULE_EDITOR (editor));
+
+ class = E_RULE_EDITOR_GET_CLASS (editor);
+ g_return_if_fail (class->set_source != NULL);
+
+ class->set_source (editor, source);
+}
+
+EFilterRule *
+e_rule_editor_create_rule (ERuleEditor *editor)
+{
+ ERuleEditorClass *class;
+
+ g_return_val_if_fail (E_IS_RULE_EDITOR (editor), NULL);
+
+ class = E_RULE_EDITOR_GET_CLASS (editor);
+ g_return_val_if_fail (class->create_rule != NULL, NULL);
+
+ return class->create_rule (editor);
+}
+
+static void
+double_click (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, ERuleEditor *editor)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ selection = gtk_tree_view_get_selection (editor->list);
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ gtk_tree_model_get (GTK_TREE_MODEL (editor->model), &iter, 1, &editor->current, -1);
+
+ if (editor->current)
+ rule_edit ((GtkWidget *) treeview, editor);
+}
+
+static void
+rule_able_toggled (GtkCellRendererToggle *renderer,
+ gchar *arg1,
+ gpointer user_data)
+{
+ GtkWidget *table = user_data;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ path = gtk_tree_path_new_from_string (arg1);
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (table));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (table));
+
+ if (gtk_tree_model_get_iter (model, &iter, path)) {
+ EFilterRule *rule = NULL;
+
+ gtk_tree_model_get (model, &iter, 1, &rule, -1);
+
+ if (rule) {
+ rule->enabled = !rule->enabled;
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter, 2, rule->enabled, -1);
+ }
+ }
+
+ gtk_tree_path_free (path);
+}
+
+GtkWidget *
+rule_editor_treeview_new (gchar *widget_name,
+ gchar *string1,
+ gchar *string2,
+ gint int1,
+ gint int2);
+
+GtkWidget *
+rule_editor_treeview_new (gchar *widget_name,
+ gchar *string1,
+ gchar *string2,
+ gint int1,
+ gint int2)
+{
+ GtkWidget *table, *scrolled;
+ GtkTreeSelection *selection;
+ GtkCellRenderer *renderer;
+ GtkListStore *model;
+ GtkTreeViewColumn *column;
+
+ scrolled = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN);
+ table = gtk_tree_view_new_with_model ((GtkTreeModel *) model);
+ gtk_tree_view_set_headers_visible ((GtkTreeView *) table, FALSE);
+
+ renderer = gtk_cell_renderer_toggle_new ();
+ g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
+ gtk_tree_view_insert_column_with_attributes ((GtkTreeView *) table, -1,
+ _("Enabled"), renderer,
+ "active", 2, NULL);
+ g_signal_connect (renderer, "toggled", G_CALLBACK (rule_able_toggled), table);
+
+ /* hide enable column by default */
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW (table), 0);
+ gtk_tree_view_column_set_visible (column, FALSE);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_attributes ((GtkTreeView *) table, -1,
+ _("Rule name"), renderer,
+ "text", 0, NULL);
+
+ selection = gtk_tree_view_get_selection ((GtkTreeView *) table);
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+ gtk_container_add (GTK_CONTAINER (scrolled), table);
+
+ g_object_set_data ((GObject *) scrolled, "table", table);
+ g_object_set_data ((GObject *) scrolled, "model", model);
+
+ gtk_widget_show (scrolled);
+ gtk_widget_show (table);
+
+ g_object_unref (model);
+
+ return scrolled;
+}
+
+void
+e_rule_editor_construct (ERuleEditor *editor,
+ ERuleContext *context,
+ GladeXML *gui,
+ const gchar *source,
+ const gchar *label)
+{
+ GtkWidget *w;
+ GtkWidget *action_area;
+ GtkWidget *content_area;
+ gint i;
+ gchar *tmp;
+
+ g_return_if_fail (E_IS_RULE_EDITOR (editor));
+ g_return_if_fail (E_IS_RULE_CONTEXT (context));
+ g_return_if_fail (GLADE_IS_XML (gui));
+
+ editor->context = g_object_ref (context);
+
+ action_area = gtk_dialog_get_action_area (GTK_DIALOG (editor));
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (editor));
+
+ gtk_window_set_resizable ((GtkWindow *) editor, TRUE);
+ gtk_window_set_default_size ((GtkWindow *) editor, 350, 400);
+ gtk_widget_realize ((GtkWidget *) editor);
+ gtk_container_set_border_width (GTK_CONTAINER (action_area), 12);
+
+ w = glade_xml_get_widget(gui, "rule_editor");
+ gtk_box_pack_start (GTK_BOX (content_area), w, TRUE, TRUE, 3);
+
+ for (i = 0; i < BUTTON_LAST; i++) {
+ editor->priv->buttons[i] = (GtkButton *) (w = glade_xml_get_widget (gui, edit_buttons[i].name));
+ g_signal_connect (w, "clicked", edit_buttons[i].func, editor);
+ }
+
+ w = glade_xml_get_widget (gui, "rule_list");
+ editor->list = (GtkTreeView *) g_object_get_data ((GObject *) w, "table");
+ editor->model = (GtkListStore *) g_object_get_data ((GObject *) w, "model");
+
+ g_signal_connect (editor->list, "cursor-changed", G_CALLBACK (cursor_changed), editor);
+ g_signal_connect (editor->list, "row-activated", G_CALLBACK (double_click), editor);
+
+ w = glade_xml_get_widget (gui, "rule_label");
+ tmp = alloca(strlen(label)+8);
+ sprintf(tmp, "<b>%s</b>", label);
+ gtk_label_set_label((GtkLabel *)w, tmp);
+ gtk_label_set_mnemonic_widget ((GtkLabel *) w, (GtkWidget *) editor->list);
+
+ g_signal_connect (editor, "response", G_CALLBACK (editor_response), editor);
+ rule_editor_set_source (editor, source);
+
+ gtk_dialog_set_has_separator ((GtkDialog *) editor, FALSE);
+ gtk_dialog_add_buttons ((GtkDialog *) editor,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+}
diff --git a/filter/e-rule-editor.h b/filter/e-rule-editor.h
new file mode 100644
index 0000000000..f7f2d2defd
--- /dev/null
+++ b/filter/e-rule-editor.h
@@ -0,0 +1,122 @@
+/*
+ * 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; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_RULE_EDITOR_H
+#define E_RULE_EDITOR_H
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+
+#include "e-rule-context.h"
+#include "e-filter-rule.h"
+
+/* Standard GObject macros */
+#define E_TYPE_RULE_EDITOR \
+ (e_rule_editor_get_type ())
+#define E_RULE_EDITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_RULE_EDITOR, ERuleEditor))
+#define E_RULE_EDITOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_RULE_EDITOR, ERuleEditorClass))
+#define E_IS_RULE_EDITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_RULE_EDITOR))
+#define E_IS_RULE_EDITOR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_RULE_EDITOR))
+#define E_RULE_EDITOR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_RULE_EDITOR, ERuleEditorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ERuleEditor ERuleEditor;
+typedef struct _ERuleEditorClass ERuleEditorClass;
+typedef struct _ERuleEditorPrivate ERuleEditorPrivate;
+
+typedef struct _ERuleEditorUndo ERuleEditorUndo;
+
+struct _ERuleEditor {
+ GtkDialog parent;
+
+ GtkListStore *model;
+ GtkTreeView *list;
+
+ ERuleContext *context;
+ EFilterRule *current;
+ EFilterRule *edit; /* for editing/adding rules, so we only do 1 at a time */
+
+ GtkWidget *dialog;
+
+ gchar *source;
+
+ ERuleEditorUndo *undo_log; /* cancel/undo log */
+ guint undo_active:1; /* we're performing undo */
+
+ ERuleEditorPrivate *priv;
+};
+
+struct _ERuleEditorClass {
+ GtkDialogClass parent_class;
+
+ void (*set_sensitive) (ERuleEditor *editor);
+ void (*set_source) (ERuleEditor *editor,
+ const gchar *source);
+
+ EFilterRule * (*create_rule) (ERuleEditor *editor);
+};
+
+enum {
+ E_RULE_EDITOR_LOG_EDIT,
+ E_RULE_EDITOR_LOG_ADD,
+ E_RULE_EDITOR_LOG_REMOVE,
+ E_RULE_EDITOR_LOG_RANK
+};
+
+struct _ERuleEditorUndo {
+ ERuleEditorUndo *next;
+
+ guint type;
+ EFilterRule *rule;
+ gint rank;
+ gint newrank;
+};
+
+GType e_rule_editor_get_type (void);
+ERuleEditor * e_rule_editor_new (ERuleContext *context,
+ const gchar *source,
+ const gchar *label);
+void e_rule_editor_construct (ERuleEditor *editor,
+ ERuleContext *context,
+ GladeXML *gui,
+ const gchar *source,
+ const gchar *label);
+void e_rule_editor_set_source (ERuleEditor *editor,
+ const gchar *source);
+void e_rule_editor_set_sensitive (ERuleEditor *editor);
+EFilterRule * e_rule_editor_create_rule (ERuleEditor *editor);
+
+G_END_DECLS
+
+#endif /* E_RULE_EDITOR_H */
diff --git a/filter/filter-code.c b/filter/filter-code.c
deleted file mode 100644
index 9c7eb152ea..0000000000
--- a/filter/filter-code.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "filter-code.h"
-
-static void build_code (FilterElement *fe, GString *out, struct _FilterPart *ff);
-static void format_sexp (FilterElement *, GString *);
-
-static void filter_code_class_init (FilterCodeClass *class);
-static void filter_code_init (FilterCode *fc);
-static void filter_code_finalise (GObject *obj);
-
-static FilterInputClass *parent_class;
-
-GType
-filter_code_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (FilterCodeClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) filter_code_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (FilterCode),
- 0, /* n_preallocs */
- (GInstanceInitFunc) filter_code_init,
- };
-
- type = g_type_register_static (FILTER_TYPE_INPUT, "FilterCode", &info, 0);
- }
-
- return type;
-}
-
-static void
-filter_code_class_init (FilterCodeClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- FilterElementClass *fe_class = FILTER_ELEMENT_CLASS (klass);
-
- parent_class = g_type_class_ref (FILTER_TYPE_INPUT);
-
- object_class->finalize = filter_code_finalise;
-
- /* override methods */
- fe_class->build_code = build_code;
- fe_class->format_sexp = format_sexp;
-}
-
-static void
-filter_code_init (FilterCode *fc)
-{
- ((FilterInput *) fc)->type = (gchar *)xmlStrdup ((const guchar *)"code");
-}
-
-static void
-filter_code_finalise (GObject *obj)
-{
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-/**
- * filter_code_new:
- *
- * Create a new FilterCode object.
- *
- * Return value: A new #FilterCode object.
- **/
-FilterCode *
-filter_code_new (gboolean raw_code)
-{
- FilterCode *fc = (FilterCode *) g_object_new (FILTER_TYPE_CODE, NULL, NULL);
-
- if (fc && raw_code) {
- xmlFree (((FilterInput *) fc)->type);
- ((FilterInput *) fc)->type = (gchar *)xmlStrdup ((const guchar *)"rawcode");
- }
-
- return fc;
-}
-
-/* here, the string IS the code */
-static void
-build_code (FilterElement *fe, GString *out, struct _FilterPart *ff)
-{
- GList *l;
- FilterInput *fi = (FilterInput *)fe;
- gboolean is_rawcode = fi && fi->type && g_str_equal (fi->type, "rawcode");
-
- if (!is_rawcode)
- g_string_append(out, "(match-all ");
-
- l = fi->values;
- while (l) {
- g_string_append(out, (gchar *)l->data);
- l = g_list_next(l);
- }
-
- if (!is_rawcode)
- g_string_append (out, ")");
-}
-
-/* and we have no value */
-static void
-format_sexp (FilterElement *fe, GString *out)
-{
- ;
-}
diff --git a/filter/filter-code.h b/filter/filter-code.h
deleted file mode 100644
index 38336fc450..0000000000
--- a/filter/filter-code.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _FILTER_CODE_H
-#define _FILTER_CODE_H
-
-#include "filter-input.h"
-
-#define FILTER_TYPE_CODE (filter_code_get_type ())
-#define FILTER_CODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FILTER_TYPE_CODE, FilterCode))
-#define FILTER_CODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FILTER_TYPE_CODE, FilterCodeClass))
-#define IS_FILTER_CODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FILTER_TYPE_CODE))
-#define IS_FILTER_CODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FILTER_TYPE_CODE))
-#define FILTER_CODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FILTER_TYPE_CODE, FilterCodeClass))
-
-typedef struct _FilterCode FilterCode;
-typedef struct _FilterCodeClass FilterCodeClass;
-
-struct _FilterCode {
- FilterInput parent_object;
-};
-
-struct _FilterCodeClass {
- FilterInputClass parent_class;
-
- /* virtual methods */
-
- /* signals */
-};
-
-GType filter_code_get_type (void);
-FilterCode *filter_code_new (gboolean raw_code);
-
-/* methods */
-
-#endif /* ! _FILTER_CODE_H */
diff --git a/filter/filter-colour.c b/filter/filter-colour.c
deleted file mode 100644
index f466f63390..0000000000
--- a/filter/filter-colour.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gtk/gtk.h>
-
-#include "libedataserver/e-sexp.h"
-#include "filter-colour.h"
-
-#define d(x)
-
-static gint colour_eq (FilterElement *fe, FilterElement *cm);
-static void xml_create (FilterElement *fe, xmlNodePtr node);
-static xmlNodePtr xml_encode (FilterElement *fe);
-static gint 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 *, GString *);
-
-static void filter_colour_class_init (FilterColourClass *klass);
-static void filter_colour_init (FilterColour *fc);
-static void filter_colour_finalise (GObject *obj);
-
-static FilterElementClass *parent_class;
-
-GType
-filter_colour_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (FilterColourClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) filter_colour_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (FilterColour),
- 0, /* n_preallocs */
- (GInstanceInitFunc) filter_colour_init,
- };
-
- type = g_type_register_static (FILTER_TYPE_ELEMENT, "FilterColour", &info, 0);
- }
-
- return type;
-}
-
-static void
-filter_colour_class_init (FilterColourClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- FilterElementClass *fe_class = FILTER_ELEMENT_CLASS (klass);
-
- parent_class = g_type_class_ref (FILTER_TYPE_ELEMENT);
-
- object_class->finalize = filter_colour_finalise;
-
- /* override methods */
- fe_class->eq = colour_eq;
- fe_class->xml_create = xml_create;
- fe_class->xml_encode = xml_encode;
- fe_class->xml_decode = xml_decode;
- fe_class->get_widget = get_widget;
- fe_class->build_code = build_code;
- fe_class->format_sexp = format_sexp;
-}
-
-static void
-filter_colour_init (FilterColour *fc)
-{
- ;
-}
-
-static void
-filter_colour_finalise (GObject *obj)
-{
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-/**
- * filter_colour_new:
- *
- * Create a new FilterColour object.
- *
- * Return value: A new #FilterColour object.
- **/
-FilterColour *
-filter_colour_new (void)
-{
- return (FilterColour *) g_object_new (FILTER_TYPE_COLOUR, NULL, NULL);
-}
-
-static gint
-colour_eq (FilterElement *fe, FilterElement *cm)
-{
- FilterColour *fc = (FilterColour *) fe;
- FilterColour *cc = (FilterColour *) cm;
-
- return FILTER_ELEMENT_CLASS (parent_class)->eq (fe, cm)
- && gdk_color_equal (&fc->color, &cc->color);
-}
-
-static void
-xml_create (FilterElement *fe, xmlNodePtr node)
-{
- /* parent implementation */
- FILTER_ELEMENT_CLASS (parent_class)->xml_create (fe, node);
-}
-
-static xmlNodePtr
-xml_encode (FilterElement *fe)
-{
- FilterColour *fc = (FilterColour *)fe;
- xmlNodePtr value;
- gchar spec[16];
-
- g_snprintf (spec, sizeof (spec), "#%04x%04x%04x",
- fc->color.red, fc->color.green, fc->color.blue);
-
- value = xmlNewNode(NULL, (const guchar *)"value");
- xmlSetProp(value, (const guchar *)"type", (const guchar *)"colour");
- xmlSetProp(value, (const guchar *)"name", (guchar *)fe->name);
- xmlSetProp(value, (const guchar *)"spec", (guchar *)spec);
-
- return value;
-}
-
-static gint
-xml_decode (FilterElement *fe, xmlNodePtr node)
-{
- FilterColour *fc = (FilterColour *)fe;
- xmlChar *prop;
-
- xmlFree (fe->name);
- fe->name = (gchar *)xmlGetProp(node, (const guchar *)"name");
-
- prop = xmlGetProp(node, (const guchar *)"spec");
- if (prop != NULL) {
- gdk_color_parse((gchar *)prop, &fc->color);
- xmlFree (prop);
- } else {
- /* try reading the old RGB properties */
- prop = xmlGetProp(node, (const guchar *)"red");
- sscanf((gchar *)prop, "%" G_GINT16_MODIFIER "x", &fc->color.red);
- xmlFree (prop);
- prop = xmlGetProp(node, (const guchar *)"green");
- sscanf((gchar *)prop, "%" G_GINT16_MODIFIER "x", &fc->color.green);
- xmlFree (prop);
- prop = xmlGetProp(node, (const guchar *)"blue");
- sscanf((gchar *)prop, "%" G_GINT16_MODIFIER "x", &fc->color.blue);
- xmlFree (prop);
- }
-
- return 0;
-}
-
-static void
-set_color (GtkColorButton *color_button, FilterColour *fc)
-{
- gtk_color_button_get_color (color_button, &fc->color);
-}
-
-static GtkWidget *
-get_widget (FilterElement *fe)
-{
- FilterColour *fc = (FilterColour *) fe;
- GtkWidget *color_button;
-
- color_button = gtk_color_button_new_with_color (&fc->color);
- gtk_widget_show (color_button);
-
- g_signal_connect (
- G_OBJECT (color_button), "color_set",
- G_CALLBACK (set_color), fe);
-
- return color_button;
-}
-
-static void
-build_code (FilterElement *fe, GString *out, struct _FilterPart *ff)
-{
- return;
-}
-
-static void
-format_sexp (FilterElement *fe, GString *out)
-{
- FilterColour *fc = (FilterColour *)fe;
- gchar spec[16];
-
- g_snprintf (spec, sizeof (spec), "#%04x%04x%04x",
- fc->color.red, fc->color.green, fc->color.blue);
- e_sexp_encode_string (out, spec);
-}
diff --git a/filter/filter-colour.h b/filter/filter-colour.h
deleted file mode 100644
index cfd10d12a6..0000000000
--- a/filter/filter-colour.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _FILTER_COLOUR_H
-#define _FILTER_COLOUR_H
-
-#include "filter-element.h"
-
-#define FILTER_TYPE_COLOUR (filter_colour_get_type ())
-#define FILTER_COLOUR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FILTER_TYPE_COLOUR, FilterColour))
-#define FILTER_COLOUR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FILTER_TYPE_COLOUR, FilterColourClass))
-#define IS_FILTER_COLOUR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FILTER_TYPE_COLOUR))
-#define IS_FILTER_COLOUR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FILTER_TYPE_COLOUR))
-#define FILTER_COLOUR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FILTER_TYPE_COLOUR, FilterColourClass))
-
-typedef struct _FilterColour FilterColour;
-typedef struct _FilterColourClass FilterColourClass;
-
-struct _FilterColour {
- FilterElement parent_object;
-
- GdkColor color;
-};
-
-struct _FilterColourClass {
- FilterElementClass parent_class;
-
- /* virtual methods */
-
- /* signals */
-};
-
-GType filter_colour_get_type (void);
-FilterColour *filter_colour_new (void);
-
-/* methods */
-
-#endif /* ! _FILTER_COLOUR_H */
diff --git a/filter/filter-datespec.h b/filter/filter-datespec.h
deleted file mode 100644
index c8eee1bae7..0000000000
--- a/filter/filter-datespec.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _FILTER_DATESPEC_H
-#define _FILTER_DATESPEC_H
-
-#include <time.h>
-#include "filter-element.h"
-
-#define FILTER_TYPE_DATESPEC (filter_datespec_get_type ())
-#define FILTER_DATESPEC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FILTER_TYPE_DATESPEC, FilterDatespec))
-#define FILTER_DATESPEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FILTER_TYPE_DATESPEC, FilterDatespecClass))
-#define IS_FILTER_DATESPEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FILTER_TYPE_DATESPEC))
-#define IS_FILTER_DATESPEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FILTER_TYPE_DATESPEC))
-#define FILTER_DATESPEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FILTER_TYPE_DATESPEC, FilterDatespecClass))
-
-typedef struct _FilterDatespec FilterDatespec;
-typedef struct _FilterDatespecClass FilterDatespecClass;
-
-typedef enum _FilterDatespec_type {
- FDST_UNKNOWN = -1,
- FDST_NOW,
- FDST_SPECIFIED,
- FDST_X_AGO,
- FDST_X_FUTURE
-} FilterDatespec_type;
-
-struct _FilterDatespec {
- FilterElement parent;
- struct _FilterDatespecPrivate *priv;
-
- FilterDatespec_type type;
-
- /* either a timespan, an absolute time, or 0
- * depending on type -- the above mapping to
- * (X_FUTURE, X_AGO, SPECIFIED, NOW)
- */
-
- time_t value;
-};
-
-struct _FilterDatespecClass {
- FilterElementClass parent_class;
-
- /* virtual methods */
-
- /* signals */
-};
-
-GType filter_datespec_get_type (void);
-FilterDatespec *filter_datespec_new (void);
-
-/* methods */
-
-#endif /* ! _FILTER_DATESPEC_H */
diff --git a/filter/filter-element.c b/filter/filter-element.c
deleted file mode 100644
index 952805e48b..0000000000
--- a/filter/filter-element.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "filter-element.h"
-
-struct _element_type {
- gchar *name;
-
- FilterElementFunc create;
- gpointer data;
-};
-
-static gboolean validate (FilterElement *fe, GtkWindow *error_parent);
-static gint element_eq(FilterElement *fe, FilterElement *cm);
-static void xml_create(FilterElement *fe, xmlNodePtr node);
-static FilterElement *clone(FilterElement *fe);
-static void copy_value(FilterElement *de, FilterElement *se);
-
-static void filter_element_class_init (FilterElementClass *klass);
-static void filter_element_init (FilterElement *fe);
-static void filter_element_finalise (GObject *obj);
-
-static GObjectClass *parent_class = NULL;
-
-GType
-filter_element_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (FilterElementClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) filter_element_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (FilterElement),
- 0, /* n_preallocs */
- (GInstanceInitFunc) filter_element_init,
- };
- type = g_type_register_static (G_TYPE_OBJECT, "FilterElement", &info, 0);
- }
-
- return type;
-}
-
-static void
-filter_element_class_init (FilterElementClass *klass)
-{
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
- ((GObjectClass *)klass)->finalize = filter_element_finalise;
-
- /* override methods */
- klass->validate = validate;
- klass->eq = element_eq;
- klass->xml_create = xml_create;
- klass->clone = clone;
- klass->copy_value = copy_value;
-}
-
-static void
-filter_element_init (FilterElement *fe)
-{
- ;
-}
-
-static void
-filter_element_finalise (GObject *obj)
-{
- FilterElement *o = (FilterElement *)obj;
-
- xmlFree (o->name);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-/**
- * filter_element_new:
- *
- * Create a new FilterElement object.
- *
- * Return value: A new #FilterElement object.
- **/
-FilterElement *
-filter_element_new (void)
-{
- return (FilterElement *) g_object_new (FILTER_TYPE_ELEMENT, NULL, NULL);
-}
-
-gboolean
-filter_element_validate (FilterElement *fe, GtkWindow *error_parent)
-{
- return FILTER_ELEMENT_GET_CLASS (fe)->validate (fe, error_parent);
-}
-
-gint
-filter_element_eq (FilterElement *fe, FilterElement *cm)
-{
- FilterElementClass *klass;
-
- klass = FILTER_ELEMENT_GET_CLASS (fe);
- return (klass == FILTER_ELEMENT_GET_CLASS (cm)) && klass->eq (fe, cm);
-}
-
-/**
- * filter_element_xml_create:
- * @fe: filter element
- * @node: xml node
- *
- * Create a new filter element based on an xml definition of
- * that element.
- **/
-void
-filter_element_xml_create (FilterElement *fe, xmlNodePtr node)
-{
- FILTER_ELEMENT_GET_CLASS (fe)->xml_create (fe, node);
-}
-
-/**
- * filter_element_xml_encode:
- * @fe: filter element
- *
- * Encode the values of a filter element into xml format.
- *
- * Return value:
- **/
-xmlNodePtr
-filter_element_xml_encode (FilterElement *fe)
-{
- return FILTER_ELEMENT_GET_CLASS (fe)->xml_encode (fe);
-}
-
-/**
- * filter_element_xml_decode:
- * @fe: filter element
- * @node: xml node
- *
- * Decode the values of a fitler element from xml format.
- *
- * Return value:
- **/
-gint
-filter_element_xml_decode (FilterElement *fe, xmlNodePtr node)
-{
- return FILTER_ELEMENT_GET_CLASS (fe)->xml_decode (fe, node);
-}
-
-/**
- * filter_element_clone:
- * @fe: filter element
- *
- * Clones the FilterElement @fe.
- *
- * Return value:
- **/
-FilterElement *
-filter_element_clone (FilterElement *fe)
-{
- return FILTER_ELEMENT_GET_CLASS (fe)->clone (fe);
-}
-
-/**
- * filter_element_get_widget:
- * @fe: filter element
- * @node: xml node
- *
- * Create a widget to represent this element.
- *
- * Return value:
- **/
-GtkWidget *
-filter_element_get_widget (FilterElement *fe)
-{
- return FILTER_ELEMENT_GET_CLASS (fe)->get_widget (fe);
-}
-
-/**
- * filter_element_build_code:
- * @fe: filter element
- * @out: output buffer
- * @ff:
- *
- * Add the code representing this element to the output string @out.
- **/
-void
-filter_element_build_code (FilterElement *fe, GString *out, struct _FilterPart *ff)
-{
- FILTER_ELEMENT_GET_CLASS (fe)->build_code (fe, out, ff);
-}
-
-/**
- * filter_element_format_sexp:
- * @fe: filter element
- * @out: output buffer
- *
- * Format the value(s) of this element in a method suitable for the context of
- * sexp where it is used. Usually as space separated, double-quoted strings.
- **/
-void
-filter_element_format_sexp (FilterElement *fe, GString *out)
-{
- FILTER_ELEMENT_GET_CLASS (fe)->format_sexp (fe, out);
-}
-
-void
-filter_element_set_data (FilterElement *fe, gpointer data)
-{
- fe->data = data;
-}
-
-/* default implementations */
-static gboolean
-validate (FilterElement *fe, GtkWindow *error_parent)
-{
- return TRUE;
-}
-
-static gint
-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)
-{
- fe->name = (gchar *)xmlGetProp (node, (const guchar *)"name");
-}
-
-static FilterElement *
-clone (FilterElement *fe)
-{
- xmlNodePtr node;
- FilterElement *new;
-
- new = (FilterElement *) g_object_new (G_OBJECT_TYPE (fe), NULL, NULL);
- node = filter_element_xml_encode (fe);
- filter_element_xml_decode (new, node);
- xmlFreeNodeList (node);
-
- return new;
-}
-
-/* This is somewhat hackish, implement all the base cases in here */
-#include "filter-input.h"
-#include "filter-option.h"
-#include "filter-code.h"
-#include "filter-colour.h"
-#include "filter-datespec.h"
-#include "filter-int.h"
-#include "filter-file.h"
-
-static void
-copy_value(FilterElement *de, FilterElement *se)
-{
- if (IS_FILTER_INPUT(se)) {
- if (IS_FILTER_INPUT(de)) {
- if (((FilterInput *)se)->values)
- filter_input_set_value((FilterInput*)de, ((FilterInput *)se)->values->data);
- } else if (IS_FILTER_INT(de)) {
- ((FilterInt *)de)->val = atoi((gchar *) ((FilterInput *)se)->values->data);
- }
- } else if (IS_FILTER_COLOUR(se)) {
- if (IS_FILTER_COLOUR(de)) {
- FilterColour *s = (FilterColour *)se;
- FilterColour *d = (FilterColour *)de;
-
- d->color = s->color;
- }
- } else if (IS_FILTER_DATESPEC(se)) {
- if (IS_FILTER_DATESPEC(de)) {
- FilterDatespec *s = (FilterDatespec *)se, *d = (FilterDatespec *)de;
-
- d->type = s->type;
- d->value = s->value;
- }
- } else if (IS_FILTER_INT(se)) {
- if (IS_FILTER_INT(de)) {
- FilterInt *s = (FilterInt *)se, *d = (FilterInt *)de;
-
- d->val = s->val;
- } else if (IS_FILTER_INPUT(de)) {
- FilterInt *s = (FilterInt *)se;
- FilterInput *d = (FilterInput *)de;
- gchar *v;
-
- v = g_strdup_printf("%d", s->val);
- filter_input_set_value(d, v);
- g_free(v);
- }
- } else if (IS_FILTER_OPTION(se)) {
- if (IS_FILTER_OPTION(de)) {
- FilterOption *s = (FilterOption *)se, *d = (FilterOption *)de;
-
- if (s->current)
- filter_option_set_current(d, s->current->value);
- }
- }
-}
-
-/* only copies the value, not the name/type */
-void
-filter_element_copy_value (FilterElement *de, FilterElement *se)
-{
- FILTER_ELEMENT_GET_CLASS (de)->copy_value(de, se);
-}
diff --git a/filter/filter-element.h b/filter/filter-element.h
deleted file mode 100644
index 9bcb3f98df..0000000000
--- a/filter/filter-element.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _FILTER_ELEMENT_H
-#define _FILTER_ELEMENT_H
-
-#include <gtk/gtk.h>
-#include <libxml/parser.h>
-#include <libxml/xmlmemory.h>
-
-#define FILTER_TYPE_ELEMENT (filter_element_get_type ())
-#define FILTER_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FILTER_TYPE_ELEMENT, FilterElement))
-#define FILTER_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FILTER_TYPE_ELEMENT, FilterElementClass))
-#define IS_FILTER_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FILTER_TYPE_ELEMENT))
-#define IS_FILTER_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FILTER_TYPE_ELEMENT))
-#define FILTER_ELEMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FILTER_TYPE_ELEMENT, FilterElementClass))
-
-typedef struct _FilterElement FilterElement;
-typedef struct _FilterElementClass FilterElementClass;
-
-typedef FilterElement *(*FilterElementFunc)(gpointer data);
-
-struct _FilterElement {
- GObject parent_object;
-
- gchar *name;
- gpointer data;
-};
-
-struct _FilterPart;
-
-struct _FilterElementClass {
- GObjectClass parent_class;
-
- /* virtual methods */
- gboolean (*validate) (FilterElement *fe, GtkWindow *error_parent);
- gint (*eq) (FilterElement *fe, FilterElement *cm);
-
- void (*xml_create) (FilterElement *, xmlNodePtr);
- xmlNodePtr (*xml_encode) (FilterElement *);
- gint (*xml_decode) (FilterElement *, xmlNodePtr);
-
- FilterElement *(*clone) (FilterElement *fe);
- void (*copy_value)(FilterElement *fe, FilterElement *se);
-
- GtkWidget *(*get_widget) (FilterElement *);
- void (*build_code) (FilterElement *, GString *, struct _FilterPart *ff);
- void (*format_sexp) (FilterElement *, GString *);
-
- /* signals */
-};
-
-GType filter_element_get_type (void);
-FilterElement *filter_element_new (void);
-
-void filter_element_set_data (FilterElement *fe, gpointer data);
-
-/* methods */
-gboolean filter_element_validate (FilterElement *fe, GtkWindow *error_parent);
-gint filter_element_eq (FilterElement *fe, FilterElement *cm);
-
-void filter_element_xml_create (FilterElement *fe, xmlNodePtr node);
-
-xmlNodePtr filter_element_xml_encode (FilterElement *fe);
-gint filter_element_xml_decode (FilterElement *fe, xmlNodePtr node);
-FilterElement *filter_element_clone (FilterElement *fe);
-void filter_element_copy_value (FilterElement *de, FilterElement *se);
-
-GtkWidget *filter_element_get_widget (FilterElement *fe);
-void filter_element_build_code (FilterElement *fe, GString *out, struct _FilterPart *ff);
-void filter_element_format_sexp (FilterElement *fe, GString *out);
-
-#endif /* ! _FILTER_ELEMENT_H */
diff --git a/filter/filter-file.c b/filter/filter-file.c
deleted file mode 100644
index b541022554..0000000000
--- a/filter/filter-file.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#include <config.h>
-
-#include <string.h>
-#include <sys/types.h>
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-#include <glib/gstdio.h>
-
-#include <libedataserver/e-sexp.h>
-
-#include "e-util/e-error.h"
-
-#include "filter-file.h"
-
-#define d(x)
-
-static gboolean validate (FilterElement *fe, GtkWindow *error_parent);
-static gint file_eq (FilterElement *fe, FilterElement *cm);
-static void xml_create (FilterElement *fe, xmlNodePtr node);
-static xmlNodePtr xml_encode (FilterElement *fe);
-static gint 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 *, GString *);
-
-static void filter_file_class_init (FilterFileClass *klass);
-static void filter_file_init (FilterFile *ff);
-static void filter_file_finalise (GObject *obj);
-
-static FilterElementClass *parent_class = NULL;
-
-GType
-filter_file_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (FilterFileClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) filter_file_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (FilterFile),
- 0, /* n_preallocs */
- (GInstanceInitFunc) filter_file_init,
- };
-
- type = g_type_register_static (FILTER_TYPE_ELEMENT, "FilterFile", &info, 0);
- }
-
- return type;
-}
-
-static void
-filter_file_class_init (FilterFileClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- FilterElementClass *fe_class = FILTER_ELEMENT_CLASS (klass);
-
- parent_class = g_type_class_ref (FILTER_TYPE_ELEMENT);
-
- object_class->finalize = filter_file_finalise;
-
- /* override methods */
- fe_class->validate = validate;
- fe_class->eq = file_eq;
- fe_class->xml_create = xml_create;
- fe_class->xml_encode = xml_encode;
- fe_class->xml_decode = xml_decode;
- fe_class->get_widget = get_widget;
- fe_class->build_code = build_code;
- fe_class->format_sexp = format_sexp;
-}
-
-static void
-filter_file_init (FilterFile *ff)
-{
- ;
-}
-
-static void
-filter_file_finalise (GObject *obj)
-{
- FilterFile *ff = (FilterFile *) obj;
-
- xmlFree (ff->type);
- g_free (ff->path);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-/**
- * filter_file_new:
- *
- * Create a new FilterFile object.
- *
- * Return value: A new #FilterFile object.
- **/
-FilterFile *
-filter_file_new (void)
-{
- return (FilterFile *) g_object_new (FILTER_TYPE_FILE, NULL, NULL);
-}
-
-FilterFile *
-filter_file_new_type_name (const gchar *type)
-{
- FilterFile *file;
-
- file = filter_file_new ();
- file->type = (gchar *)xmlStrdup ((xmlChar *)type);
-
- return file;
-}
-
-void
-filter_file_set_path (FilterFile *file, const gchar *path)
-{
- g_free (file->path);
- file->path = g_strdup (path);
-}
-
-static gboolean
-validate (FilterElement *fe, GtkWindow *error_parent)
-{
- FilterFile *file = (FilterFile *) fe;
-
- if (!file->path) {
- e_error_run (error_parent, "filter:no-file", NULL);
-
- return FALSE;
- }
-
- /* FIXME: do more to validate command-lines? */
-
- if (strcmp (file->type, "file") == 0) {
- if (!g_file_test (file->path, G_FILE_TEST_IS_REGULAR)) {
- e_error_run (error_parent, "filter:bad-file", file->path, NULL);
-
- return FALSE;
- }
- } else if (strcmp (file->type, "command") == 0) {
- /* only requirements so far is that the command can't
- be an empty string */
- return file->path[0] != '\0';
- }
-
- return TRUE;
-}
-
-static gint
-file_eq (FilterElement *fe, FilterElement *cm)
-{
- FilterFile *ff = (FilterFile *)fe, *cf = (FilterFile *)cm;
-
- return FILTER_ELEMENT_CLASS (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)
-{
- /* parent implementation */
- FILTER_ELEMENT_CLASS (parent_class)->xml_create (fe, node);
-}
-
-static xmlNodePtr
-xml_encode (FilterElement *fe)
-{
- FilterFile *file = (FilterFile *) fe;
- xmlNodePtr cur, value;
- const gchar *type;
-
- type = file->type ? file->type : "file";
-
- d(printf ("Encoding %s as xml\n", type));
-
- value = xmlNewNode (NULL, (const guchar *)"value");
- xmlSetProp (value, (const guchar *)"name", (guchar *)fe->name);
- xmlSetProp (value, (const guchar *)"type", (guchar *)type);
-
- cur = xmlNewChild (value, NULL, (guchar *)type, NULL);
- xmlNodeSetContent (cur, (guchar *)file->path);
-
- return value;
-}
-
-static gint
-xml_decode (FilterElement *fe, xmlNodePtr node)
-{
- FilterFile *file = (FilterFile *)fe;
- gchar *name, *str, *type;
- xmlNodePtr n;
-
- name = (gchar *)xmlGetProp (node, (const guchar *)"name");
- type = (gchar *)xmlGetProp (node, (const guchar *)"type");
-
- d(printf("Decoding %s from xml %p\n", type, fe));
- d(printf ("Name = %s\n", name));
-
- xmlFree (fe->name);
- fe->name = name;
- xmlFree (file->type);
- file->type = type;
-
- g_free (file->path);
- file->path = NULL;
-
- n = node->children;
- while (n != NULL) {
- if (!strcmp ((gchar *)n->name, type)) {
- str = (gchar *)xmlNodeGetContent (n);
- file->path = g_strdup (str ? str : "");
- xmlFree (str);
-
- d(printf (" '%s'\n", file->path));
- break;
- } else if (n->type == XML_ELEMENT_NODE) {
- g_warning ("Unknown node type '%s' encountered decoding a %s\n", n->name, type);
- }
-
- n = n->next;
- }
-
- return 0;
-}
-
-static void
-filename_changed (GtkWidget *widget, FilterElement *fe)
-{
- FilterFile *file = (FilterFile *) fe;
- const gchar *new;
-
- new = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
- g_free (file->path);
- file->path = g_strdup (new);
-}
-
-static GtkWidget *
-get_widget (FilterElement *fe)
-{
- FilterFile *file = (FilterFile *) fe;
- GtkWidget *filewidget;
-
- filewidget = (GtkWidget *) gtk_file_chooser_button_new (_("Choose a file"), GTK_FILE_CHOOSER_ACTION_OPEN);
- gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (filewidget), file->path);
- g_signal_connect (GTK_FILE_CHOOSER_BUTTON (filewidget), "selection-changed",
- G_CALLBACK (filename_changed), fe);
- return filewidget;
-}
-
-static void
-build_code (FilterElement *fe, GString *out, struct _FilterPart *ff)
-{
- return;
-}
-
-static void
-format_sexp (FilterElement *fe, GString *out)
-{
- FilterFile *file = (FilterFile *) fe;
-
- e_sexp_encode_string (out, file->path);
-}
diff --git a/filter/filter-file.h b/filter/filter-file.h
deleted file mode 100644
index af8d05fe7a..0000000000
--- a/filter/filter-file.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- *
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef __FILTER_FILE_H__
-#define __FILTER_FILE_H__
-
-G_BEGIN_DECLS
-
-#include "filter-element.h"
-
-#define FILTER_TYPE_FILE (filter_file_get_type ())
-#define FILTER_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FILTER_TYPE_FILE, FilterFile))
-#define FILTER_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FILTER_TYPE_FILE, FilterFileClass))
-#define IS_FILTER_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FILTER_TYPE_FILE))
-#define IS_FILTER_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FILTER_TYPE_FILE))
-#define FILTER_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FILTER_TYPE_FILE, FilterFileClass))
-
-typedef struct _FilterFile FilterFile;
-typedef struct _FilterFileClass FilterFileClass;
-
-struct _FilterFile {
- FilterElement parent_object;
-
- gchar *type;
- gchar *path;
-};
-
-struct _FilterFileClass {
- FilterElementClass parent_class;
-
- /* virtual methods */
-
- /* signals */
-};
-
-GType filter_file_get_type (void);
-
-FilterFile *filter_file_new (void);
-
-FilterFile *filter_file_new_type_name (const gchar *type);
-
-/* methods */
-void filter_file_set_path (FilterFile *file, const gchar *path);
-
-G_END_DECLS
-
-#endif /* ! __FILTER_FILE_H__ */
diff --git a/filter/filter-input.c b/filter/filter-input.c
deleted file mode 100644
index 31f74d991f..0000000000
--- a/filter/filter-input.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <sys/types.h>
-#include <regex.h>
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-
-#include "filter-input.h"
-#include "libedataserver/e-sexp.h"
-#include "e-util/e-error.h"
-
-#define d(x)
-
-static gboolean validate (FilterElement *fe, GtkWindow *error_parent);
-static gint input_eq (FilterElement *fe, FilterElement *cm);
-static void xml_create (FilterElement *fe, xmlNodePtr node);
-static xmlNodePtr xml_encode (FilterElement *fe);
-static gint 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 *, GString *);
-
-static void filter_input_class_init (FilterInputClass *klass);
-static void filter_input_init (FilterInput *fi);
-static void filter_input_finalise (GObject *obj);
-
-static FilterElementClass *parent_class = NULL;
-
-GType
-filter_input_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (FilterInputClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) filter_input_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (FilterInput),
- 0, /* n_preallocs */
- (GInstanceInitFunc) filter_input_init,
- };
-
- type = g_type_register_static (FILTER_TYPE_ELEMENT, "FilterInput", &info, 0);
- }
-
- return type;
-}
-
-static void
-filter_input_class_init (FilterInputClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- FilterElementClass *fe_class = FILTER_ELEMENT_CLASS (klass);
-
- parent_class = g_type_class_ref (FILTER_TYPE_ELEMENT);
-
- object_class->finalize = filter_input_finalise;
-
- /* override methods */
- fe_class->validate = validate;
- fe_class->eq = input_eq;
- fe_class->xml_create = xml_create;
- fe_class->xml_encode = xml_encode;
- fe_class->xml_decode = xml_decode;
- fe_class->get_widget = get_widget;
- fe_class->build_code = build_code;
- fe_class->format_sexp = format_sexp;
-}
-
-static void
-filter_input_init (FilterInput *fi)
-{
- fi->values = g_list_prepend (NULL, g_strdup (""));
-}
-
-static void
-filter_input_finalise (GObject *obj)
-{
- FilterInput *fi = (FilterInput *) obj;
-
- xmlFree (fi->type);
- g_list_foreach (fi->values, (GFunc)g_free, NULL);
- g_list_free (fi->values);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-/**
- * filter_input_new:
- *
- * Create a new FilterInput object.
- *
- * Return value: A new #FilterInput object.
- **/
-FilterInput *
-filter_input_new (void)
-{
- return (FilterInput *) g_object_new (FILTER_TYPE_INPUT, NULL, NULL);
-}
-
-FilterInput *
-filter_input_new_type_name (const gchar *type)
-{
- FilterInput *fi;
-
- fi = filter_input_new ();
- fi->type = (gchar *)xmlStrdup ((xmlChar *)type);
-
- d(printf("new type %s = %p\n", type, fi));
-
- return fi;
-}
-
-void
-filter_input_set_value (FilterInput *fi, const gchar *value)
-{
- GList *l;
-
- d(printf("set_value '%s'\n", value));
-
- l = fi->values;
- while (l) {
- g_free (l->data);
- l = g_list_next (l);
- }
- g_list_free (fi->values);
-
- fi->values = g_list_append (NULL, g_strdup (value));
-}
-
-static gboolean
-validate (FilterElement *fe, GtkWindow *error_parent)
-{
- FilterInput *fi = (FilterInput *)fe;
- gboolean valid = TRUE;
-
- if (fi->values && !strcmp (fi->type, "regex")) {
- const gchar *pattern;
- regex_t regexpat;
- gint regerr;
-
- pattern = fi->values->data;
-
- if ((regerr = regcomp (&regexpat, pattern, REG_EXTENDED | REG_NEWLINE | REG_ICASE))) {
- gsize reglen;
- gchar *regmsg;
-
- /* regerror gets called twice to get the full error string
- length to do proper posix error reporting */
- reglen = regerror (regerr, &regexpat, 0, 0);
- regmsg = g_malloc0 (reglen + 1);
- regerror (regerr, &regexpat, regmsg, reglen);
-
- e_error_run (error_parent, "filter:bad-regexp", pattern, regmsg, NULL);
- g_free (regmsg);
-
- valid = FALSE;
- }
-
- regfree (&regexpat);
- }
-
- return valid;
-}
-
-static gint
-list_eq (GList *al, GList *bl)
-{
- gint truth = TRUE;
-
- while (truth && al && bl) {
- truth = strcmp ((gchar *) al->data, (gchar *) bl->data) == 0;
- al = al->next;
- bl = bl->next;
- }
-
- return truth && al == NULL && bl == NULL;
-}
-
-static gint
-input_eq (FilterElement *fe, FilterElement *cm)
-{
- FilterInput *fi = (FilterInput *)fe, *ci = (FilterInput *)cm;
-
- return FILTER_ELEMENT_CLASS (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)
-{
- /* parent implementation */
- FILTER_ELEMENT_CLASS (parent_class)->xml_create (fe, node);
-}
-
-static xmlNodePtr
-xml_encode (FilterElement *fe)
-{
- xmlNodePtr value;
- GList *l;
- FilterInput *fi = (FilterInput *)fe;
- const gchar *type;
-
- type = fi->type ? fi->type : "string";
-
- d(printf ("Encoding %s as xml\n", type));
-
- value = xmlNewNode (NULL, (const guchar *)"value");
- xmlSetProp (value, (const guchar *)"name", (guchar *)fe->name);
- xmlSetProp (value, (const guchar *)"type", (guchar *)type);
- l = fi->values;
- while (l) {
- xmlNodePtr cur;
- xmlChar *str = l->data;
-
- cur = xmlNewChild (value, NULL, (guchar *)type, NULL);
-
- str = xmlEncodeEntitiesReentrant (NULL, str);
- xmlNodeSetContent (cur, str);
- xmlFree (str);
-
- l = l->next;
- }
-
- return value;
-}
-
-static gint
-xml_decode (FilterElement *fe, xmlNodePtr node)
-{
- FilterInput *fi = (FilterInput *)fe;
- gchar *name, *str, *type;
- xmlNodePtr n;
- GList *l;
-
- l = fi->values;
- while (l) {
- g_free (l->data);
- l = l->next;
- }
- g_list_free (fi->values);
- fi->values = NULL;
-
- name = (gchar *)xmlGetProp (node, (const guchar *)"name");
- type = (gchar *)xmlGetProp (node, (const guchar *)"type");
-
- d(printf("Decoding %s from xml %p\n", type, fe));
- d(printf ("Name = %s\n", name));
- xmlFree (fe->name);
- fe->name = name;
- xmlFree (fi->type);
- fi->type = type;
- n = node->children;
- while (n) {
- if (!strcmp ((gchar *)n->name, type)) {
- if (!(str = (gchar *)xmlNodeGetContent (n)))
- str = (gchar *)xmlStrdup ((const guchar *)"");
-
- d(printf (" '%s'\n", str));
- fi->values = g_list_append (fi->values, g_strdup (str));
- xmlFree (str);
- } else if (n->type == XML_ELEMENT_NODE) {
- g_warning ("Unknown node type '%s' encountered decoding a %s\n", n->name, type);
- }
- n = n->next;
- }
-
- return 0;
-}
-
-static void
-entry_changed (GtkEntry *entry, FilterElement *fe)
-{
- FilterInput *fi = (FilterInput *) fe;
- const gchar *new;
- GList *l;
-
- new = gtk_entry_get_text (entry);
-
- d(printf("entry_changed '%s'\n", new));
-
- /* NOTE: entry only supports a single value ... */
- l = fi->values;
- while (l) {
- g_free (l->data);
- l = l->next;
- }
-
- g_list_free (fi->values);
-
- fi->values = g_list_append (NULL, g_strdup (new));
-}
-
-static GtkWidget *
-get_widget (FilterElement *fe)
-{
- GtkWidget *entry;
- FilterInput *fi = (FilterInput *)fe;
-
- entry = gtk_entry_new ();
- if (fi->values && fi->values->data)
- gtk_entry_set_text (GTK_ENTRY (entry), (const gchar *) fi->values->data);
-
- g_signal_connect (entry, "changed", G_CALLBACK (entry_changed), fe);
-
- return entry;
-}
-
-static void
-build_code (FilterElement *fe, GString *out, struct _FilterPart *ff)
-{
- ;
-}
-
-static void
-format_sexp (FilterElement *fe, GString *out)
-{
- FilterInput *fi = (FilterInput *) fe;
- GList *l;
-
- d(printf("format_sexp, first elem=%p\n", fi->values));
-
- l = fi->values;
- while (l) {
- e_sexp_encode_string (out, l->data);
- l = l->next;
- }
-}
diff --git a/filter/filter-input.h b/filter/filter-input.h
deleted file mode 100644
index 9a5e181eaa..0000000000
--- a/filter/filter-input.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _FILTER_INPUT_H
-#define _FILTER_INPUT_H
-
-#include "filter-element.h"
-
-#define FILTER_TYPE_INPUT (filter_input_get_type ())
-#define FILTER_INPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FILTER_TYPE_INPUT, FilterInput))
-#define FILTER_INPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FILTER_TYPE_INPUT, FilterInputClass))
-#define IS_FILTER_INPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FILTER_TYPE_INPUT))
-#define IS_FILTER_INPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FILTER_TYPE_INPUT))
-#define FILTER_INPUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FILTER_TYPE_INPUT, FilterInputClass))
-
-typedef struct _FilterInput FilterInput;
-typedef struct _FilterInputClass FilterInputClass;
-
-struct _FilterInput {
- FilterElement parent_object;
-
- gchar *type; /* name of type */
- GList *values; /* strings */
-};
-
-struct _FilterInputClass {
- FilterElementClass parent_class;
-
- /* virtual methods */
-
- /* signals */
-};
-
-GType filter_input_get_type (void);
-FilterInput *filter_input_new (void);
-
-FilterInput *filter_input_new_type_name (const gchar *type);
-
-/* methods */
-void filter_input_set_value (FilterInput *fi, const gchar *value);
-
-#endif /* ! _FILTER_INPUT_H */
diff --git a/filter/filter-int.c b/filter/filter-int.c
deleted file mode 100644
index ab8208e45e..0000000000
--- a/filter/filter-int.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <gtk/gtk.h>
-
-#include <libedataserver/e-sexp.h>
-#include "filter-int.h"
-
-#define d(x)
-
-static gint int_eq (FilterElement *fe, FilterElement *cm);
-static FilterElement *int_clone(FilterElement *fe);
-static void xml_create (FilterElement *fe, xmlNodePtr node);
-static xmlNodePtr xml_encode (FilterElement *fe);
-static gint 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_int_class_init (FilterIntClass *klass);
-static void filter_int_init (FilterInt *fi);
-static void filter_int_finalise (GObject *obj);
-
-static FilterElementClass *parent_class;
-
-GType
-filter_int_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (FilterIntClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) filter_int_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (FilterInt),
- 0, /* n_preallocs */
- (GInstanceInitFunc) filter_int_init,
- };
-
- type = g_type_register_static (FILTER_TYPE_ELEMENT, "FilterInt", &info, 0);
- }
-
- return type;
-}
-
-static void
-filter_int_class_init (FilterIntClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- FilterElementClass *fe_class = FILTER_ELEMENT_CLASS (klass);
-
- parent_class = g_type_class_ref (FILTER_TYPE_ELEMENT);
-
- object_class->finalize = filter_int_finalise;
-
- /* override methods */
- fe_class->eq = int_eq;
- fe_class->clone = int_clone;
- fe_class->xml_create = xml_create;
- fe_class->xml_encode = xml_encode;
- fe_class->xml_decode = xml_decode;
- fe_class->get_widget = get_widget;
- fe_class->build_code = build_code;
- fe_class->format_sexp = format_sexp;
-}
-
-static void
-filter_int_init (FilterInt *fi)
-{
- fi->min = 0;
- fi->max = G_MAXINT;
-}
-
-static void
-filter_int_finalise (GObject *obj)
-{
- FilterInt *fi = (FilterInt *) obj;
-
- g_free (fi->type);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-/**
- * filter_int_new:
- *
- * Create a new FilterInt object.
- *
- * Return value: A new #FilterInt object.
- **/
-FilterInt *
-filter_int_new (void)
-{
- return (FilterInt *) g_object_new (FILTER_TYPE_INT, NULL, NULL);
-}
-
-FilterInt *
-filter_int_new_type (const gchar *type, gint min, gint max)
-{
- FilterInt *fi;
-
- fi = filter_int_new ();
-
- fi->type = g_strdup (type);
- fi->min = min;
- fi->max = max;
-
- return fi;
-}
-
-void
-filter_int_set_value (FilterInt *fi, gint val)
-{
- fi->val = val;
-}
-
-static gint
-int_eq (FilterElement *fe, FilterElement *cm)
-{
- return FILTER_ELEMENT_CLASS (parent_class)->eq (fe, cm)
- && ((FilterInt *)fe)->val == ((FilterInt *)cm)->val;
-}
-
-static FilterElement *
-int_clone(FilterElement *fe)
-{
- FilterInt *fi, *fs;
-
- fs = (FilterInt *)fe;
- fi = filter_int_new_type(fs->type, fs->min, fs->max);
- fi->val = fs->val;
- ((FilterElement *)fi)->name = g_strdup(fe->name);
-
- return (FilterElement *)fi;
-}
-
-static void
-xml_create (FilterElement *fe, xmlNodePtr node)
-{
- /* parent implementation */
- FILTER_ELEMENT_CLASS (parent_class)->xml_create (fe, node);
-}
-
-static xmlNodePtr
-xml_encode (FilterElement *fe)
-{
- xmlNodePtr value;
- FilterInt *fs = (FilterInt *)fe;
- gchar intval[32];
- const gchar *type;
-
- type = fs->type?fs->type:"integer";
-
- d(printf("Encoding %s as xml\n", type));
-
- value = xmlNewNode (NULL, (const guchar *)"value");
- xmlSetProp (value, (const guchar *)"name", (guchar *)fe->name);
- xmlSetProp (value, (const guchar *)"type", (guchar *)type);
-
- sprintf(intval, "%d", fs->val);
- xmlSetProp (value, (guchar *)type, (guchar *)intval);
-
- return value;
-}
-
-static gint
-xml_decode (FilterElement *fe, xmlNodePtr node)
-{
- FilterInt *fs = (FilterInt *)fe;
- gchar *name, *type;
- gchar *intval;
-
- d(printf("Decoding integer from xml %p\n", fe));
-
- name = (gchar *)xmlGetProp (node, (const guchar *)"name");
- d(printf ("Name = %s\n", name));
- xmlFree (fe->name);
- fe->name = name;
-
- type = (gchar *)xmlGetProp(node, (const guchar *)"type");
- d(printf ("Type = %s\n", type));
- g_free(fs->type);
- fs->type = g_strdup(type);
- xmlFree(type);
-
- intval = (gchar *)xmlGetProp (node, (guchar *)(fs->type ? fs->type : "integer"));
- if (intval) {
- d(printf ("Value = %s\n", intval));
- fs->val = atoi (intval);
- xmlFree (intval);
- } else {
- d(printf ("Value = ?unknown?\n"));
- fs->val = 0;
- }
-
- return 0;
-}
-
-static void
-spin_changed (GtkWidget *spin, FilterElement *fe)
-{
- FilterInt *fs = (FilterInt *)fe;
-
- fs->val = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin));
-}
-
-static GtkWidget *
-get_widget (FilterElement *fe)
-{
- GtkWidget *spin;
- GtkObject *adjustment;
- FilterInt *fs = (FilterInt *)fe;
-
- adjustment = gtk_adjustment_new (0.0, (gfloat)fs->min, (gfloat)fs->max, 1.0, 1.0, 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)
- gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), (gfloat) fs->val);
-
- g_signal_connect (spin, "value-changed", G_CALLBACK (spin_changed), fe);
-
- return spin;
-}
-
-static void
-build_code (FilterElement *fe, GString *out, struct _FilterPart *ff)
-{
- return;
-}
-
-static void
-format_sexp (FilterElement *fe, GString *out)
-{
- FilterInt *fs = (FilterInt *)fe;
-
- if (fs->val < 0)
- /* See #364731 #457523 C6*/
- g_string_append_printf (out, "(- %d)", (fs->val * -1));
- else
- g_string_append_printf (out, "%d", fs->val);
-}
diff --git a/filter/filter-int.h b/filter/filter-int.h
deleted file mode 100644
index 4167bc8cf3..0000000000
--- a/filter/filter-int.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _FILTER_INT_H
-#define _FILTER_INT_H
-
-#include "filter-element.h"
-
-#define FILTER_TYPE_INT (filter_int_get_type ())
-#define FILTER_INT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FILTER_TYPE_INT, FilterInt))
-#define FILTER_INT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FILTER_TYPE_INT, FilterIntClass))
-#define IS_FILTER_INT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FILTER_TYPE_INT))
-#define IS_FILTER_INT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FILTER_TYPE_INT))
-#define FILTER_INT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FILTER_TYPE_INT, FilterIntClass))
-
-typedef struct _FilterInt FilterInt;
-typedef struct _FilterIntClass FilterIntClass;
-
-struct _FilterInt {
- FilterElement parent_object;
-
- gchar *type;
- gint val;
- gint min;
- gint max;
-};
-
-struct _FilterIntClass {
- FilterElementClass parent_class;
-
- /* virtual methods */
-
- /* signals */
-};
-
-GType filter_int_get_type (void);
-FilterInt *filter_int_new (void);
-FilterInt *filter_int_new_type (const gchar *type, gint min, gint max);
-void filter_int_set_value (FilterInt *fi, gint val);
-
-/* methods */
-
-#endif /* ! _FILTER_INT_H */
diff --git a/filter/filter-option.c b/filter/filter-option.c
deleted file mode 100644
index 14bb796ff6..0000000000
--- a/filter/filter-option.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-#include <gmodule.h>
-
-#include "filter-option.h"
-#include "filter-part.h"
-#include <libedataserver/e-sexp.h>
-
-#define d(x)
-
-static gint option_eq (FilterElement *fe, FilterElement *cm);
-static void xml_create (FilterElement *fe, xmlNodePtr node);
-static xmlNodePtr xml_encode (FilterElement *fe);
-static gint xml_decode (FilterElement *fe, xmlNodePtr node);
-static FilterElement *clone (FilterElement *fe);
-static GtkWidget *get_widget (FilterElement *fe);
-static void build_code (FilterElement *fe, GString *out, struct _FilterPart *ff);
-static void format_sexp (FilterElement *, GString *);
-static GSList *get_dynamic_options (FilterOption *fo);
-
-static void filter_option_class_init (FilterOptionClass *klass);
-static void filter_option_init (FilterOption *fo);
-static void filter_option_finalise (GObject *obj);
-
-static FilterElementClass *parent_class;
-
-GType
-filter_option_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (FilterOptionClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) filter_option_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (FilterOption),
- 0, /* n_preallocs */
- (GInstanceInitFunc) filter_option_init,
- };
-
- type = g_type_register_static (FILTER_TYPE_ELEMENT, "FilterOption", &info, 0);
- }
-
- return type;
-}
-
-static void
-filter_option_class_init (FilterOptionClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- FilterElementClass *fe_class = FILTER_ELEMENT_CLASS (klass);
-
- parent_class = g_type_class_ref (FILTER_TYPE_ELEMENT);
-
- object_class->finalize = filter_option_finalise;
-
- /* override methods */
- fe_class->eq = option_eq;
- fe_class->xml_create = xml_create;
- fe_class->xml_encode = xml_encode;
- fe_class->xml_decode = xml_decode;
- fe_class->clone = clone;
- fe_class->get_widget = get_widget;
- fe_class->build_code = build_code;
- fe_class->format_sexp = format_sexp;
-}
-
-static void
-filter_option_init (FilterOption *fo)
-{
- fo->type = "option";
- fo->dynamic_func = NULL;
-}
-
-static void
-free_option (struct _filter_option *o, gpointer data)
-{
- g_free (o->title);
- g_free (o->value);
- g_free (o->code);
- g_free (o);
-}
-
-static void
-filter_option_finalise (GObject *obj)
-{
- FilterOption *fo = (FilterOption *) obj;
-
- g_list_foreach (fo->options, (GFunc)free_option, NULL);
- g_list_free (fo->options);
- g_free (fo->dynamic_func);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-/**
- * filter_option_new:
- *
- * Create a new FilterOption object.
- *
- * Return value: A new #FilterOption object.
- **/
-FilterOption *
-filter_option_new (void)
-{
- return (FilterOption *) g_object_new (FILTER_TYPE_OPTION, NULL, NULL);
-}
-
-static struct _filter_option *
-find_option (FilterOption *fo, const gchar *name)
-{
- GList *l = fo->options;
- struct _filter_option *op;
-
- while (l) {
- op = l->data;
- if (!strcmp (name, op->value)) {
- return op;
- }
- l = g_list_next (l);
- }
-
- return NULL;
-}
-
-void
-filter_option_set_current (FilterOption *option, const gchar *name)
-{
- g_return_if_fail (IS_FILTER_OPTION(option));
-
- option->current = find_option (option, name);
-}
-
-/* used by implementers to add additional options */
-struct _filter_option *
-filter_option_add(FilterOption *fo, const gchar *value, const gchar *title, const gchar *code, gboolean is_dynamic)
-{
- struct _filter_option *op;
-
- g_return_val_if_fail (IS_FILTER_OPTION(fo), NULL);
- g_return_val_if_fail(find_option(fo, value) == NULL, NULL);
-
- op = g_malloc(sizeof(*op));
- op->title = g_strdup(title);
- op->value = g_strdup(value);
- op->code = g_strdup(code);
- op->is_dynamic = is_dynamic;
-
- fo->options = g_list_append(fo->options, op);
- if (fo->current == NULL)
- fo->current = op;
-
- return op;
-}
-
-const gchar *
-filter_option_get_current (FilterOption *option)
-{
- g_return_val_if_fail (IS_FILTER_OPTION (option), NULL);
-
- if (!option->current)
- return NULL;
-
- return option->current->value;
-}
-
-void
-filter_option_remove_all (FilterOption *fo)
-{
- g_return_if_fail (IS_FILTER_OPTION (fo));
-
- g_list_foreach (fo->options, (GFunc)free_option, NULL);
- g_list_free (fo->options);
- fo->options = NULL;
-
- fo->current = NULL;
-}
-
-static gint
-option_eq(FilterElement *fe, FilterElement *cm)
-{
- FilterOption *fo = (FilterOption *)fe, *co = (FilterOption *)cm;
-
- return FILTER_ELEMENT_CLASS (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)
-{
- FilterOption *fo = (FilterOption *)fe;
- xmlNodePtr n, work;
-
- /* parent implementation */
- FILTER_ELEMENT_CLASS (parent_class)->xml_create (fe, node);
-
- n = node->children;
- while (n) {
- if (!strcmp ((gchar *)n->name, "option")) {
- gchar *tmp, *value, *title = NULL, *code = NULL;
-
- value = (gchar *)xmlGetProp (n, (const guchar *)"value");
- work = n->children;
- while (work) {
- if (!strcmp ((gchar *)work->name, "title") || !strcmp ((gchar *)work->name, "_title")) {
- if (!title) {
- if (!(tmp = (gchar *)xmlNodeGetContent (work)))
- tmp = (gchar *)xmlStrdup ((const guchar *)"");
-
- title = g_strdup (tmp);
- xmlFree (tmp);
- }
- } else if (!strcmp ((gchar *)work->name, "code")) {
- if (!code) {
- if (!(tmp = (gchar *)xmlNodeGetContent (work)))
- tmp = (gchar *)xmlStrdup ((const guchar *)"");
-
- code = g_strdup (tmp);
- xmlFree (tmp);
- }
- }
- work = work->next;
- }
-
- filter_option_add (fo, value, title, code, FALSE);
- xmlFree (value);
- g_free (title);
- g_free (code);
- } else if (g_str_equal ((gchar *)n->name, "dynamic")) {
- if (fo->dynamic_func) {
- g_warning ("Only one 'dynamic' node is acceptable in the optionlist '%s'", fe->name);
- } else {
- /* Expecting only one <dynamic func="cb" /> in the option list,
- The 'cb' should be of this prototype:
- GSList *cb (void);
- returning GSList of struct _filter_option, all newly allocated, because it'll
- be freed with g_free and g_slist_free. 'is_dynamic' member is ignored here.
- */
- xmlChar *fn;
-
- fn = xmlGetProp (n, (const guchar *)"func");
- if (fn && *fn) {
- GSList *items, *i;
- struct _filter_option *op;
-
- fo->dynamic_func = g_strdup ((const gchar *)fn);
-
- /* get options now, to have them available when reading saved rules */
- items = get_dynamic_options (fo);
- for (i = items; i; i = i->next) {
- op = i->data;
-
- if (op) {
- filter_option_add (fo, op->value, op->title, op->code, TRUE);
- free_option (op, NULL);
- }
- }
-
- g_slist_free (items);
- } else {
- g_warning ("Missing 'func' attribute within '%s' node in optionlist '%s'", n->name, fe->name);
- }
-
- xmlFree (fn);
- }
- } else if (n->type == XML_ELEMENT_NODE) {
- g_warning ("Unknown xml node within optionlist: %s\n", n->name);
- }
- n = n->next;
- }
-}
-
-static xmlNodePtr
-xml_encode (FilterElement *fe)
-{
- xmlNodePtr value;
- FilterOption *fo = (FilterOption *)fe;
-
- d(printf ("Encoding option as xml\n"));
- value = xmlNewNode (NULL, (const guchar *)"value");
- xmlSetProp (value, (const guchar *)"name", (guchar *)fe->name);
- xmlSetProp (value, (const guchar *)"type", (guchar *)fo->type);
- if (fo->current)
- xmlSetProp (value, (const guchar *)"value", (guchar *)fo->current->value);
-
- return value;
-}
-
-static gint
-xml_decode (FilterElement *fe, xmlNodePtr node)
-{
- FilterOption *fo = (FilterOption *)fe;
- gchar *value;
-
- d(printf ("Decoding option from xml\n"));
- xmlFree (fe->name);
- fe->name = (gchar *)xmlGetProp (node, (const guchar *)"name");
- value = (gchar *)xmlGetProp (node, (const guchar *)"value");
- if (value) {
- fo->current = find_option (fo, value);
- xmlFree (value);
- } else {
- fo->current = NULL;
- }
- return 0;
-}
-
-static void
-combobox_changed (GtkWidget *widget, FilterElement *fe)
-{
- FilterOption *fo = (FilterOption *)fe;
-
- fo->current = (struct _filter_option *) g_list_nth_data (fo->options, gtk_combo_box_get_active (GTK_COMBO_BOX (widget)));
-}
-
-static GSList *
-get_dynamic_options (FilterOption *fo)
-{
- GModule *module;
- GSList *(*get_func)(void);
- GSList *res = NULL;
-
- if (!fo || !fo->dynamic_func)
- return res;
-
- module = g_module_open (NULL, G_MODULE_BIND_LAZY);
-
- if (g_module_symbol (module, fo->dynamic_func, (gpointer) &get_func)) {
- res = get_func ();
- } else {
- g_warning ("optionlist dynamic fill function '%s' not found", fo->dynamic_func);
- }
-
- g_module_close (module);
-
- return res;
-}
-
-static GtkWidget *
-get_widget (FilterElement *fe)
-{
- FilterOption *fo = (FilterOption *)fe;
- GtkWidget *combobox;
- GList *l;
- struct _filter_option *op;
- gint index = 0, current = 0;
-
- if (fo->dynamic_func) {
- /* it is dynamically filled, thus remove all dynamics and put there the fresh ones */
- GSList *items, *i;
- GList *old_ops;
- struct _filter_option *old_cur;
-
- old_ops = fo->options;
- old_cur = fo->current;
- l = old_ops;
-
- /* start with an empty list */
- fo->current = NULL;
- fo->options = NULL;
-
- for (l = fo->options; l; l = l->next) {
- op = l->data;
-
- if (op->is_dynamic) {
- break;
- } else {
- filter_option_add (fo, op->value, op->title, op->code, FALSE);
- }
- }
-
- items = get_dynamic_options (fo);
- for (i = items; i; i = i->next) {
- op = i->data;
-
- if (op) {
- filter_option_add (fo, op->value, op->title, op->code, TRUE);
- free_option (op, NULL);
- }
- }
-
- g_slist_free (items);
-
- /* maybe some static left after those dynamic, add them too */
- for (; l; l = l->next) {
- op = l->data;
-
- if (!op->is_dynamic)
- filter_option_add (fo, op->value, op->title, op->code, FALSE);
- }
-
- if (old_cur)
- filter_option_set_current (fo, old_cur->value);
-
- /* free old list */
- g_list_foreach (old_ops, (GFunc)free_option, NULL);
- g_list_free (old_ops);
- }
-
- combobox = gtk_combo_box_new_text ();
- l = fo->options;
- while (l) {
- op = l->data;
- gtk_combo_box_append_text (GTK_COMBO_BOX (combobox), _(op->title));
-
- if (op == fo->current)
- current = index;
-
- l = g_list_next (l);
- index++;
- }
-
- g_signal_connect (combobox, "changed", G_CALLBACK (combobox_changed), fe);
- gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), current);
-
- return combobox;
-}
-
-static void
-build_code (FilterElement *fe, GString *out, struct _FilterPart *ff)
-{
- FilterOption *fo = (FilterOption *)fe;
-
- d(printf ("building option code %p, current = %p\n", fo, fo->current));
-
- if (fo->current && fo->current->code)
- filter_part_expand_code (ff, fo->current->code, out);
-}
-
-static void
-format_sexp (FilterElement *fe, GString *out)
-{
- FilterOption *fo = (FilterOption *)fe;
-
- if (fo->current)
- e_sexp_encode_string (out, fo->current->value);
-}
-
-static FilterElement *
-clone (FilterElement *fe)
-{
- FilterOption *fo = (FilterOption *)fe, *new;
- GList *l;
- struct _filter_option *op, *newop;
-
- d(printf ("cloning option\n"));
-
- new = FILTER_OPTION (FILTER_ELEMENT_CLASS (parent_class)->clone (fe));
- l = fo->options;
- while (l) {
- op = l->data;
- newop = filter_option_add (new, op->value, op->title, op->code, op->is_dynamic);
- if (fo->current == op)
- new->current = newop;
- l = l->next;
- }
-
- new->dynamic_func = g_strdup (fo->dynamic_func);
-
- d(printf ("cloning option code %p, current = %p\n", new, new->current));
-
- return (FilterElement *) new;
-}
diff --git a/filter/filter-option.h b/filter/filter-option.h
deleted file mode 100644
index 9fa1670951..0000000000
--- a/filter/filter-option.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _FILTER_OPTION_H
-#define _FILTER_OPTION_H
-
-#include "filter-element.h"
-
-#define FILTER_TYPE_OPTION (filter_option_get_type ())
-#define FILTER_OPTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FILTER_TYPE_OPTION, FilterOption))
-#define FILTER_OPTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FILTER_TYPE_OPTION, FilterOptionClass))
-#define IS_FILTER_OPTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FILTER_TYPE_OPTION))
-#define IS_FILTER_OPTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FILTER_TYPE_OPTION))
-#define FILTER_OPTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FILTER_TYPE_OPTION, FilterOptionClass))
-
-typedef struct _FilterOption FilterOption;
-typedef struct _FilterOptionClass FilterOptionClass;
-
-struct _filter_option {
- gchar *title; /* button title */
- gchar *value; /* value, if it has one */
- gchar *code; /* used to string code segments together */
-
- gboolean is_dynamic; /* whether is the option dynamic, FALSE if static */
-};
-
-struct _FilterOption {
- FilterElement parent_object;
-
- const gchar *type; /* static memory, type name written to xml */
-
- GList *options;
- struct _filter_option *current;
- gchar *dynamic_func; /* name of the dynamic fill func, called in get_widget */
-};
-
-struct _FilterOptionClass {
- FilterElementClass parent_class;
-
- /* virtual methods */
-
- /* signals */
-};
-
-GType filter_option_get_type (void);
-FilterOption *filter_option_new (void);
-
-/* methods */
-void filter_option_set_current (FilterOption *option, const gchar *name);
-const gchar *filter_option_get_current (FilterOption *option);
-
-struct _filter_option *filter_option_add (FilterOption *fo, const gchar *name, const gchar *title, const gchar *code, gboolean is_dynamic);
-void filter_option_remove_all (FilterOption *fo);
-
-#endif /* ! _FILTER_OPTION_H */
diff --git a/filter/filter-part.c b/filter/filter-part.c
deleted file mode 100644
index d59796a2cc..0000000000
--- a/filter/filter-part.c
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-
-#include "filter-part.h"
-#include "rule-context.h"
-#include "filter-file.h"
-
-#define d(x)
-
-static void filter_part_class_init (FilterPartClass *klass);
-static void filter_part_init (FilterPart *fp);
-static void filter_part_finalise (GObject *obj);
-
-static GObjectClass *parent_class = NULL;
-
-GType
-filter_part_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (FilterPartClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) filter_part_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (FilterPart),
- 0, /* n_preallocs */
- (GInstanceInitFunc) filter_part_init,
- };
-
- type = g_type_register_static (G_TYPE_OBJECT, "FilterPart", &info, 0);
- }
-
- return type;
-}
-
-static void
-filter_part_class_init (FilterPartClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
- object_class->finalize = filter_part_finalise;
-}
-
-static void
-filter_part_init (FilterPart *fp)
-{
- ;
-}
-
-static void
-filter_part_finalise (GObject *obj)
-{
- FilterPart *fp = (FilterPart *) obj;
- GList *l;
-
- l = fp->elements;
- while (l) {
- g_object_unref (l->data);
- l = l->next;
- }
-
- g_list_free (fp->elements);
- g_free (fp->name);
- g_free (fp->title);
- g_free (fp->code);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-/**
- * filter_part_new:
- *
- * Create a new FilterPart object.
- *
- * Return value: A new #FilterPart object.
- **/
-FilterPart *
-filter_part_new (void)
-{
- return (FilterPart *) g_object_new (FILTER_TYPE_PART, NULL, NULL);
-}
-
-gboolean
-filter_part_validate (FilterPart *fp, GtkWindow *error_parent)
-{
- gboolean correct = TRUE;
- GList *l;
-
- l = fp->elements;
- while (l && correct) {
- FilterElement *fe = l->data;
-
- correct = filter_element_validate (fe, error_parent);
-
- l = l->next;
- }
-
- return correct;
-}
-
-gint
-filter_part_eq (FilterPart *fp, FilterPart *fc)
-{
- gint 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;
-}
-
-gint
-filter_part_xml_create (FilterPart *ff, xmlNodePtr node, RuleContext *rc)
-{
- xmlNodePtr n;
- gchar *type, *str;
- FilterElement *el;
-
- str = (gchar *)xmlGetProp (node, (const guchar *)"name");
- ff->name = g_strdup (str);
- if (str)
- xmlFree (str);
-
- n = node->children;
- while (n) {
- if (!strcmp ((gchar *)n->name, "input")) {
- type = (gchar *)xmlGetProp (n, (const guchar *)"type");
- d(printf ("creating new element type input '%s'\n", type));
- if (type != NULL
- && (el = rule_context_new_element(rc, type)) != NULL) {
- filter_element_xml_create (el, n);
- xmlFree (type);
- d(printf ("adding element part %p %s\n", ff, el, el->name));
- ff->elements = g_list_append (ff->elements, el);
- } else {
- g_warning ("Invalid xml format, missing/unknown input type");
- }
- } else if (!strcmp ((gchar *)n->name, "title") || !strcmp ((gchar *)n->name, "_title")) {
- if (!ff->title) {
- str = (gchar *)xmlNodeGetContent (n);
- ff->title = g_strdup (str);
- if (str)
- xmlFree (str);
- }
- } else if (!strcmp ((gchar *)n->name, "code")) {
- if (!ff->code) {
- str = (gchar *)xmlNodeGetContent (n);
- ff->code = g_strdup (str);
- if (str)
- xmlFree (str);
- }
- } else if (n->type == XML_ELEMENT_NODE) {
- g_warning ("Unknown part element in xml: %s\n", n->name);
- }
- n = n->next;
- }
-
- return 0;
-}
-
-xmlNodePtr
-filter_part_xml_encode (FilterPart *fp)
-{
- GList *l;
- FilterElement *fe;
- xmlNodePtr part, value;
-
- g_return_val_if_fail (fp != NULL, NULL);
-
- part = xmlNewNode (NULL, (const guchar *)"part");
- xmlSetProp (part, (const guchar *)"name", (guchar *)fp->name);
- l = fp->elements;
- while (l) {
- fe = l->data;
- value = filter_element_xml_encode (fe);
- xmlAddChild (part, value);
- l = g_list_next (l);
- }
-
- return part;
-}
-
-gint
-filter_part_xml_decode (FilterPart *fp, xmlNodePtr node)
-{
- FilterElement *fe;
- xmlNodePtr n;
- gchar *name;
-
- g_return_val_if_fail (fp != NULL, -1);
- g_return_val_if_fail (node != NULL, -1);
-
- n = node->children;
- while (n) {
- if (!strcmp ((gchar *)n->name, "value")) {
- name = (gchar *)xmlGetProp (n, (const guchar *)"name");
- d(printf ("finding element part %p %s = %p\n", name, name, fe));
- fe = filter_part_find_element (fp, name);
- d(printf ("finding element part %p %s = %p\n", name, name, fe));
- xmlFree (name);
- if (fe)
- filter_element_xml_decode (fe, n);
- }
- n = n->next;
- }
-
- return 0;
-}
-
-FilterPart *
-filter_part_clone (FilterPart *fp)
-{
- FilterPart *new;
- GList *l;
- FilterElement *fe, *ne;
-
- new = (FilterPart *) g_object_new (G_OBJECT_TYPE (fp), NULL, NULL);
- new->name = g_strdup (fp->name);
- new->title = g_strdup (fp->title);
- new->code = g_strdup (fp->code);
- l = fp->elements;
- while (l) {
- fe = l->data;
- ne = filter_element_clone (fe);
- new->elements = g_list_append (new->elements, ne);
- l = g_list_next (l);
- }
-
- return new;
-}
-
-/* only copies values of matching parts in the right order */
-void
-filter_part_copy_values (FilterPart *dst, FilterPart *src)
-{
- GList *dstl, *srcl, *dstt;
- FilterElement *de, *se;
-
- /* NOTE: we go backwards, it just works better that way */
-
- /* for each source type, search the dest type for
- a matching type in the same order */
- srcl = g_list_last (src->elements);
- dstl = g_list_last (dst->elements);
- while (srcl && dstl) {
- se = srcl->data;
- dstt = dstl;
- while (dstt) {
- de = dstt->data;
- if (FILTER_PART_GET_CLASS (de) == FILTER_PART_GET_CLASS (se)) {
- filter_element_copy_value (de, se);
- dstl = dstt->prev;
- break;
- }
- dstt = dstt->prev;
- }
-
- srcl = srcl->prev;
- }
-}
-
-FilterElement *
-filter_part_find_element (FilterPart *ff, const gchar *name)
-{
- GList *l = ff->elements;
- FilterElement *fe;
-
- if (name == NULL)
- return NULL;
-
- while (l) {
- fe = l->data;
- if (fe->name && !strcmp (fe->name, name))
- return fe;
- l = g_list_next (l);
- }
-
- return NULL;
-}
-
-GtkWidget *
-filter_part_get_widget (FilterPart *ff)
-{
- GtkWidget *hbox;
- GList *l = ff->elements;
- FilterElement *fe;
- GtkWidget *w;
-
- hbox = gtk_hbox_new (FALSE, 3);
-
- while (l) {
- fe = l->data;
- w = filter_element_get_widget (fe);
- if (w)
- gtk_box_pack_start (GTK_BOX (hbox), w, IS_FILTER_FILE (fe), IS_FILTER_FILE (fe), 3);
-
- l = g_list_next (l);
- }
-
- gtk_widget_show_all (hbox);
-
- return hbox;
-}
-
-/**
- * filter_part_build_code:
- * @ff:
- * @out:
- *
- * Outputs the code of a part.
- **/
-void
-filter_part_build_code (FilterPart *ff, GString *out)
-{
- GList *l = ff->elements;
- FilterElement *fe;
-
- if (ff->code)
- filter_part_expand_code (ff, ff->code, out);
-
- while (l) {
- fe = l->data;
- filter_element_build_code (fe, out, ff);
- l = l->next;
- }
-}
-
-/**
- * filter_part_build_code_list:
- * @l:
- * @out:
- *
- * Construct a list of the filter parts code into
- * a single string.
- **/
-void
-filter_part_build_code_list (GList *l, GString *out)
-{
- FilterPart *fp;
-
- while (l) {
- fp = l->data;
- filter_part_build_code (fp, out);
- g_string_append (out, "\n ");
- l = l->next;
- }
-}
-
-/**
- * filter_part_find_list:
- * @l:
- * @name:
- *
- * Find a filter part stored in a list.
- *
- * Return value:
- **/
-FilterPart *
-filter_part_find_list (GList *l, const gchar *name)
-{
- FilterPart *part;
-
- d(printf ("Find part named %s\n", name));
-
- while (l) {
- part = l->data;
- if (!strcmp (part->name, name)) {
- d(printf ("Found!\n"));
- return part;
- }
- l = l->next;
- }
-
- return NULL;
-}
-
-/**
- * filter_part_next_list:
- * @l:
- * @last: The last item retrieved, or NULL to start
- * from the beginning of the list.
- *
- * Iterate through a filter part list.
- *
- * Return value: The next value in the list, or NULL if the
- * list is expired.
- **/
-FilterPart *
-filter_part_next_list (GList *l, FilterPart *last)
-{
- GList *node = l;
-
- if (last != NULL) {
- node = g_list_find (node, last);
- if (node == NULL)
- node = l;
- else
- node = node->next;
- }
-
- if (node)
- return node->data;
-
- return NULL;
-}
-
-/**
- * filter_part_expand_code:
- * @ff:
- * @str:
- * @out:
- *
- * Expands the variables in string @str based on the values of the part.
- **/
-void
-filter_part_expand_code (FilterPart *ff, const gchar *source, GString *out)
-{
- const gchar *newstart, *start, *end;
- gchar *name = alloca (32);
- gint len, namelen = 32;
- FilterElement *fe;
-
- start = source;
- while (start && (newstart = strstr (start, "${"))
- && (end = strstr (newstart+2, "}")) ) {
- len = end - newstart - 2;
- if (len + 1 > namelen) {
- namelen = (len + 1) * 2;
- name = g_alloca (namelen);
- }
- memcpy (name, newstart+2, len);
- name[len] = 0;
- fe = filter_part_find_element (ff, name);
- d(printf("expand code: looking up variab le '%s' = %p\n", ff, name, fe));
- if (fe) {
- g_string_append_printf (out, "%.*s", (gint)(newstart-start), start);
- filter_element_format_sexp (fe, out);
-#if 0
- } else if ((val = g_hash_table_lookup (ff->globals, name))) {
- g_string_append_printf (out, "%.*s", newstart-start, start);
- e_sexp_encode_string (out, val);
-#endif
- } else {
- g_string_append_printf (out, "%.*s", (gint)(end-start+1), start);
- }
- start = end + 1;
- }
- g_string_append (out, start);
-}
-
-#if 0
-gint main(gint argc, gchar **argv)
-{
- GtkWidget *dialog, *w;
- xmlDocPtr system;
- xmlNodePtr node;
- FilterPart *ff;
- GString *code;
-
- gnome_init ("test", "0.0", argc, argv);
-
- system = xmlParseFile ("form.xml");
- if (system == NULL) {
- printf("i/o error\n");
- return 1;
- }
-
- ff = filter_part_new ();
- filter_part_xml_create (ff, system->root);
-
- w = filter_part_get_widget (ff);
-
- dialog = gtk_dialog_new ();
- gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_BUTTONS_OK, NULL);
- gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
- gtk_window_set_title (GTK_WINDOW (dialog), _("Test"));
- gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
- gtk_box_pack_start (GTK_BOX (dialog->vbox), w, TRUE, TRUE, 0);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-
- code = g_string_new ("");
- filter_part_build_code (ff, code);
- printf ("code is:\n%s\n", code->str);
-
- return 0;
-}
-#endif
diff --git a/filter/filter-part.h b/filter/filter-part.h
deleted file mode 100644
index 10e58979e7..0000000000
--- a/filter/filter-part.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _FILTER_PART_H
-#define _FILTER_PART_H
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gtk/gtk.h>
-
-#include "filter-input.h"
-
-struct _RuleContext;
-
-#define FILTER_TYPE_PART (filter_part_get_type ())
-#define FILTER_PART(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FILTER_TYPE_PART, FilterPart))
-#define FILTER_PART_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FILTER_TYPE_PART, FilterPartClass))
-#define IS_FILTER_PART(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FILTER_TYPE_PART))
-#define IS_FILTER_PART_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FILTER_TYPE_PART))
-#define FILTER_PART_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FILTER_TYPE_PART, FilterElementClass))
-
-typedef struct _FilterPart FilterPart;
-typedef struct _FilterPartClass FilterPartClass;
-
-struct _FilterPart {
- GObject parent_object;
- struct _FilterPartPrivate *priv;
-
- gchar *name;
- gchar *title;
- gchar *code;
- GList *elements;
-};
-
-struct _FilterPartClass {
- GObjectClass parent_class;
-
- /* virtual methods */
-
- /* signals */
-};
-
-GType filter_part_get_type (void);
-FilterPart *filter_part_new (void);
-
-/* methods */
-gboolean filter_part_validate (FilterPart *fp, GtkWindow *error_parent);
-gint filter_part_eq (FilterPart *fp, FilterPart *fc);
-
-gint filter_part_xml_create (FilterPart *ff, xmlNodePtr node, struct _RuleContext *rc);
-
-xmlNodePtr filter_part_xml_encode (FilterPart *fe);
-gint filter_part_xml_decode (FilterPart *fe, xmlNodePtr node);
-
-FilterPart *filter_part_clone (FilterPart *fp);
-void filter_part_copy_values (FilterPart *dfp, FilterPart *sfp);
-
-FilterElement *filter_part_find_element (FilterPart *ff, const gchar *name);
-
-GtkWidget *filter_part_get_widget (FilterPart *ff);
-void filter_part_build_code (FilterPart *ff, GString *out);
-void filter_part_expand_code (FilterPart *ff, const gchar *str, GString *out);
-
-/* static functions */
-void filter_part_build_code_list (GList *l, GString *out);
-FilterPart *filter_part_find_list (GList *l, const gchar *name);
-FilterPart *filter_part_next_list (GList *l, FilterPart *last);
-
-#endif /* ! _FILTER_PART_H */
diff --git a/filter/filter-rule.c b/filter/filter-rule.c
deleted file mode 100644
index 28cf83cb8a..0000000000
--- a/filter/filter-rule.c
+++ /dev/null
@@ -1,1044 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-
-#include "e-util/e-error.h"
-#include "filter-rule.h"
-#include "rule-context.h"
-
-#define d(x)
-
-static gint validate(FilterRule *, GtkWindow *error_parent);
-static gint rule_eq(FilterRule *fr, FilterRule *cm);
-static xmlNodePtr xml_encode (FilterRule *);
-static gint xml_decode (FilterRule *, xmlNodePtr, RuleContext *);
-static void build_code (FilterRule *, GString * out);
-static void rule_copy (FilterRule *dest, FilterRule *src);
-static GtkWidget *get_widget (FilterRule * fr, struct _RuleContext *f);
-
-static void filter_rule_class_init (FilterRuleClass *klass);
-static void filter_rule_init (FilterRule *fr);
-static void filter_rule_finalise (GObject *obj);
-
-#define _PRIVATE(x) (((FilterRule *)(x))->priv)
-
-struct _FilterRulePrivate {
- gint frozen;
-};
-
-static GObjectClass *parent_class = NULL;
-
-enum {
- CHANGED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-GType
-filter_rule_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (FilterRuleClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) filter_rule_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (FilterRule),
- 0, /* n_preallocs */
- (GInstanceInitFunc) filter_rule_init,
- };
-
- type = g_type_register_static (G_TYPE_OBJECT, "FilterRule", &info, 0);
- }
-
- return type;
-}
-
-static void
-filter_rule_class_init (FilterRuleClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
- object_class->finalize = filter_rule_finalise;
-
- /* override methods */
- klass->validate = validate;
- klass->eq = rule_eq;
- klass->xml_encode = xml_encode;
- klass->xml_decode = xml_decode;
- klass->build_code = build_code;
- klass->copy = rule_copy;
- klass->get_widget = get_widget;
-
- /* signals */
- signals[CHANGED] =
- g_signal_new ("changed",
- FILTER_TYPE_RULE,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (FilterRuleClass, changed),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-static void
-filter_rule_init (FilterRule *fr)
-{
- fr->priv = g_malloc0 (sizeof (*fr->priv));
- fr->enabled = TRUE;
-}
-
-static void
-filter_rule_finalise (GObject *obj)
-{
- FilterRule *fr = (FilterRule *) obj;
-
- g_free (fr->name);
- g_free (fr->source);
- g_list_foreach (fr->parts, (GFunc)g_object_unref, NULL);
- g_list_free (fr->parts);
-
- g_free (fr->priv);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-/**
- * filter_rule_new:
- *
- * Create a new FilterRule object.
- *
- * Return value: A new #FilterRule object.
- **/
-FilterRule *
-filter_rule_new (void)
-{
- return (FilterRule *) g_object_new (FILTER_TYPE_RULE, NULL, NULL);
-}
-
-FilterRule *
-filter_rule_clone (FilterRule *base)
-{
- FilterRule *rule;
-
- g_return_val_if_fail (IS_FILTER_RULE (base), NULL);
-
- rule = g_object_new (G_OBJECT_TYPE (base), NULL, NULL);
- filter_rule_copy (rule, base);
-
- return rule;
-}
-
-void
-filter_rule_set_name (FilterRule *fr, const gchar *name)
-{
- g_return_if_fail (IS_FILTER_RULE (fr));
-
- if ((fr->name && name && strcmp (fr->name, name) == 0)
- || (fr->name == NULL && name == NULL))
- return;
-
- g_free (fr->name);
- fr->name = g_strdup (name);
-
- filter_rule_emit_changed (fr);
-}
-
-void
-filter_rule_set_source (FilterRule *fr, const gchar *source)
-{
- g_return_if_fail (IS_FILTER_RULE (fr));
-
- if ((fr->source && source && strcmp (fr->source, source) == 0)
- || (fr->source == NULL && source == NULL))
- return;
-
- g_free (fr->source);
- fr->source = g_strdup (source);
-
- filter_rule_emit_changed (fr);
-}
-
-gint
-filter_rule_validate (FilterRule *fr, GtkWindow *error_parent)
-{
- g_return_val_if_fail (IS_FILTER_RULE (fr), 0);
-
- return FILTER_RULE_GET_CLASS (fr)->validate (fr, error_parent);
-}
-
-static gint
-validate (FilterRule *fr, GtkWindow *error_parent)
-{
- gint valid = TRUE;
- GList *parts;
-
- if (!fr->name || !*fr->name) {
- e_error_run (error_parent, "filter:no-name", NULL);
-
- return FALSE;
- }
-
- /* validate rule parts */
- parts = fr->parts;
- valid = parts != NULL;
- while (parts && valid) {
- valid = filter_part_validate ((FilterPart *) parts->data, error_parent);
- parts = parts->next;
- }
-
- return valid;
-}
-
-gint
-filter_rule_eq (FilterRule *fr, FilterRule *cm)
-{
- g_return_val_if_fail (IS_FILTER_RULE (fr), 0);
- g_return_val_if_fail (IS_FILTER_RULE (cm), 0);
-
- return (FILTER_RULE_GET_CLASS (fr) == FILTER_RULE_GET_CLASS (cm))
- && FILTER_RULE_GET_CLASS (fr)->eq (fr, cm);
-}
-
-static gint
-list_eq(GList *al, GList *bl)
-{
- gint 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 gint
-rule_eq (FilterRule *fr, FilterRule *cm)
-{
- return fr->enabled == cm->enabled
- && 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)
- || (fr->source == NULL && cm->source == NULL) )
- && list_eq (fr->parts, cm->parts);
-}
-
-xmlNodePtr
-filter_rule_xml_encode (FilterRule *fr)
-{
- g_return_val_if_fail (IS_FILTER_RULE (fr), NULL);
-
- return FILTER_RULE_GET_CLASS (fr)->xml_encode (fr);
-}
-
-static xmlNodePtr
-xml_encode (FilterRule *fr)
-{
- xmlNodePtr node, set, work;
- GList *l;
-
- node = xmlNewNode (NULL, (const guchar *)"rule");
-
- xmlSetProp (node, (const guchar *)"enabled", (const guchar *)(fr->enabled ? "true" : "false"));
-
- switch (fr->grouping) {
- case FILTER_GROUP_ALL:
- xmlSetProp (node, (const guchar *)"grouping", (const guchar *)"all");
- break;
- case FILTER_GROUP_ANY:
- xmlSetProp (node, (const guchar *)"grouping", (const guchar *)"any");
- break;
- }
-
- switch (fr->threading) {
- case FILTER_THREAD_NONE:
- break;
- case FILTER_THREAD_ALL:
- xmlSetProp(node, (const guchar *)"threading", (const guchar *)"all");
- break;
- case FILTER_THREAD_REPLIES:
- xmlSetProp(node, (const guchar *)"threading", (const guchar *)"replies");
- break;
- case FILTER_THREAD_REPLIES_PARENTS:
- xmlSetProp(node, (const guchar *)"threading", (const guchar *)"replies_parents");
- break;
- case FILTER_THREAD_SINGLE:
- xmlSetProp(node, (const guchar *)"threading", (const guchar *)"single");
- break;
- }
-
- if (fr->source) {
- xmlSetProp (node, (const guchar *)"source", (guchar *)fr->source);
- } else {
- /* set to the default filter type */
- xmlSetProp (node, (const guchar *)"source", (const guchar *)"incoming");
- }
-
- if (fr->name) {
- gchar *escaped = g_markup_escape_text (fr->name, -1);
-
- work = xmlNewNode (NULL, (const guchar *)"title");
- xmlNodeSetContent (work, (guchar *)escaped);
- xmlAddChild (node, work);
-
- g_free (escaped);
- }
-
- set = xmlNewNode (NULL, (const guchar *)"partset");
- xmlAddChild (node, set);
- l = fr->parts;
- while (l) {
- work = filter_part_xml_encode ((FilterPart *) l->data);
- xmlAddChild (set, work);
- l = l->next;
- }
-
- return node;
-}
-
-static void
-load_set (xmlNodePtr node, FilterRule *fr, RuleContext *f)
-{
- xmlNodePtr work;
- gchar *rulename;
- FilterPart *part;
-
- work = node->children;
- while (work) {
- if (!strcmp ((gchar *)work->name, "part")) {
- rulename = (gchar *)xmlGetProp (work, (const guchar *)"name");
- part = rule_context_find_part (f, rulename);
- if (part) {
- part = filter_part_clone (part);
- filter_part_xml_decode (part, work);
- filter_rule_add_part (fr, part);
- } else {
- g_warning ("cannot find rule part '%s'\n", rulename);
- }
- xmlFree (rulename);
- } else if (work->type == XML_ELEMENT_NODE) {
- g_warning ("Unknown xml node in part: %s", work->name);
- }
- work = work->next;
- }
-}
-
-gint
-filter_rule_xml_decode (FilterRule *fr, xmlNodePtr node, RuleContext *f)
-{
- gint res;
-
- g_return_val_if_fail (IS_FILTER_RULE (fr), 0);
- g_return_val_if_fail (IS_RULE_CONTEXT (f), 0);
- g_return_val_if_fail (node != NULL, 0);
-
- fr->priv->frozen++;
- res = FILTER_RULE_GET_CLASS (fr)->xml_decode (fr, node, f);
- fr->priv->frozen--;
-
- filter_rule_emit_changed (fr);
-
- return res;
-}
-
-static gint
-xml_decode (FilterRule *fr, xmlNodePtr node, RuleContext *f)
-{
- xmlNodePtr work;
- gchar *grouping;
- gchar *source;
-
- if (fr->name) {
- g_free (fr->name);
- fr->name = NULL;
- }
-
- grouping = (gchar *)xmlGetProp (node, (const guchar *)"enabled");
- if (!grouping)
- fr->enabled = TRUE;
- else {
- fr->enabled = strcmp (grouping, "false") != 0;
- xmlFree (grouping);
- }
-
- grouping = (gchar *)xmlGetProp (node, (const guchar *)"grouping");
- if (!strcmp (grouping, "any"))
- fr->grouping = FILTER_GROUP_ANY;
- else
- fr->grouping = FILTER_GROUP_ALL;
- xmlFree (grouping);
-
- fr->threading = FILTER_THREAD_NONE;
- if (f->flags & RULE_CONTEXT_THREADING
- && (grouping = (gchar *)xmlGetProp (node, (const guchar *)"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;
- else if (!strcmp(grouping, "single"))
- fr->threading = FILTER_THREAD_SINGLE;
- xmlFree (grouping);
- }
-
- g_free (fr->source);
- source = (gchar *)xmlGetProp (node, (const guchar *)"source");
- if (source) {
- fr->source = g_strdup (source);
- xmlFree (source);
- } else {
- /* default filter type */
- fr->source = g_strdup ("incoming");
- }
-
- work = node->children;
- while (work) {
- if (!strcmp ((gchar *)work->name, "partset")) {
- load_set (work, fr, f);
- } else if (!strcmp ((gchar *)work->name, "title") || !strcmp ((gchar *)work->name, "_title")) {
- if (!fr->name) {
- gchar *str, *decstr = NULL;
-
- str = (gchar *)xmlNodeGetContent (work);
- if (str) {
- decstr = g_strdup (_(str));
- xmlFree (str);
- }
- fr->name = decstr;
- }
- }
- work = work->next;
- }
-
- return 0;
-}
-
-static void
-rule_copy (FilterRule *dest, FilterRule *src)
-{
- GList *node;
-
- dest->enabled = src->enabled;
-
- g_free (dest->name);
- dest->name = g_strdup (src->name);
-
- g_free (dest->source);
- 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);
- dest->parts = NULL;
- }
-
- node = src->parts;
- while (node) {
- FilterPart *part;
-
- part = filter_part_clone (node->data);
- dest->parts = g_list_append (dest->parts, part);
- node = node->next;
- }
-}
-
-void
-filter_rule_copy (FilterRule *dest, FilterRule *src)
-{
- g_return_if_fail (IS_FILTER_RULE (dest));
- g_return_if_fail (IS_FILTER_RULE (src));
-
- FILTER_RULE_GET_CLASS (dest)->copy (dest, src);
-
- filter_rule_emit_changed (dest);
-}
-
-void
-filter_rule_add_part (FilterRule *fr, FilterPart *fp)
-{
- g_return_if_fail (IS_FILTER_RULE (fr));
- g_return_if_fail (IS_FILTER_PART (fp));
-
- fr->parts = g_list_append (fr->parts, fp);
-
- filter_rule_emit_changed (fr);
-}
-
-void
-filter_rule_remove_part (FilterRule *fr, FilterPart *fp)
-{
- g_return_if_fail (IS_FILTER_RULE (fr));
- g_return_if_fail (IS_FILTER_PART (fp));
-
- fr->parts = g_list_remove (fr->parts, fp);
-
- filter_rule_emit_changed (fr);
-}
-
-void
-filter_rule_replace_part (FilterRule *fr, FilterPart *fp, FilterPart *new)
-{
- GList *l;
-
- g_return_if_fail (IS_FILTER_RULE (fr));
- g_return_if_fail (IS_FILTER_PART (fp));
- g_return_if_fail (IS_FILTER_PART (new));
-
- l = g_list_find (fr->parts, fp);
- if (l) {
- l->data = new;
- } else {
- fr->parts = g_list_append (fr->parts, new);
- }
-
- filter_rule_emit_changed (fr);
-}
-
-void
-filter_rule_build_code (FilterRule *fr, GString *out)
-{
- g_return_if_fail (IS_FILTER_RULE (fr));
- g_return_if_fail (out != NULL);
-
- FILTER_RULE_GET_CLASS (fr)->build_code (fr, out);
-
- d(printf ("build_code: [%s](%d)", out->str, out->len));
-}
-
-void
-filter_rule_emit_changed(FilterRule *fr)
-{
- g_return_if_fail (IS_FILTER_RULE (fr));
-
- if (fr->priv->frozen == 0)
- g_signal_emit (fr, signals[CHANGED], 0);
-}
-
-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;
- case FILTER_THREAD_SINGLE:
- g_string_append(out, " (match-threads \"single\" ");
- break;
- }
-
- switch (fr->grouping) {
- case FILTER_GROUP_ALL:
- g_string_append (out, " (and\n ");
- break;
- case FILTER_GROUP_ANY:
- g_string_append (out, " (or\n ");
- break;
- default:
- g_warning ("Invalid grouping");
- }
-
- 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
-fr_grouping_changed(GtkWidget *w, FilterRule *fr)
-{
- fr->grouping = gtk_combo_box_get_active (GTK_COMBO_BOX (w));
-}
-
-static void
-fr_threading_changed(GtkWidget *w, FilterRule *fr)
-{
- fr->threading = gtk_combo_box_get_active (GTK_COMBO_BOX (w));
-}
-
-struct _part_data {
- FilterRule *fr;
- RuleContext *f;
- FilterPart *part;
- GtkWidget *partwidget, *container;
-};
-
-static void
-part_combobox_changed (GtkComboBox *combobox, struct _part_data *data)
-{
- FilterPart *part = NULL;
- FilterPart *newpart;
- gint index, i;
-
- index = gtk_combo_box_get_active (combobox);
- for (i = 0, part = rule_context_next_part (data->f, part); part && i < index; i++, part = rule_context_next_part (data->f, part)) {
- /* traverse until reached index */
- }
-
- g_return_if_fail (part != NULL);
- g_return_if_fail (i == index);
-
- /* dont update if we haven't changed */
- if (!strcmp (part->title, data->part->title))
- return;
-
- /* here we do a widget shuffle, throw away the old widget/rulepart,
- and create another */
- if (data->partwidget)
- gtk_container_remove (GTK_CONTAINER (data->container), data->partwidget);
-
- newpart = filter_part_clone (part);
- filter_part_copy_values (newpart, data->part);
- filter_rule_replace_part (data->fr, data->part, newpart);
- g_object_unref (data->part);
- data->part = newpart;
- data->partwidget = filter_part_get_widget (newpart);
- if (data->partwidget)
- gtk_box_pack_start (GTK_BOX (data->container), data->partwidget, TRUE, TRUE, 0);
-}
-
-static GtkWidget *
-get_rule_part_widget (RuleContext *f, FilterPart *newpart, FilterRule *fr)
-{
- FilterPart *part = NULL;
- GtkWidget *combobox;
- GtkWidget *hbox;
- GtkWidget *p;
- gint index = 0, current = 0;
- struct _part_data *data;
-
- data = g_malloc0 (sizeof (*data));
- data->fr = fr;
- data->f = f;
- data->part = newpart;
-
- hbox = gtk_hbox_new (FALSE, 0);
- /* only set to automatically clean up the memory */
- g_object_set_data_full ((GObject *) hbox, "data", data, g_free);
-
- p = filter_part_get_widget (newpart);
-
- data->partwidget = p;
- data->container = hbox;
-
- combobox = gtk_combo_box_new_text ();
-
- /* sigh, this is a little ugly */
- while ((part = rule_context_next_part (f, part))) {
- gtk_combo_box_append_text (GTK_COMBO_BOX (combobox), _(part->title));
-
- if (!strcmp (newpart->title, part->title))
- current = index;
-
- index++;
- }
-
- gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), current);
- g_signal_connect (combobox, "changed", G_CALLBACK (part_combobox_changed), data);
- gtk_widget_show (combobox);
-
- gtk_box_pack_start (GTK_BOX (hbox), combobox, FALSE, FALSE, 0);
- if (p)
- gtk_box_pack_start (GTK_BOX (hbox), p, TRUE, TRUE, 0);
-
- gtk_widget_show_all (hbox);
-
- return hbox;
-}
-
-struct _rule_data {
- FilterRule *fr;
- RuleContext *f;
- GtkWidget *parts;
-};
-
-static void
-less_parts (GtkWidget *button, struct _rule_data *data)
-{
- FilterPart *part;
- GtkWidget *rule;
- struct _part_data *part_data;
-
- if (g_list_length (data->fr->parts) < 1)
- return;
-
- rule = g_object_get_data ((GObject *) button, "rule");
- part_data = g_object_get_data ((GObject *) rule, "data");
-
- g_return_if_fail (part_data != NULL);
-
- part = part_data->part;
-
- /* remove the part from the list */
- filter_rule_remove_part (data->fr, part);
- g_object_unref (part);
-
- /* and from the display */
- gtk_container_remove (GTK_CONTAINER (data->parts), rule);
- gtk_container_remove (GTK_CONTAINER (data->parts), button);
-}
-
-static void
-attach_rule (GtkWidget *rule, struct _rule_data *data, FilterPart *part, gint row)
-{
- GtkWidget *remove;
-
- gtk_table_attach (GTK_TABLE (data->parts), rule, 0, 1, row, row + 1,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
-
- remove = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
- g_object_set_data ((GObject *) remove, "rule", rule);
- /*gtk_button_set_relief (GTK_BUTTON (remove), GTK_RELIEF_NONE);*/
- g_signal_connect (remove, "clicked", G_CALLBACK (less_parts), data);
- gtk_table_attach (GTK_TABLE (data->parts), remove, 1, 2, row, row + 1,
- 0, 0, 0, 0);
-
- gtk_widget_show (remove);
-}
-
-static void
-do_grab_focus_cb (GtkWidget *widget, gpointer data)
-{
- gboolean *done = (gboolean *) data;
-
- if (*done)
- return;
-
- if (widget && GTK_WIDGET_CAN_FOCUS (widget)) {
- *done = TRUE;
- gtk_widget_grab_focus (widget);
- }
-}
-
-static void
-more_parts (GtkWidget *button, struct _rule_data *data)
-{
- FilterPart *new;
-
- /* first make sure that the last part is ok */
- if (data->fr->parts) {
- FilterPart *part;
- GList *l;
-
- l = g_list_last (data->fr->parts);
- part = l->data;
- if (!filter_part_validate (part, GTK_WINDOW (gtk_widget_get_toplevel (button))))
- return;
- }
-
- /* create a new rule entry, use the first type of rule */
- new = rule_context_next_part (data->f, NULL);
- if (new) {
- GtkWidget *w;
- gint rows;
-
- new = filter_part_clone (new);
- filter_rule_add_part (data->fr, new);
- w = get_rule_part_widget (data->f, new, data->fr);
-
- rows = GTK_TABLE (data->parts)->nrows;
- gtk_table_resize (GTK_TABLE (data->parts), rows + 1, 2);
- attach_rule (w, data, new, rows);
-
- if (GTK_IS_CONTAINER (w)) {
- gboolean done = FALSE;
-
- gtk_container_foreach (GTK_CONTAINER (w), do_grab_focus_cb, &done);
- } else
- gtk_widget_grab_focus (w);
-
- /* also scroll down to see new part */
- w = (GtkWidget*) g_object_get_data (G_OBJECT (button), "scrolled-window");
- if (w) {
- GtkAdjustment *adjustment;
-
- adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (w));
- if (adjustment) {
- gdouble upper;
-
- upper = gtk_adjustment_get_upper (adjustment);
- gtk_adjustment_set_value (adjustment, upper);
- }
-
- }
- }
-}
-
-static void
-name_changed (GtkEntry *entry, FilterRule *fr)
-{
- g_free (fr->name);
- fr->name = g_strdup (gtk_entry_get_text (entry));
-}
-
-GtkWidget *
-filter_rule_get_widget (FilterRule *fr, RuleContext *rc)
-{
- return FILTER_RULE_GET_CLASS (fr)->get_widget (fr, rc);
-}
-
-static void
-grab_focus (GtkWidget *entry, gpointer data)
-{
- gtk_widget_grab_focus (entry);
-}
-
-static GtkWidget *
-get_widget (FilterRule *fr, struct _RuleContext *f)
-{
- GtkWidget *hbox, *vbox, *parts, *inframe;
- GtkWidget *add, *label, *name, *w;
- GtkWidget *combobox;
- GtkWidget *scrolledwindow;
- GtkObject *hadj, *vadj;
- GList *l;
- gchar *text;
- FilterPart *part;
- struct _rule_data *data;
- gint rows, i;
-
- /* this stuff should probably be a table, but the
- rule parts need to be a vbox */
- vbox = gtk_vbox_new (FALSE, 6);
-
- label = gtk_label_new_with_mnemonic (_("R_ule name:"));
- name = gtk_entry_new ();
- gtk_label_set_mnemonic_widget ((GtkLabel *)label, name);
-
- if (!fr->name) {
- fr->name = g_strdup (_("Untitled"));
- gtk_entry_set_text (GTK_ENTRY (name), fr->name);
- /* FIXME: do we want the following code in the future? */
- /*gtk_editable_select_region (GTK_EDITABLE (name), 0, -1);*/
- } else {
- gtk_entry_set_text (GTK_ENTRY (name), fr->name);
- }
-
- /* evil kludgy hack because gtk sucks */
- g_signal_connect (name, "realize", G_CALLBACK (grab_focus), name);
-
- hbox = gtk_hbox_new (FALSE, 12);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (hbox), name, TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
- g_signal_connect (name, "changed", G_CALLBACK (name_changed), fr);
- gtk_widget_show (label);
- gtk_widget_show (hbox);
-
- hbox = gtk_hbox_new (FALSE, 12);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
- gtk_widget_show (hbox);
-
- text = g_strdup_printf("<b>%s</b>", _("Find items that meet the following conditions"));
- label = gtk_label_new (text);
- gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
- g_free(text);
-
- hbox = gtk_hbox_new (FALSE, 12);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
- gtk_widget_show (hbox);
-
- label = gtk_label_new ("");
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
-
- inframe = gtk_vbox_new (FALSE, 6);
- gtk_box_pack_start (GTK_BOX (hbox), inframe, TRUE, TRUE, 0);
-
- /* this is the parts table, it should probably be inside a scrolling list */
- rows = g_list_length (fr->parts);
- parts = gtk_table_new (rows, 2, FALSE);
-
- /* data for the parts part of the display */
- data = g_malloc0 (sizeof (*data));
- data->f = f;
- data->fr = fr;
- data->parts = parts;
-
- /* only set to automatically clean up the memory */
- g_object_set_data_full ((GObject *) vbox, "data", data, g_free);
-
- hbox = gtk_hbox_new (FALSE, 3);
-
- add = gtk_button_new_with_mnemonic (_("A_dd Condition"));
- gtk_button_set_image (GTK_BUTTON (add), gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON));
- 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 gchar *thread_types[] = { N_("If all conditions are met"), N_("If any conditions are met") };
-
- label = gtk_label_new_with_mnemonic (_("_Find items:"));
- combobox = gtk_combo_box_new_text ();
-
- for (i=0;i<2;i++) {
- gtk_combo_box_append_text (GTK_COMBO_BOX (combobox), _(thread_types[i]));
- }
-
- gtk_label_set_mnemonic_widget ((GtkLabel *)label, combobox);
- gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), fr->grouping);
- gtk_widget_show (combobox);
-
- gtk_box_pack_end (GTK_BOX (hbox), combobox, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
- g_signal_connect (combobox, "changed", G_CALLBACK (fr_grouping_changed), fr);
- }
-
- if (f->flags & RULE_CONTEXT_THREADING) {
- const gchar *thread_types[] = { N_("None"), N_("All related"), N_("Replies"), N_("Replies and parents"), N_("No reply or parent") };
-
- label = gtk_label_new_with_mnemonic (_("I_nclude threads"));
- combobox = gtk_combo_box_new_text ();
-
- for (i=0;i<5;i++) {
- gtk_combo_box_append_text (GTK_COMBO_BOX (combobox), _(thread_types[i]));
- }
-
- gtk_label_set_mnemonic_widget ((GtkLabel *)label, combobox);
- gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), fr->threading);
- gtk_widget_show (combobox);
-
- gtk_box_pack_end (GTK_BOX (hbox), combobox, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
- g_signal_connect (combobox, "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));
- w = get_rule_part_widget (f, part, fr);
- attach_rule (w, data, part, i++);
- l = g_list_next (l);
- }
-
- hadj = gtk_adjustment_new (0.0, 0.0, 1.0, 1.0, 1.0, 1.0);
- vadj = gtk_adjustment_new (0.0, 0.0, 1.0, 1.0, 1.0, 1.0);
- scrolledwindow = gtk_scrolled_window_new (GTK_ADJUSTMENT (hadj), GTK_ADJUSTMENT (vadj));
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
-
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolledwindow), parts);
-
- gtk_box_pack_start (GTK_BOX (inframe), scrolledwindow, TRUE, TRUE, 3);
-
- gtk_widget_show_all (vbox);
-
- g_object_set_data (G_OBJECT (add), "scrolled-window", scrolledwindow);
-
- return vbox;
-}
-
-FilterRule *
-filter_rule_next_list (GList *l, FilterRule *last, const gchar *source)
-{
- GList *node = l;
-
- if (last != NULL) {
- node = g_list_find (node, last);
- if (node == NULL)
- node = l;
- else
- node = node->next;
- }
-
- if (source) {
- while (node) {
- FilterRule *rule = node->data;
-
- if (rule->source && strcmp (rule->source, source) == 0)
- break;
- node = node->next;
- }
- }
-
- if (node)
- return node->data;
-
- return NULL;
-}
-
-FilterRule *
-filter_rule_find_list (GList * l, const gchar *name, const gchar *source)
-{
- while (l) {
- FilterRule *rule = l->data;
-
- if (strcmp (rule->name, name) == 0)
- if (source == NULL || (rule->source != NULL && strcmp (rule->source, source) == 0))
- return rule;
- l = l->next;
- }
-
- return NULL;
-}
-
-#ifdef FOR_TRANSLATIONS_ONLY
-
-static gchar *list[] = {
- N_("Incoming"), N_("Outgoing")
-};
-#endif
diff --git a/filter/filter-rule.h b/filter/filter-rule.h
deleted file mode 100644
index 113026fce9..0000000000
--- a/filter/filter-rule.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _FILTER_RULE_H
-#define _FILTER_RULE_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include "filter-part.h"
-
-#define FILTER_TYPE_RULE (filter_rule_get_type ())
-#define FILTER_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FILTER_TYPE_RULE, FilterRule))
-#define FILTER_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FILTER_TYPE_RULE, FilterRuleClass))
-#define IS_FILTER_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FILTER_TYPE_RULE))
-#define IS_FILTER_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FILTER_TYPE_RULE))
-#define FILTER_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FILTER_TYPE_RULE, FilterRuleClass))
-
-struct _RuleContext;
-
-typedef struct _FilterRule FilterRule;
-typedef struct _FilterRuleClass FilterRuleClass;
-
-enum _filter_grouping_t {
- FILTER_GROUP_ALL, /* all rules must match */
- 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 */
- FILTER_THREAD_SINGLE /* messages with no replies or parents */
-};
-
-#define FILTER_SOURCE_INCOMING "incoming" /* performed on incoming email */
-#define FILTER_SOURCE_DEMAND "demand" /* performed on the selected folder
- * when the user asks for it */
-#define FILTER_SOURCE_OUTGOING "outgoing"/* performed on outgoing mail */
-#define FILTER_SOURCE_JUNKTEST "junktest"/* perform only junktest on incoming mail */
-
-struct _FilterRule {
- GObject parent_object;
- struct _FilterRulePrivate *priv;
-
- gchar *name;
- gchar *source;
-
- enum _filter_grouping_t grouping;
- enum _filter_threading_t threading;
-
- guint system:1; /* this is a system rule, cannot be edited/deleted */
- GList *parts;
-
- gboolean enabled;
-};
-
-struct _FilterRuleClass {
- GObjectClass parent_class;
-
- /* virtual methods */
- gint (*validate) (FilterRule *, GtkWindow *error_parent);
- gint (*eq) (FilterRule *fr, FilterRule *cm);
-
- xmlNodePtr (*xml_encode) (FilterRule *);
- gint (*xml_decode) (FilterRule *, xmlNodePtr, struct _RuleContext *);
-
- void (*build_code) (FilterRule *, GString *out);
-
- void (*copy) (FilterRule *dest, FilterRule *src);
-
- GtkWidget *(*get_widget) (FilterRule *fr, struct _RuleContext *f);
-
- /* signals */
- void (*changed) (FilterRule *fr);
-};
-
-GType filter_rule_get_type (void);
-FilterRule *filter_rule_new (void);
-
-FilterRule *filter_rule_clone (FilterRule *base);
-
-/* methods */
-void filter_rule_set_name (FilterRule *fr, const gchar *name);
-void filter_rule_set_source (FilterRule *fr, const gchar *source);
-
-gint filter_rule_validate (FilterRule *fr, GtkWindow *error_parent);
-gint filter_rule_eq (FilterRule *fr, FilterRule *cm);
-
-xmlNodePtr filter_rule_xml_encode (FilterRule *fr);
-gint filter_rule_xml_decode (FilterRule *fr, xmlNodePtr node, struct _RuleContext *f);
-
-void filter_rule_copy (FilterRule *dest, FilterRule *src);
-
-void filter_rule_add_part (FilterRule *fr, FilterPart *fp);
-void filter_rule_remove_part (FilterRule *fr, FilterPart *fp);
-void filter_rule_replace_part (FilterRule *fr, FilterPart *fp, FilterPart *new);
-
-GtkWidget *filter_rule_get_widget (FilterRule *fr, struct _RuleContext *f);
-
-void filter_rule_build_code (FilterRule *fr, GString *out);
-/*
-void filter_rule_build_action(FilterRule *fr, GString *out);
-*/
-
-void filter_rule_emit_changed (FilterRule *fr);
-
-/* static functions */
-FilterRule *filter_rule_next_list (GList *l, FilterRule *last, const gchar *source);
-FilterRule *filter_rule_find_list (GList *l, const gchar *name, const gchar *source);
-
-#endif /* ! _FILTER_RULE_H */
diff --git a/filter/rule-context.c b/filter/rule-context.c
deleted file mode 100644
index 45f495e37e..0000000000
--- a/filter/rule-context.c
+++ /dev/null
@@ -1,952 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#include <config.h>
-
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include <gtk/gtk.h>
-
-#include <glib/gi18n.h>
-
-#include <libedataserver/e-xml-utils.h>
-
-#include "e-util/e-error.h"
-#include "e-util/e-xml-utils.h"
-
-#include "filter-code.h"
-#include "filter-colour.h"
-#include "filter-datespec.h"
-#include "filter-file.h"
-#include "filter-input.h"
-#include "filter-int.h"
-#include "filter-option.h"
-#include "filter-rule.h"
-#include "rule-context.h"
-
-#define d(x)
-
-static gint load(RuleContext *rc, const gchar *system, const gchar *user);
-static gint save(RuleContext *rc, const gchar *user);
-static gint revert(RuleContext *rc, const gchar *user);
-static GList *rename_uri(RuleContext *rc, const gchar *olduri, const gchar *newuri, GCompareFunc cmp);
-static GList *delete_uri(RuleContext *rc, const gchar *uri, GCompareFunc cmp);
-static FilterElement *new_element(RuleContext *rc, const gchar *name);
-
-static void rule_context_class_init(RuleContextClass *klass);
-static void rule_context_init(RuleContext *rc);
-static void rule_context_finalise(GObject *obj);
-
-#define _PRIVATE(x)(((RuleContext *)(x))->priv)
-
-struct _RuleContextPrivate {
- gint frozen;
-};
-
-static GObjectClass *parent_class = NULL;
-
-enum {
- RULE_ADDED,
- RULE_REMOVED,
- CHANGED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-GType
-rule_context_get_type(void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof(RuleContextClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) rule_context_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof(RuleContext),
- 0, /* n_preallocs */
- (GInstanceInitFunc) rule_context_init,
- };
-
- type = g_type_register_static(G_TYPE_OBJECT, "RuleContext", &info, 0);
- }
-
- return type;
-}
-
-static void
-rule_context_class_init(RuleContextClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
-
- parent_class = g_type_class_ref(G_TYPE_OBJECT);
-
- object_class->finalize = rule_context_finalise;
-
- /* override methods */
- klass->load = load;
- klass->save = save;
- klass->revert = revert;
- klass->rename_uri = rename_uri;
- klass->delete_uri = delete_uri;
- klass->new_element = new_element;
-
- /* signals */
- signals[RULE_ADDED] =
- g_signal_new("rule_added",
- RULE_TYPE_CONTEXT,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(RuleContextClass, rule_added),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
-
- signals[RULE_REMOVED] =
- g_signal_new("rule_removed",
- RULE_TYPE_CONTEXT,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(RuleContextClass, rule_removed),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
-
- signals[CHANGED] =
- g_signal_new("changed",
- RULE_TYPE_CONTEXT,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(RuleContextClass, changed),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-static void
-rule_context_init(RuleContext *rc)
-{
- rc->priv = g_malloc0(sizeof(*rc->priv));
-
- 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
-free_part_set(struct _part_set_map *map, gpointer data)
-{
- g_free(map->name);
- g_free(map);
-}
-
-static void
-free_rule_set(struct _rule_set_map *map, gpointer data)
-{
- g_free(map->name);
- g_free(map);
-}
-
-static void
-rule_context_finalise(GObject *obj)
-{
- RuleContext *rc =(RuleContext *) obj;
-
- g_list_foreach(rc->rule_set_list, (GFunc)free_rule_set, NULL);
- g_list_free(rc->rule_set_list);
- g_hash_table_destroy(rc->rule_set_map);
-
- g_list_foreach(rc->part_set_list, (GFunc)free_part_set, NULL);
- g_list_free(rc->part_set_list);
- g_hash_table_destroy(rc->part_set_map);
-
- g_free(rc->error);
-
- g_list_foreach(rc->parts, (GFunc)g_object_unref, NULL);
- g_list_free(rc->parts);
- g_list_foreach(rc->rules, (GFunc)g_object_unref, NULL);
- g_list_free(rc->rules);
-
- g_free(rc->priv);
-
- G_OBJECT_CLASS(parent_class)->finalize(obj);
-}
-
-/**
- * rule_context_new:
- *
- * Create a new RuleContext object.
- *
- * Return value: A new #RuleContext object.
- **/
-RuleContext *
-rule_context_new(void)
-{
- return(RuleContext *) g_object_new(RULE_TYPE_CONTEXT, NULL, NULL);
-}
-
-void
-rule_context_add_part_set(RuleContext *rc, const gchar *setname, GType part_type, RCPartFunc append, RCNextPartFunc next)
-{
- struct _part_set_map *map;
-
- g_return_if_fail (g_hash_table_lookup(rc->part_set_map, setname) == NULL);
-
- map = g_malloc0(sizeof(*map));
- map->type = part_type;
- map->append = append;
- map->next = next;
- map->name = g_strdup(setname);
- g_hash_table_insert(rc->part_set_map, map->name, map);
- rc->part_set_list = g_list_append(rc->part_set_list, map);
- d(printf("adding part set '%s'\n", setname));
-}
-
-void
-rule_context_add_rule_set(RuleContext *rc, const gchar *setname, GType rule_type, RCRuleFunc append, RCNextRuleFunc next)
-{
- struct _rule_set_map *map;
-
- g_return_if_fail (g_hash_table_lookup(rc->rule_set_map, setname) == NULL);
-
- map = g_malloc0(sizeof(*map));
- map->type = rule_type;
- map->append = append;
- map->next = next;
- map->name = g_strdup(setname);
- g_hash_table_insert(rc->rule_set_map, map->name, map);
- rc->rule_set_list = g_list_append(rc->rule_set_list, map);
- d(printf("adding rule set '%s'\n", setname));
-}
-
-/**
- * rule_context_set_error:
- * @f:
- * @error:
- *
- * Set the text error for the context, or NULL to clear it.
- **/
-static void
-rule_context_set_error(RuleContext *rc, gchar *error)
-{
- g_return_if_fail (rc);
-
- g_free(rc->error);
- rc->error = error;
-}
-
-/**
- * rule_context_load:
- * @f:
- * @system:
- * @user:
- *
- * Load a rule context from a system and user description file.
- *
- * Return value:
- **/
-gint
-rule_context_load(RuleContext *rc, const gchar *system, const gchar *user)
-{
- gint res;
-
- g_return_val_if_fail (rc, -1);
-
- d(printf("rule_context: loading %s %s\n", system, user));
-
- rc->priv->frozen++;
- res = RULE_CONTEXT_GET_CLASS(rc)->load(rc, system, user);
- rc->priv->frozen--;
-
- return res;
-}
-
-static gint
-load(RuleContext *rc, const gchar *system, const gchar *user)
-{
- xmlNodePtr set, rule, root;
- xmlDocPtr systemdoc, userdoc;
- struct _part_set_map *part_map;
- struct _rule_set_map *rule_map;
-
- rule_context_set_error(rc, NULL);
-
- d(printf("loading rules %s %s\n", system, user));
-
- systemdoc = e_xml_parse_file (system);
- if (systemdoc == NULL) {
- rule_context_set_error(rc, g_strdup_printf("Unable to load system rules '%s': %s",
- system, g_strerror(errno)));
- return -1;
- }
-
- root = xmlDocGetRootElement(systemdoc);
- if (root == NULL || strcmp((gchar *)root->name, "filterdescription")) {
- rule_context_set_error(rc, g_strdup_printf("Unable to load system rules '%s': Invalid format", system));
- xmlFreeDoc(systemdoc);
- return -1;
- }
- /* doesn't matter if this doens't exist */
- userdoc = NULL;
- if (g_file_test(user, G_FILE_TEST_IS_REGULAR))
- userdoc = e_xml_parse_file (user);
-
- /* now parse structure */
- /* get rule parts */
- set = root->children;
- while (set) {
- d(printf("set name = %s\n", set->name));
- part_map = g_hash_table_lookup(rc->part_set_map, set->name);
- if (part_map) {
- d(printf("loading parts ...\n"));
- rule = set->children;
- while (rule) {
- if (!strcmp((gchar *)rule->name, "part")) {
- FilterPart *part = FILTER_PART(g_object_new(part_map->type, NULL, NULL));
-
- if (filter_part_xml_create(part, rule, rc) == 0) {
- part_map->append(rc, part);
- } else {
- g_object_unref(part);
- g_warning("Cannot load filter part");
- }
- }
- rule = rule->next;
- }
- } else if ((rule_map = g_hash_table_lookup(rc->rule_set_map, set->name))) {
- d(printf("loading system rules ...\n"));
- rule = set->children;
- while (rule) {
- d(printf("checking node: %s\n", rule->name));
- if (!strcmp((gchar *)rule->name, "rule")) {
- FilterRule *part = FILTER_RULE(g_object_new(rule_map->type, NULL, NULL));
-
- if (filter_rule_xml_decode(part, rule, rc) == 0) {
- part->system = TRUE;
- rule_map->append(rc, part);
- } else {
- g_object_unref(part);
- g_warning("Cannot load filter part");
- }
- }
- rule = rule->next;
- }
- }
- set = set->next;
- }
-
- /* now load actual rules */
- if (userdoc) {
- root = xmlDocGetRootElement(userdoc);
- set = root?root->children:NULL;
- while (set) {
- d(printf("set name = %s\n", set->name));
- rule_map = g_hash_table_lookup(rc->rule_set_map, set->name);
- if (rule_map) {
- d(printf("loading rules ...\n"));
- rule = set->children;
- while (rule) {
- d(printf("checking node: %s\n", rule->name));
- if (!strcmp((gchar *)rule->name, "rule")) {
- FilterRule *part = FILTER_RULE(g_object_new(rule_map->type, NULL, NULL));
-
- if (filter_rule_xml_decode(part, rule, rc) == 0) {
- rule_map->append(rc, part);
- } else {
- g_object_unref(part);
- g_warning("Cannot load filter part");
- }
- }
- rule = rule->next;
- }
- }
- set = set->next;
- }
- }
-
- xmlFreeDoc(userdoc);
- xmlFreeDoc(systemdoc);
-
- return 0;
-}
-
-/**
- * rule_context_save:
- * @f:
- * @user:
- *
- * Save a rule context to disk.
- *
- * Return value:
- **/
-gint
-rule_context_save(RuleContext *rc, const gchar *user)
-{
- g_return_val_if_fail (rc, -1);
- g_return_val_if_fail (user, -1);
-
- return RULE_CONTEXT_GET_CLASS(rc)->save(rc, user);
-}
-
-static gint
-save(RuleContext *rc, const gchar *user)
-{
- xmlDocPtr doc;
- xmlNodePtr root, rules, work;
- GList *l;
- FilterRule *rule;
- struct _rule_set_map *map;
- gint ret;
-
- doc = xmlNewDoc((const guchar *)"1.0");
- /* FIXME: set character encoding to UTF-8? */
- root = xmlNewDocNode(doc, NULL, (const guchar *)"filteroptions", NULL);
- xmlDocSetRootElement(doc, root);
- l = rc->rule_set_list;
- while (l) {
- map = l->data;
- rules = xmlNewDocNode(doc, NULL, (guchar *)map->name, NULL);
- xmlAddChild(root, rules);
- rule = NULL;
- while ((rule = map->next(rc, rule, NULL))) {
- if (!rule->system) {
- d(printf("processing rule %s\n", rule->name));
- work = filter_rule_xml_encode(rule);
- xmlAddChild(rules, work);
- }
- }
- l = g_list_next(l);
- }
-
- ret = e_xml_save_file(user, doc);
-
- xmlFreeDoc(doc);
-
- 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:
- **/
-gint
-rule_context_revert(RuleContext *rc, const gchar *user)
-{
- g_return_val_if_fail (rc, 0);
-
- d(printf("rule_context: restoring %s\n", user));
-
- return RULE_CONTEXT_GET_CLASS(rc)->revert(rc, user);
-}
-
-struct _revert_data {
- GHashTable *rules;
- gint rank;
-};
-
-static void
-revert_rule_remove(gpointer key, FilterRule *frule, RuleContext *rc)
-{
- rule_context_remove_rule(rc, frule);
- g_object_unref(frule);
-}
-
-static void
-revert_source_remove(gpointer key, struct _revert_data *rest_data, RuleContext *rc)
-{
- g_hash_table_foreach(rest_data->rules, (GHFunc)revert_rule_remove, rc);
- g_hash_table_destroy(rest_data->rules);
- g_free(rest_data);
-}
-
-static guint
-source_hashf(const gchar *a)
-{
- if (a)
- return g_str_hash(a);
- return 0;
-}
-
-static gint
-source_eqf(const gchar *a, const gchar *b)
-{
- return((a && b && strcmp(a, b) == 0))
- || (a == NULL && b == NULL);
-}
-
-static gint
-revert(RuleContext *rc, const gchar *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(rc, NULL);
-
- d(printf("restoring rules %s\n", user));
-
- userdoc = e_xml_parse_file (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(rc, 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 = xmlDocGetRootElement(userdoc);
- set = set?set->children:NULL;
- while (set) {
- d(printf("set name = %s\n", set->name));
- rule_map = g_hash_table_lookup(rc->rule_set_map, set->name);
- if (rule_map) {
- d(printf("loading rules ...\n"));
- rule = set->children;
- while (rule) {
- d(printf("checking node: %s\n", rule->name));
- if (!strcmp((gchar *)rule->name, "rule")) {
- FilterRule *part = FILTER_RULE(g_object_new(rule_map->type, NULL, NULL));
-
- if (filter_rule_xml_decode(part, rule, rc) == 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 (rc->priv->frozen == 0 && !filter_rule_eq(frule, part))
- filter_rule_copy(frule, part);
-
- g_object_unref(part);
- rule_context_rank_rule(rc, frule, frule->source, rest_data->rank);
- g_hash_table_remove(rest_data->rules, frule->name);
- } else {
- rule_context_add_rule(rc, part);
- rule_context_rank_rule(rc, part, part->source, rest_data->rank);
- }
- rest_data->rank++;
- } else {
- g_object_unref(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, rc);
- g_hash_table_destroy(source_hash);
-
- return 0;
-}
-
-FilterPart *
-rule_context_find_part(RuleContext *rc, const gchar *name)
-{
- g_return_val_if_fail (rc, NULL);
- g_return_val_if_fail (name, NULL);
-
- d(printf("find part : "));
- return filter_part_find_list(rc->parts, name);
-}
-
-FilterPart *
-rule_context_create_part(RuleContext *rc, const gchar *name)
-{
- FilterPart *part;
-
- g_return_val_if_fail (rc, NULL);
- g_return_val_if_fail (name, NULL);
-
- if ((part = rule_context_find_part(rc, name)))
- return filter_part_clone(part);
-
- return NULL;
-}
-
-FilterPart *
-rule_context_next_part(RuleContext *rc, FilterPart *last)
-{
- g_return_val_if_fail (rc, NULL);
-
- return filter_part_next_list(rc->parts, last);
-}
-
-FilterRule *
-rule_context_next_rule(RuleContext *rc, FilterRule *last, const gchar *source)
-{
- g_return_val_if_fail (rc, NULL);
-
- return filter_rule_next_list(rc->rules, last, source);
-}
-
-FilterRule *
-rule_context_find_rule(RuleContext *rc, const gchar *name, const gchar *source)
-{
- g_return_val_if_fail (name, NULL);
- g_return_val_if_fail (rc, NULL);
-
- return filter_rule_find_list(rc->rules, name, source);
-}
-
-void
-rule_context_add_part(RuleContext *rc, FilterPart *part)
-{
- g_return_if_fail (rc);
- g_return_if_fail (part);
-
- rc->parts = g_list_append(rc->parts, part);
-}
-
-void
-rule_context_add_rule(RuleContext *rc, FilterRule *new)
-{
- g_return_if_fail (rc);
- g_return_if_fail (new);
-
- d(printf("add rule '%s'\n", new->name));
-
- rc->rules = g_list_append(rc->rules, new);
-
- if (rc->priv->frozen == 0) {
- g_signal_emit(rc, signals[RULE_ADDED], 0, new);
- g_signal_emit(rc, signals[CHANGED], 0);
- }
-}
-
-static void
-new_rule_response(GtkWidget *dialog, gint button, RuleContext *context)
-{
- if (button == GTK_RESPONSE_OK) {
- FilterRule *rule = g_object_get_data((GObject *) dialog, "rule");
- gchar *user = g_object_get_data((GObject *) dialog, "path");
-
- if (!filter_rule_validate (rule, GTK_WINDOW (dialog))) {
- /* no need to popup a dialog because the validate code does that. */
- return;
- }
-
- if (rule_context_find_rule (context, rule->name, rule->source)) {
- e_error_run ((GtkWindow *)dialog, "filter:bad-name-notunique", rule->name, NULL);
-
- return;
- }
-
- g_object_ref(rule);
- rule_context_add_rule(context, rule);
- if (user)
- rule_context_save(context, user);
- }
-
- gtk_widget_destroy(dialog);
-}
-
-/* add a rule, with a gui, asking for confirmation first ... optionally save to path */
-void
-rule_context_add_rule_gui(RuleContext *rc, FilterRule *rule, const gchar *title, const gchar *path)
-{
- GtkDialog *dialog;
- GtkWidget *widget;
- GtkWidget *content_area;
-
- d(printf("add rule gui '%s'\n", rule->name));
-
- g_return_if_fail (rc);
- g_return_if_fail (rule);
-
- widget = filter_rule_get_widget(rule, rc);
- gtk_widget_show(widget);
-
- dialog =(GtkDialog *) gtk_dialog_new();
- gtk_dialog_add_buttons(dialog,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- NULL);
- gtk_dialog_set_has_separator (dialog, FALSE);
-
- gtk_window_set_title((GtkWindow *) dialog, title);
- gtk_window_set_default_size((GtkWindow *) dialog, 600, 400);
- gtk_window_set_resizable((GtkWindow *) dialog, TRUE);
-
- content_area = gtk_dialog_get_content_area (dialog);
- gtk_box_pack_start (GTK_BOX (content_area), widget, TRUE, TRUE, 0);
-
- g_object_set_data_full((GObject *) dialog, "rule", rule, g_object_unref);
- if (path)
- g_object_set_data_full((GObject *) dialog, "path", g_strdup(path), g_free);
-
- g_signal_connect(dialog, "response", G_CALLBACK(new_rule_response), rc);
-
- g_object_ref(rc);
-
- g_object_set_data_full((GObject *) dialog, "context", rc, g_object_unref);
-
- gtk_widget_show((GtkWidget *) dialog);
-}
-
-void
-rule_context_remove_rule(RuleContext *rc, FilterRule *rule)
-{
- g_return_if_fail (rc);
- g_return_if_fail (rule);
-
- d(printf("remove rule '%s'\n", rule->name));
-
- rc->rules = g_list_remove(rc->rules, rule);
-
- if (rc->priv->frozen == 0) {
- g_signal_emit(rc, signals[RULE_REMOVED], 0, rule);
- g_signal_emit(rc, signals[CHANGED], 0);
- }
-}
-
-void
-rule_context_rank_rule(RuleContext *rc, FilterRule *rule, const gchar *source, gint rank)
-{
- GList *node;
- gint i = 0, index = 0;
-
- g_return_if_fail (rc);
- g_return_if_fail (rule);
-
- if (rule_context_get_rank_rule (rc, rule, source) == rank)
- return;
-
- rc->rules = g_list_remove(rc->rules, rule);
- node = rc->rules;
- while (node) {
- FilterRule *r = node->data;
-
- if (i == rank) {
- rc->rules = g_list_insert(rc->rules, rule, index);
- if (rc->priv->frozen == 0)
- g_signal_emit(rc, signals[CHANGED], 0);
-
- return;
- }
-
- index++;
- if (source == NULL || (r->source && strcmp(r->source, source) == 0))
- i++;
-
- node = node->next;
- }
-
- rc->rules = g_list_append(rc->rules, rule);
- if (rc->priv->frozen == 0)
- g_signal_emit(rc, signals[CHANGED], 0);
-}
-
-gint
-rule_context_get_rank_rule(RuleContext *rc, FilterRule *rule, const gchar *source)
-{
- GList *node;
- gint i = 0;
-
- g_return_val_if_fail (rc, -1);
- g_return_val_if_fail (rule, -1);
-
- d(printf("getting rank of rule '%s'\n", rule->name));
-
- node = rc->rules;
- while (node) {
- FilterRule *r = node->data;
-
- d(printf(" checking against rule '%s' rank '%d'\n", r->name, i));
-
- if (r == rule)
- return i;
-
- if (source == NULL || (r->source && strcmp(r->source, source) == 0))
- i++;
-
- node = node->next;
- }
-
- return -1;
-}
-
-FilterRule *
-rule_context_find_rank_rule(RuleContext *rc, gint rank, const gchar *source)
-{
- GList *node;
- gint i = 0;
-
- g_return_val_if_fail (rc, NULL);
-
- d(printf("getting rule at rank %d source '%s'\n", rank, source?source:"<any>"));
-
- node = rc->rules;
- while (node) {
- FilterRule *r = node->data;
-
- d(printf(" checking against rule '%s' rank '%d'\n", r->name, i));
-
- if (source == NULL || (r->source && strcmp(r->source, source) == 0)) {
- if (rank == i)
- return r;
- i++;
- }
-
- node = node->next;
- }
-
- return NULL;
-}
-
-static GList *
-delete_uri(RuleContext *rc, const gchar *uri, GCompareFunc cmp)
-{
- return NULL;
-}
-
-GList *
-rule_context_delete_uri(RuleContext *rc, const gchar *uri, GCompareFunc cmp)
-{
- return RULE_CONTEXT_GET_CLASS(rc)->delete_uri(rc, uri, cmp);
-}
-
-static GList *
-rename_uri(RuleContext *rc, const gchar *olduri, const gchar *newuri, GCompareFunc cmp)
-{
- return NULL;
-}
-
-GList *
-rule_context_rename_uri(RuleContext *rc, const gchar *olduri, const gchar *newuri, GCompareFunc cmp)
-{
- return RULE_CONTEXT_GET_CLASS(rc)->rename_uri(rc, olduri, newuri, cmp);
-}
-
-void
-rule_context_free_uri_list(RuleContext *rc, GList *uris)
-{
- GList *l = uris, *n;
-
- /* TODO: should be virtual */
-
- while (l) {
- n = l->next;
- g_free(l->data);
- g_list_free_1(l);
- l = n;
- }
-}
-
-static FilterElement *
-new_element(RuleContext *rc, const gchar *type)
-{
- if (!strcmp (type, "string")) {
- return (FilterElement *) filter_input_new ();
- } else if (!strcmp (type, "address")) {
- /* FIXME: temporary ... need real address type */
- return (FilterElement *) filter_input_new_type_name (type);
- } else if (!strcmp (type, "code")) {
- return (FilterElement *) filter_code_new (FALSE);
- } else if (!strcmp (type, "rawcode")) {
- return (FilterElement *) filter_code_new (TRUE);
- } else if (!strcmp (type, "colour")) {
- return (FilterElement *) filter_colour_new ();
- } else if (!strcmp (type, "optionlist")) {
- return (FilterElement *) filter_option_new ();
- } else if (!strcmp (type, "datespec")) {
- return (FilterElement *) filter_datespec_new ();
- } else if (!strcmp (type, "command")) {
- return (FilterElement *) filter_file_new_type_name (type);
- } else if (!strcmp (type, "file")) {
- return (FilterElement *) filter_file_new_type_name (type);
- } else if (!strcmp (type, "integer")) {
- return (FilterElement *) filter_int_new ();
- } else if (!strcmp (type, "regex")) {
- return (FilterElement *) filter_input_new_type_name (type);
- }else if (!strcmp(type, "completedpercent")) {
- return (FilterElement *) filter_int_new_type("completedpercent", 0,100);
-
- } else {
- g_warning("Unknown filter type '%s'", type);
- return NULL;
- }
-}
-
-/**
- * rule_context_new_element:
- * @rc:
- * @name:
- *
- * create a new filter element based on name.
- *
- * Return value:
- **/
-FilterElement *
-rule_context_new_element(RuleContext *rc, const gchar *name)
-{
- if (name == NULL)
- return NULL;
-
- return RULE_CONTEXT_GET_CLASS(rc)->new_element(rc, name);
-}
-
diff --git a/filter/rule-context.h b/filter/rule-context.h
deleted file mode 100644
index 63c9abaa67..0000000000
--- a/filter/rule-context.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- *
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _RULE_CONTEXT_H
-#define _RULE_CONTEXT_H
-
-#include <glib.h>
-#include <glib-object.h>
-#include <libxml/parser.h>
-
-#include "filter-part.h"
-#include "filter-rule.h"
-
-#define RULE_TYPE_CONTEXT (rule_context_get_type ())
-#define RULE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RULE_TYPE_CONTEXT, RuleContext))
-#define RULE_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RULE_TYPE_CONTEXT, RuleContextClass))
-#define IS_RULE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RULE_TYPE_CONTEXT))
-#define IS_RULE_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RULE_TYPE_CONTEXT))
-#define RULE_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RULE_TYPE_CONTEXT, RuleContextClass))
-
-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;
-
- gchar *error; /* string version of error */
-
- guint32 flags; /* capability flags */
-
- GList *parts;
- GList *rules;
-
- GHashTable *part_set_map; /* map set types to part types */
- GList *part_set_list;
- GHashTable *rule_set_map; /* map set types to rule types */
- GList *rule_set_list;
-};
-
-typedef void (*RCRegisterFunc) (RuleContext *rc, FilterRule *rule, gpointer user_data);
-
-struct _RuleContextClass {
- GObjectClass parent_class;
-
- /* virtual methods */
- gint (*load) (RuleContext *rc, const gchar *system, const gchar *user);
- gint (*save) (RuleContext *rc, const gchar *user);
- gint (*revert) (RuleContext *rc, const gchar *user);
-
- GList *(*delete_uri) (RuleContext *rc, const gchar *uri, GCompareFunc cmp);
- GList *(*rename_uri) (RuleContext *rc, const gchar *olduri, const gchar *newuri, GCompareFunc cmp);
-
- FilterElement *(*new_element)(RuleContext *rc, const gchar *name);
-
- /* signals */
- void (*rule_added) (RuleContext *rc, FilterRule *rule);
- void (*rule_removed) (RuleContext *rc, FilterRule *rule);
- void (*changed) (RuleContext *rc);
-};
-
-typedef void (*RCPartFunc) (RuleContext *rc, FilterPart *part);
-typedef void (*RCRuleFunc) (RuleContext *rc, FilterRule *part);
-typedef FilterPart * (*RCNextPartFunc) (RuleContext *rc, FilterPart *part);
-typedef FilterRule * (*RCNextRuleFunc) (RuleContext *rc, FilterRule *rule, const gchar *source);
-
-struct _part_set_map {
- gchar *name;
- GType type;
- RCPartFunc append;
- RCNextPartFunc next;
-};
-
-struct _rule_set_map {
- gchar *name;
- GType type;
- RCRuleFunc append;
- RCNextRuleFunc next;
-};
-
-GType rule_context_get_type (void);
-
-/* methods */
-RuleContext *rule_context_new (void);
-
-/* io */
-gint rule_context_load (RuleContext *rc, const gchar *system, const gchar *user);
-gint rule_context_save (RuleContext *rc, const gchar *user);
-gint rule_context_revert (RuleContext *rc, const gchar *user);
-
-void rule_context_add_part (RuleContext *rc, FilterPart *new);
-FilterPart *rule_context_find_part (RuleContext *rc, const gchar *name);
-FilterPart *rule_context_create_part (RuleContext *rc, const gchar *name);
-FilterPart *rule_context_next_part (RuleContext *rc, FilterPart *last);
-
-FilterRule *rule_context_next_rule (RuleContext *rc, FilterRule *last, const gchar *source);
-FilterRule *rule_context_find_rule (RuleContext *rc, const gchar *name, const gchar *source);
-FilterRule *rule_context_find_rank_rule (RuleContext *rc, gint rank, const gchar *source);
-void rule_context_add_rule (RuleContext *rc, FilterRule *new);
-void rule_context_add_rule_gui (RuleContext *rc, FilterRule *rule, const gchar *title, const gchar *path);
-void rule_context_remove_rule (RuleContext *rc, FilterRule *rule);
-
-/* get/set the rank (position) of a rule */
-void rule_context_rank_rule (RuleContext *rc, FilterRule *rule, const gchar *source, gint rank);
-gint rule_context_get_rank_rule (RuleContext *rc, FilterRule *rule, const gchar *source);
-
-/* setup type for set parts */
-void rule_context_add_part_set (RuleContext *rc, const gchar *setname, GType part_type,
- RCPartFunc append, RCNextPartFunc next);
-void rule_context_add_rule_set (RuleContext *rc, const gchar *setname, GType rule_type,
- RCRuleFunc append, RCNextRuleFunc next);
-
-/* dynamic element types */
-FilterElement *rule_context_new_element(RuleContext *rc, const gchar *name);
-
-/* uri's disappear/renamed externally */
-GList *rule_context_delete_uri (RuleContext *rc, const gchar *uri, GCompareFunc cmp);
-GList *rule_context_rename_uri (RuleContext *rc, const gchar *olduri, const gchar *newuri, GCompareFunc cmp);
-
-void rule_context_free_uri_list (RuleContext *rc, GList *uris);
-
-#endif /* ! _RULE_CONTEXT_H */
diff --git a/filter/rule-editor.c b/filter/rule-editor.c
deleted file mode 100644
index edda65e116..0000000000
--- a/filter/rule-editor.c
+++ /dev/null
@@ -1,880 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-/* for getenv only, remove when getenv need removed */
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib/gi18n.h>
-
-#include "e-util/e-error.h"
-#include "e-util/e-util-private.h"
-#include "rule-editor.h"
-
-static gint enable_undo = 0;
-
-#define d(x)
-
-static void set_source (RuleEditor *re, const gchar *source);
-static void set_sensitive (RuleEditor *re);
-static FilterRule *create_rule (RuleEditor *re);
-
-static gboolean update_selected_rule (RuleEditor *re);
-static void cursor_changed (GtkTreeView *treeview, RuleEditor *re);
-
-static void rule_editor_class_init (RuleEditorClass *klass);
-static void rule_editor_init (RuleEditor *re);
-static void rule_editor_finalise (GObject *obj);
-static void rule_editor_destroy (GtkObject *obj);
-
-static void dialog_rule_changed (FilterRule *fr, GtkWidget *dialog);
-
-#define _PRIVATE(x)(((RuleEditor *)(x))->priv)
-
-enum {
- BUTTON_ADD,
- BUTTON_EDIT,
- BUTTON_DELETE,
- BUTTON_TOP,
- BUTTON_UP,
- BUTTON_DOWN,
- BUTTON_BOTTOM,
- BUTTON_LAST
-};
-
-struct _RuleEditorPrivate {
- GtkButton *buttons[BUTTON_LAST];
-};
-
-static GtkDialogClass *parent_class = NULL;
-
-GType
-rule_editor_get_type (void)
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo info = {
- sizeof (RuleEditorClass),
- NULL, /* base_class_init */
- NULL, /* base_class_finalize */
- (GClassInitFunc) rule_editor_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (RuleEditor),
- 0, /* n_preallocs */
- (GInstanceInitFunc) rule_editor_init,
- };
-
- /* TODO: Remove when it works (or never will) */
- enable_undo = getenv ("EVOLUTION_RULE_UNDO") != NULL;
-
- type = g_type_register_static (gtk_dialog_get_type (), "RuleEditor", &info, 0);
- }
-
- return type;
-}
-
-static void
-rule_editor_class_init (RuleEditorClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GtkObjectClass *object_class = (GtkObjectClass *) klass;
-
- parent_class = g_type_class_ref(gtk_dialog_get_type ());
-
- gobject_class->finalize = rule_editor_finalise;
- object_class->destroy = rule_editor_destroy;
-
- /* override methods */
- klass->set_source = set_source;
- klass->set_sensitive = set_sensitive;
- klass->create_rule = create_rule;
-}
-
-static void
-rule_editor_init (RuleEditor *re)
-{
- re->priv = g_malloc0 (sizeof (*re->priv));
-}
-
-static void
-rule_editor_finalise (GObject *obj)
-{
- RuleEditor *re = (RuleEditor *)obj;
- RuleEditorUndo *undo, *next;
-
- g_object_unref (re->context);
- g_free (re->priv);
-
- undo = re->undo_log;
- while (undo) {
- next = undo->next;
- g_object_unref (undo->rule);
- g_free (undo);
- undo = next;
- }
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-static void
-rule_editor_destroy (GtkObject *obj)
-{
- RuleEditor *re = (RuleEditor *) obj;
-
- if (re->dialog) {
- gtk_widget_destroy (GTK_WIDGET (re->dialog));
- re->dialog = NULL;
- }
-
- ((GtkObjectClass *)(parent_class))->destroy (obj);
-}
-
-/**
- * rule_editor_new:
- *
- * Create a new RuleEditor object.
- *
- * Return value: A new #RuleEditor object.
- **/
-RuleEditor *
-rule_editor_new (RuleContext *rc, const gchar *source, const gchar *label)
-{
- RuleEditor *re = (RuleEditor *) g_object_new (RULE_TYPE_EDITOR, NULL);
- GladeXML *gui;
- gchar *filter_glade = g_build_filename (EVOLUTION_GLADEDIR,
- "filter.glade",
- NULL);
-
- gui = glade_xml_new (filter_glade, "rule_editor", NULL);
- g_free (filter_glade);
- rule_editor_construct (re, rc, gui, source, label);
- gtk_widget_hide (glade_xml_get_widget (gui, "label17"));
- gtk_widget_hide (glade_xml_get_widget (gui, "filter_source_combobox"));
- g_object_unref (gui);
-
- return re;
-}
-
-/* used internally by implementations if required */
-void
-rule_editor_set_sensitive (RuleEditor *re)
-{
- RULE_EDITOR_GET_CLASS (re)->set_sensitive (re);
-}
-
-/* used internally by implementations */
-void
-rule_editor_set_source (RuleEditor *re, const gchar *source)
-{
- RULE_EDITOR_GET_CLASS (re)->set_source (re, source);
-}
-
-/* factory method for "add" button */
-FilterRule *
-rule_editor_create_rule (RuleEditor *re)
-{
- return RULE_EDITOR_GET_CLASS (re)->create_rule (re);
-}
-
-static FilterRule *
-create_rule (RuleEditor *re)
-{
- FilterRule *rule = filter_rule_new ();
- FilterPart *part;
-
- /* create a rule with 1 part in it */
- part = rule_context_next_part (re->context, NULL);
- filter_rule_add_part (rule, filter_part_clone (part));
-
- return rule;
-}
-
-static void
-editor_destroy (RuleEditor *re, GObject *deadbeef)
-{
- if (re->edit) {
- g_object_unref (re->edit);
- re->edit = NULL;
- }
-
- re->dialog = NULL;
-
- gtk_widget_set_sensitive (GTK_WIDGET (re), TRUE);
- rule_editor_set_sensitive (re);
-}
-
-static void
-rule_editor_add_undo (RuleEditor *re, gint type, FilterRule *rule, gint rank, gint newrank)
-{
- RuleEditorUndo *undo;
-
- if (!re->undo_active && enable_undo) {
- undo = g_malloc0 (sizeof (*undo));
- undo->rule = rule;
- undo->type = type;
- undo->rank = rank;
- undo->newrank = newrank;
-
- undo->next = re->undo_log;
- re->undo_log = undo;
- } else {
- g_object_unref (rule);
- }
-}
-
-static void
-rule_editor_play_undo (RuleEditor *re)
-{
- RuleEditorUndo *undo, *next;
- FilterRule *rule;
-
- re->undo_active = TRUE;
- undo = re->undo_log;
- re->undo_log = NULL;
- while (undo) {
- next = undo->next;
- switch (undo->type) {
- case RULE_EDITOR_LOG_EDIT:
- d(printf ("Undoing edit on rule '%s'\n", undo->rule->name));
- rule = rule_context_find_rank_rule (re->context, undo->rank, undo->rule->source);
- if (rule) {
- d(printf (" name was '%s'\n", rule->name));
- filter_rule_copy (rule, undo->rule);
- d(printf (" name is '%s'\n", rule->name));
- } else {
- g_warning ("Could not find the right rule to undo against?");
- }
- break;
- case RULE_EDITOR_LOG_ADD:
- d(printf ("Undoing add on rule '%s'\n", undo->rule->name));
- rule = rule_context_find_rank_rule (re->context, undo->rank, undo->rule->source);
- if (rule)
- rule_context_remove_rule (re->context, rule);
- break;
- case RULE_EDITOR_LOG_REMOVE:
- d(printf ("Undoing remove on rule '%s'\n", undo->rule->name));
- g_object_ref (undo->rule);
- rule_context_add_rule (re->context, undo->rule);
- rule_context_rank_rule (re->context, undo->rule, re->source, undo->rank);
- break;
- case RULE_EDITOR_LOG_RANK:
- rule = rule_context_find_rank_rule (re->context, undo->newrank, undo->rule->source);
- if (rule)
- rule_context_rank_rule (re->context, rule, re->source, undo->rank);
- break;
- }
-
- g_object_unref (undo->rule);
- g_free (undo);
- undo = next;
- }
- re->undo_active = FALSE;
-}
-
-static void
-editor_response (GtkWidget *dialog, gint button, RuleEditor *re)
-{
- if (button == GTK_RESPONSE_CANCEL) {
- if (enable_undo)
- rule_editor_play_undo (re);
- else {
- RuleEditorUndo *undo, *next;
-
- undo = re->undo_log;
- re->undo_log = NULL;
- while (undo) {
- next = undo->next;
- g_object_unref (undo->rule);
- g_free (undo);
- undo = next;
- }
- }
- }
-}
-
-static void
-add_editor_response (GtkWidget *dialog, gint button, RuleEditor *re)
-{
- GtkTreeSelection *selection;
- GtkTreePath *path;
- GtkTreeIter iter;
-
- if (button == GTK_RESPONSE_OK) {
- if (!filter_rule_validate (re->edit, GTK_WINDOW (dialog))) {
- /* no need to popup a dialog because the validate code does that. */
- return;
- }
-
- if (rule_context_find_rule (re->context, re->edit->name, re->edit->source)) {
- e_error_run ((GtkWindow *)dialog, "filter:bad-name-notunique", re->edit->name, NULL);
- return;
- }
-
- g_object_ref (re->edit);
-
- gtk_list_store_append (re->model, &iter);
- gtk_list_store_set (re->model, &iter, 0, re->edit->name, 1, re->edit, 2, re->edit->enabled, -1);
- selection = gtk_tree_view_get_selection (re->list);
- gtk_tree_selection_select_iter (selection, &iter);
-
- /* scroll to the newly added row */
- path = gtk_tree_model_get_path ((GtkTreeModel *) re->model, &iter);
- gtk_tree_view_scroll_to_cell (re->list, path, NULL, TRUE, 1.0, 0.0);
- gtk_tree_path_free (path);
-
- re->current = re->edit;
- rule_context_add_rule (re->context, re->current);
-
- g_object_ref (re->current);
- rule_editor_add_undo (re, RULE_EDITOR_LOG_ADD, re->current,
- rule_context_get_rank_rule (re->context, re->current, re->current->source), 0);
- }
-
- gtk_widget_destroy (dialog);
-}
-
-static void
-rule_add (GtkWidget *widget, RuleEditor *re)
-{
- GtkWidget *rules;
- GtkWidget *content_area;
-
- if (re->edit != NULL)
- return;
-
- re->edit = rule_editor_create_rule (re);
- filter_rule_set_source (re->edit, re->source);
- rules = filter_rule_get_widget (re->edit, re->context);
-
- re->dialog = gtk_dialog_new ();
- gtk_dialog_add_buttons ((GtkDialog *) re->dialog,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- NULL);
- gtk_dialog_set_has_separator ((GtkDialog *) re->dialog, FALSE);
-
- gtk_window_set_title ((GtkWindow *) re->dialog, _("Add Rule"));
- gtk_window_set_default_size (GTK_WINDOW (re->dialog), 650, 400);
- gtk_window_set_resizable (GTK_WINDOW (re->dialog), TRUE);
- gtk_window_set_transient_for ((GtkWindow *) re->dialog, (GtkWindow *) re);
- gtk_container_set_border_width ((GtkContainer *) re->dialog, 6);
-
- content_area = gtk_dialog_get_content_area (GTK_DIALOG (re->dialog));
- gtk_box_pack_start (GTK_BOX (content_area), rules, TRUE, TRUE, 3);
-
- g_signal_connect (re->dialog, "response", G_CALLBACK (add_editor_response), re);
- g_object_weak_ref ((GObject *) re->dialog, (GWeakNotify) editor_destroy, re);
-
- g_signal_connect (re->edit, "changed", G_CALLBACK (dialog_rule_changed), re->dialog);
- dialog_rule_changed (re->edit, re->dialog);
-
- gtk_widget_set_sensitive (GTK_WIDGET (re), FALSE);
-
- gtk_widget_show (re->dialog);
-}
-
-static void
-edit_editor_response (GtkWidget *dialog, gint button, RuleEditor *re)
-{
- FilterRule *rule;
- GtkTreePath *path;
- GtkTreeIter iter;
- gint pos;
-
- if (button == GTK_RESPONSE_OK) {
- if (!filter_rule_validate (re->edit, GTK_WINDOW (dialog))) {
- /* no need to popup a dialog because the validate code does that. */
- return;
- }
-
- rule = rule_context_find_rule (re->context, re->edit->name, re->edit->source);
- if (rule != NULL && rule != re->current) {
- e_error_run ((GtkWindow *)dialog, "filter:bad-name-notunique", rule->name, NULL);
-
- return;
- }
-
- pos = rule_context_get_rank_rule (re->context, re->current, re->source);
- if (pos != -1) {
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, pos);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (re->model), &iter, path);
- gtk_tree_path_free (path);
-
- gtk_list_store_set (re->model, &iter, 0, re->edit->name, -1);
-
- rule_editor_add_undo (re, RULE_EDITOR_LOG_EDIT, filter_rule_clone (re->current),
- pos, 0);
-
- /* replace the old rule with the new rule */
- filter_rule_copy (re->current, re->edit);
- }
- }
-
- gtk_widget_destroy (dialog);
-}
-
-static void
-rule_edit (GtkWidget *widget, RuleEditor *re)
-{
- GtkWidget *rules;
- GtkWidget *content_area;
-
- update_selected_rule(re);
-
- if (re->current == NULL || re->edit != NULL)
- return;
-
- re->edit = filter_rule_clone (re->current);
-
- rules = filter_rule_get_widget (re->edit, re->context);
-
- re->dialog = gtk_dialog_new ();
- gtk_dialog_add_buttons ((GtkDialog *) re->dialog,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- NULL);
- gtk_dialog_set_has_separator ((GtkDialog *) re->dialog, FALSE);
-
- gtk_window_set_title ((GtkWindow *) re->dialog, _("Edit Rule"));
- gtk_window_set_default_size (GTK_WINDOW (re->dialog), 650, 400);
- gtk_window_set_resizable (GTK_WINDOW (re->dialog), TRUE);
- gtk_widget_set_parent_window (GTK_WIDGET (re->dialog), GTK_WIDGET (re)->window);
- gtk_container_set_border_width ((GtkContainer *) re->dialog, 6);
-
- content_area = gtk_dialog_get_content_area (GTK_DIALOG (re->dialog));
- gtk_box_pack_start (GTK_BOX (content_area), rules, TRUE, TRUE, 3);
-
- g_signal_connect (re->dialog, "response", G_CALLBACK (edit_editor_response), re);
- g_object_weak_ref ((GObject *) re->dialog, (GWeakNotify) editor_destroy, re);
-
- g_signal_connect (re->edit, "changed", G_CALLBACK (dialog_rule_changed), re->dialog);
- dialog_rule_changed (re->edit, re->dialog);
-
- gtk_widget_set_sensitive (GTK_WIDGET (re), FALSE);
-
- gtk_widget_show (re->dialog);
-}
-
-static void
-rule_delete (GtkWidget *widget, RuleEditor *re)
-{
- GtkTreeSelection *selection;
- GtkTreePath *path;
- GtkTreeIter iter;
- gint pos, len;
-
- update_selected_rule(re);
-
- d(printf ("delete rule\n"));
- pos = rule_context_get_rank_rule (re->context, re->current, re->source);
- if (pos != -1) {
- rule_context_remove_rule (re->context, re->current);
-
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, pos);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (re->model), &iter, path);
- gtk_list_store_remove (re->model, &iter);
- gtk_tree_path_free (path);
-
- rule_editor_add_undo (re, RULE_EDITOR_LOG_REMOVE, re->current,
- rule_context_get_rank_rule (re->context, re->current, re->current->source), 0);
-#if 0
- g_object_unref (re->current);
-#endif
- re->current = NULL;
-
- /* now select the next rule */
- len = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (re->model), NULL);
- pos = pos >= len ? len - 1 : pos;
-
- if (pos >= 0) {
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, pos);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (re->model), &iter, path);
- gtk_tree_path_free (path);
-
- /* select the new row */
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (re->list));
- gtk_tree_selection_select_iter (selection, &iter);
-
- /* scroll to the selected row */
- path = gtk_tree_model_get_path ((GtkTreeModel *) re->model, &iter);
- gtk_tree_view_scroll_to_cell (re->list, path, NULL, FALSE, 0.0, 0.0);
- gtk_tree_path_free (path);
-
- /* update our selection state */
- cursor_changed (re->list, re);
- return;
- }
- }
-
- rule_editor_set_sensitive (re);
-}
-
-static void
-rule_move (RuleEditor *re, gint from, gint to)
-{
- GtkTreeSelection *selection;
- GtkTreePath *path;
- GtkTreeIter iter;
- FilterRule *rule;
-
- g_object_ref (re->current);
- rule_editor_add_undo (re, RULE_EDITOR_LOG_RANK, re->current,
- rule_context_get_rank_rule (re->context, re->current, re->source), to);
-
- d(printf ("moving %d to %d\n", from, to));
- rule_context_rank_rule (re->context, re->current, re->source, to);
-
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, from);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (re->model), &iter, path);
- gtk_tree_path_free (path);
-
- gtk_tree_model_get (GTK_TREE_MODEL (re->model), &iter, 1, &rule, -1);
- g_return_if_fail (rule != NULL);
-
- /* remove and then re-insert the row at the new location */
- gtk_list_store_remove (re->model, &iter);
- gtk_list_store_insert (re->model, &iter, to);
-
- /* set the data on the row */
- gtk_list_store_set (re->model, &iter, 0, rule->name, 1, rule, 2, rule->enabled, -1);
-
- /* select the row */
- selection = gtk_tree_view_get_selection (re->list);
- gtk_tree_selection_select_iter (selection, &iter);
-
- /* scroll to the selected row */
- path = gtk_tree_model_get_path ((GtkTreeModel *) re->model, &iter);
- gtk_tree_view_scroll_to_cell (re->list, path, NULL, FALSE, 0.0, 0.0);
- gtk_tree_path_free (path);
-
- rule_editor_set_sensitive (re);
-}
-
-static void
-rule_top (GtkWidget *widget, RuleEditor *re)
-{
- gint pos;
-
- update_selected_rule(re);
-
- d(printf ("top rule\n"));
- pos = rule_context_get_rank_rule (re->context, re->current, re->source);
- if (pos > 0)
- rule_move (re, pos, 0);
-}
-
-static void
-rule_up (GtkWidget *widget, RuleEditor *re)
-{
- gint pos;
-
- update_selected_rule(re);
-
- d(printf ("up rule\n"));
- pos = rule_context_get_rank_rule (re->context, re->current, re->source);
- if (pos > 0)
- rule_move (re, pos, pos - 1);
-}
-
-static void
-rule_down (GtkWidget *widget, RuleEditor *re)
-{
- gint pos;
-
- update_selected_rule(re);
-
- d(printf ("down rule\n"));
- pos = rule_context_get_rank_rule (re->context, re->current, re->source);
- if (pos >= 0)
- rule_move (re, pos, pos + 1);
-}
-
-static void
-rule_bottom (GtkWidget *widget, RuleEditor *re)
-{
- gint pos;
- gint index = -1, count = 0;
- FilterRule *rule = NULL;
-
- update_selected_rule(re);
-
- d(printf ("bottom rule\n"));
- pos = rule_context_get_rank_rule (re->context, re->current, re->source);
- /* There's probably a better/faster way to get the count of the list here */
- while ((rule = rule_context_next_rule (re->context, rule, re->source))) {
- if (rule == re->current)
- index = count;
- count++;
- }
- count--;
- if (pos >= 0)
- rule_move (re, pos, count);
-}
-
-static struct {
- const gchar *name;
- GCallback func;
-} edit_buttons[] = {
- { "rule_add", G_CALLBACK (rule_add) },
- { "rule_edit", G_CALLBACK (rule_edit) },
- { "rule_delete", G_CALLBACK (rule_delete) },
- { "rule_top", G_CALLBACK (rule_top) },
- { "rule_up", G_CALLBACK (rule_up) },
- { "rule_down", G_CALLBACK (rule_down) },
- { "rule_bottom", G_CALLBACK (rule_bottom) },
-};
-
-static void
-set_sensitive (RuleEditor *re)
-{
- FilterRule *rule = NULL;
- gint index = -1, count = 0;
-
- while ((rule = rule_context_next_rule (re->context, rule, re->source))) {
- if (rule == re->current)
- index = count;
- count++;
- }
-
- d(printf("index = %d count=%d\n", index, count));
-
- count--;
-
- gtk_widget_set_sensitive (GTK_WIDGET (re->priv->buttons[BUTTON_EDIT]), index != -1);
- gtk_widget_set_sensitive (GTK_WIDGET (re->priv->buttons[BUTTON_DELETE]), index != -1);
- gtk_widget_set_sensitive (GTK_WIDGET (re->priv->buttons[BUTTON_TOP]), index > 0);
- gtk_widget_set_sensitive (GTK_WIDGET (re->priv->buttons[BUTTON_UP]), index > 0);
- gtk_widget_set_sensitive (GTK_WIDGET (re->priv->buttons[BUTTON_DOWN]), index >= 0 && index < count);
- gtk_widget_set_sensitive (GTK_WIDGET (re->priv->buttons[BUTTON_BOTTOM]), index >= 0 && index < count);
-}
-
-static void
-dialog_rule_changed (FilterRule *fr, GtkWidget *dialog)
-{
- g_return_if_fail (dialog != NULL);
-
- gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, fr && fr->parts);
-}
-
-static gboolean
-update_selected_rule (RuleEditor *re)
-{
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- selection = gtk_tree_view_get_selection (re->list);
- if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
- gtk_tree_model_get (GTK_TREE_MODEL (re->model), &iter, 1, &re->current, -1);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-cursor_changed (GtkTreeView *treeview, RuleEditor *re)
-{
- if (update_selected_rule(re)) {
- g_return_if_fail (re->current);
-
- rule_editor_set_sensitive (re);
- }
-}
-
-static void
-double_click (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, RuleEditor *re)
-{
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- selection = gtk_tree_view_get_selection (re->list);
- if (gtk_tree_selection_get_selected (selection, &model, &iter))
- gtk_tree_model_get (GTK_TREE_MODEL (re->model), &iter, 1, &re->current, -1);
-
- if (re->current)
- rule_edit ((GtkWidget *) treeview, re);
-}
-
-static void
-set_source (RuleEditor *re, const gchar *source)
-{
- FilterRule *rule = NULL;
- GtkTreeIter iter;
-
- gtk_list_store_clear (re->model);
-
- d(printf("Checking for rules that are of type %s\n", source ? source : "<nil>"));
- while ((rule = rule_context_next_rule (re->context, rule, source)) != NULL) {
- d(printf("Adding row '%s'\n", rule->name));
- gtk_list_store_append (re->model, &iter);
- gtk_list_store_set (re->model, &iter, 0, rule->name, 1, rule, 2, rule->enabled, -1);
- }
-
- g_free (re->source);
- re->source = g_strdup (source);
- re->current = NULL;
- rule_editor_set_sensitive (re);
-}
-
-static void
-rule_able_toggled (GtkCellRendererToggle *renderer, gchar *arg1, gpointer user_data)
-{
- GtkWidget *table = user_data;
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
-
- path = gtk_tree_path_new_from_string (arg1);
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (table));
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (table));
-
- if (gtk_tree_model_get_iter (model, &iter, path)) {
- FilterRule *rule = NULL;
-
- gtk_tree_model_get (model, &iter, 1, &rule, -1);
-
- if (rule) {
- rule->enabled = !rule->enabled;
- gtk_list_store_set (GTK_LIST_STORE (model), &iter, 2, rule->enabled, -1);
- }
- }
-
- gtk_tree_path_free (path);
-}
-
-GtkWidget *rule_editor_treeview_new (gchar *widget_name, gchar *string1, gchar *string2,
- gint int1, gint int2);
-
-GtkWidget *
-rule_editor_treeview_new (gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2)
-{
- GtkWidget *table, *scrolled;
- GtkTreeSelection *selection;
- GtkCellRenderer *renderer;
- GtkListStore *model;
- GtkTreeViewColumn *column;
-
- scrolled = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN);
- table = gtk_tree_view_new_with_model ((GtkTreeModel *) model);
- gtk_tree_view_set_headers_visible ((GtkTreeView *) table, FALSE);
-
- renderer = gtk_cell_renderer_toggle_new ();
- g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
- gtk_tree_view_insert_column_with_attributes ((GtkTreeView *) table, -1,
- _("Enabled"), renderer,
- "active", 2, NULL);
- g_signal_connect (renderer, "toggled", G_CALLBACK (rule_able_toggled), table);
-
- /* hide enable column by default */
- column = gtk_tree_view_get_column (GTK_TREE_VIEW (table), 0);
- gtk_tree_view_column_set_visible (column, FALSE);
-
- renderer = gtk_cell_renderer_text_new ();
- gtk_tree_view_insert_column_with_attributes ((GtkTreeView *) table, -1,
- _("Rule name"), renderer,
- "text", 0, NULL);
-
- selection = gtk_tree_view_get_selection ((GtkTreeView *) table);
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
-
- gtk_container_add (GTK_CONTAINER (scrolled), table);
-
- g_object_set_data ((GObject *) scrolled, "table", table);
- g_object_set_data ((GObject *) scrolled, "model", model);
-
- gtk_widget_show (scrolled);
- gtk_widget_show (table);
-
- g_object_unref (model);
-
- return scrolled;
-}
-
-void
-rule_editor_construct (RuleEditor *re, RuleContext *context, GladeXML *gui, const gchar *source, const gchar *label)
-{
- GtkWidget *w;
- GtkWidget *action_area;
- GtkWidget *content_area;
- gint i;
- gchar *tmp;
-
- re->context = context;
- g_object_ref (context);
-
- action_area = gtk_dialog_get_action_area (GTK_DIALOG (re));
- content_area = gtk_dialog_get_content_area (GTK_DIALOG (re));
-
- gtk_window_set_resizable ((GtkWindow *) re, TRUE);
- gtk_window_set_default_size ((GtkWindow *) re, 350, 400);
- gtk_widget_realize ((GtkWidget *) re);
- gtk_container_set_border_width (GTK_CONTAINER (action_area), 12);
-
- w = glade_xml_get_widget(gui, "rule_editor");
- gtk_box_pack_start (GTK_BOX (content_area), w, TRUE, TRUE, 3);
-
- for (i = 0; i < BUTTON_LAST; i++) {
- re->priv->buttons[i] = (GtkButton *) (w = glade_xml_get_widget (gui, edit_buttons[i].name));
- g_signal_connect (w, "clicked", edit_buttons[i].func, re);
- }
-
- w = glade_xml_get_widget (gui, "rule_list");
- re->list = (GtkTreeView *) g_object_get_data ((GObject *) w, "table");
- re->model = (GtkListStore *) g_object_get_data ((GObject *) w, "model");
-
- g_signal_connect (re->list, "cursor-changed", G_CALLBACK (cursor_changed), re);
- g_signal_connect (re->list, "row-activated", G_CALLBACK (double_click), re);
-
- w = glade_xml_get_widget (gui, "rule_label");
- tmp = alloca(strlen(label)+8);
- sprintf(tmp, "<b>%s</b>", label);
- gtk_label_set_label((GtkLabel *)w, tmp);
- gtk_label_set_mnemonic_widget ((GtkLabel *) w, (GtkWidget *) re->list);
-
- g_signal_connect (re, "response", G_CALLBACK (editor_response), re);
- rule_editor_set_source (re, source);
-
- gtk_dialog_set_has_separator ((GtkDialog *) re, FALSE);
- gtk_dialog_add_buttons ((GtkDialog *) re,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- NULL);
-}
diff --git a/filter/rule-editor.h b/filter/rule-editor.h
deleted file mode 100644
index e5017eac25..0000000000
--- a/filter/rule-editor.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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; either
- * version 2 of the License, or (at your option) version 3.
- *
- * 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Authors:
- * Not Zed <notzed@lostzed.mmc.com.au>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#ifndef _RULE_EDITOR_H
-#define _RULE_EDITOR_H
-
-#include <gtk/gtk.h>
-#include <glade/glade.h>
-
-#include "rule-context.h"
-#include "filter-rule.h"
-
-#define RULE_TYPE_EDITOR (rule_editor_get_type ())
-#define RULE_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RULE_TYPE_EDITOR, RuleEditor))
-#define RULE_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RULE_TYPE_EDITOR, RuleEditorClass))
-#define IS_RULE_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RULE_TYPE_EDITOR))
-#define IS_RULE_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RULE_TYPE_EDITOR))
-#define RULE_EDITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RULE_TYPE_EDITOR, RuleEditorClass))
-
-typedef struct _RuleEditor RuleEditor;
-typedef struct _RuleEditorClass RuleEditorClass;
-typedef struct _RuleEditorUndo RuleEditorUndo;
-
-struct _RuleEditor {
- GtkDialog parent_object;
-
- GtkListStore *model;
- GtkTreeView *list;
-
- RuleContext *context;
- FilterRule *current;
- FilterRule *edit; /* for editing/adding rules, so we only do 1 at a time */
-
- GtkWidget *dialog;
-
- gchar *source;
-
- struct _RuleEditorUndo *undo_log; /* cancel/undo log */
- guint undo_active:1; /* we're performing undo */
-
- struct _RuleEditorPrivate *priv;
-};
-
-struct _RuleEditorClass {
- GtkDialogClass parent_class;
-
- /* virtual methods */
- void (*set_sensitive) (RuleEditor *);
- void (*set_source) (RuleEditor *, const gchar *source);
-
- FilterRule *(*create_rule) (RuleEditor *);
-
- /* signals */
-};
-
-enum {
- RULE_EDITOR_LOG_EDIT,
- RULE_EDITOR_LOG_ADD,
- RULE_EDITOR_LOG_REMOVE,
- RULE_EDITOR_LOG_RANK
-};
-
-struct _RuleEditorUndo {
- struct _RuleEditorUndo *next;
-
- guint type;
- FilterRule *rule;
- gint rank;
- gint newrank;
-};
-
-GType rule_editor_get_type(void);
-RuleEditor *rule_editor_new(RuleContext *rc, const gchar *source, const gchar *label);
-
-void rule_editor_construct(RuleEditor *re, RuleContext *context, GladeXML *gui, const gchar *source, const gchar *label);
-
-/* methods */
-void rule_editor_set_source(RuleEditor *re, const gchar *source);
-/* calculates the sensitivity of the editor */
-void rule_editor_set_sensitive(RuleEditor *re);
-/* used internally to create a new rule appropriate for the editor */
-struct _FilterRule *rule_editor_create_rule(RuleEditor *re);
-
-#endif /* ! _RULE_EDITOR_H */
diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c
index 26c4052736..3cfc3b3e87 100644
--- a/mail/e-mail-reader-utils.c
+++ b/mail/e-mail-reader-utils.c
@@ -30,7 +30,7 @@
#include <camel/camel-vee-store.h>
#include "e-util/e-error.h"
-#include "filter/filter-rule.h"
+#include "filter/e-filter-rule.h"
#include "mail/e-mail-browser.h"
#include "mail/em-composer-utils.h"
@@ -509,11 +509,11 @@ e_mail_reader_create_filter_from_selected (EMailReader *reader,
folder_uri = message_list->folder_uri;
if (em_utils_folder_is_sent (folder, folder_uri))
- filter_source = FILTER_SOURCE_OUTGOING;
+ filter_source = E_FILTER_SOURCE_OUTGOING;
else if (em_utils_folder_is_outbox (folder, folder_uri))
- filter_source = FILTER_SOURCE_OUTGOING;
+ filter_source = E_FILTER_SOURCE_OUTGOING;
else
- filter_source = FILTER_SOURCE_INCOMING;
+ filter_source = E_FILTER_SOURCE_INCOMING;
uids = message_list_get_selected (message_list);
diff --git a/mail/em-filter-context.c b/mail/em-filter-context.c
index 4817d896b5..7c17e694e8 100644
--- a/mail/em-filter-context.c
+++ b/mail/em-filter-context.c
@@ -29,8 +29,8 @@
#include "em-filter-context.h"
#include "em-filter-rule.h"
-#include "filter/filter-option.h"
-#include "filter/filter-int.h"
+#include "filter/e-filter-option.h"
+#include "filter/e-filter-int.h"
#include "em-filter-source-element.h"
/* For poking into filter-folder guts */
@@ -42,11 +42,11 @@ static void em_filter_context_class_init(EMFilterContextClass *klass);
static void em_filter_context_init(EMFilterContext *fc);
static void em_filter_context_finalise(GObject *obj);
-static GList *filter_rename_uri(RuleContext *rc, const gchar *olduri, const gchar *newuri, GCompareFunc cmp);
-static GList *filter_delete_uri(RuleContext *rc, const gchar *uri, GCompareFunc cmp);
-static FilterElement *filter_new_element(RuleContext *rc, const gchar *name);
+static GList *filter_rename_uri(ERuleContext *rc, const gchar *olduri, const gchar *newuri, GCompareFunc cmp);
+static GList *filter_delete_uri(ERuleContext *rc, const gchar *uri, GCompareFunc cmp);
+static EFilterElement *filter_new_element(ERuleContext *rc, const gchar *name);
-static RuleContextClass *parent_class = NULL;
+static ERuleContextClass *parent_class = NULL;
GType
em_filter_context_get_type(void)
@@ -66,7 +66,7 @@ em_filter_context_get_type(void)
(GInstanceInitFunc) em_filter_context_init,
};
- type = g_type_register_static(RULE_TYPE_CONTEXT, "EMFilterContext", &info, 0);
+ type = g_type_register_static(E_TYPE_RULE_CONTEXT, "EMFilterContext", &info, 0);
}
return type;
@@ -76,9 +76,9 @@ static void
em_filter_context_class_init(EMFilterContextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
- RuleContextClass *rc_class = RULE_CONTEXT_CLASS(klass);
+ ERuleContextClass *rc_class = E_RULE_CONTEXT_CLASS(klass);
- parent_class = g_type_class_ref(RULE_TYPE_CONTEXT);
+ parent_class = g_type_class_ref(E_TYPE_RULE_CONTEXT);
object_class->finalize = em_filter_context_finalise;
@@ -91,14 +91,14 @@ em_filter_context_class_init(EMFilterContextClass *klass)
static void
em_filter_context_init(EMFilterContext *fc)
{
- rule_context_add_part_set((RuleContext *) fc, "partset", filter_part_get_type(),
- rule_context_add_part, rule_context_next_part);
- rule_context_add_part_set((RuleContext *) fc, "actionset", filter_part_get_type(),
- (RCPartFunc) em_filter_context_add_action,
- (RCNextPartFunc) em_filter_context_next_action);
-
- rule_context_add_rule_set((RuleContext *) fc, "ruleset", em_filter_rule_get_type(),
- (RCRuleFunc) rule_context_add_rule, rule_context_next_rule);
+ e_rule_context_add_part_set((ERuleContext *) fc, "partset", e_filter_part_get_type(),
+ e_rule_context_add_part, e_rule_context_next_part);
+ e_rule_context_add_part_set((ERuleContext *) fc, "actionset", e_filter_part_get_type(),
+ (ERuleContextPartFunc) em_filter_context_add_action,
+ (ERuleContextNextPartFunc) em_filter_context_next_action);
+
+ e_rule_context_add_rule_set((ERuleContext *) fc, "ruleset", em_filter_rule_get_type(),
+ (ERuleContextRuleFunc) e_rule_context_add_rule, e_rule_context_next_rule);
}
static void
@@ -126,44 +126,44 @@ em_filter_context_new(void)
}
void
-em_filter_context_add_action(EMFilterContext *fc, FilterPart *action)
+em_filter_context_add_action(EMFilterContext *fc, EFilterPart *action)
{
d(printf("find action : "));
fc->actions = g_list_append(fc->actions, action);
}
-FilterPart *
+EFilterPart *
em_filter_context_find_action(EMFilterContext *fc, const gchar *name)
{
d(printf("find action : "));
- return filter_part_find_list(fc->actions, name);
+ return e_filter_part_find_list(fc->actions, name);
}
-FilterPart *
+EFilterPart *
em_filter_context_create_action(EMFilterContext *fc, const gchar *name)
{
- FilterPart *part;
+ EFilterPart *part;
if ((part = em_filter_context_find_action(fc, name)))
- return filter_part_clone(part);
+ return e_filter_part_clone(part);
return NULL;
}
-FilterPart *
-em_filter_context_next_action(EMFilterContext *fc, FilterPart *last)
+EFilterPart *
+em_filter_context_next_action(EMFilterContext *fc, EFilterPart *last)
{
- return filter_part_next_list(fc->actions, last);
+ return e_filter_part_next_list(fc->actions, last);
}
/* We search for any folders in our actions list that need updating, update them */
static GList *
-filter_rename_uri(RuleContext *rc, const gchar *olduri, const gchar *newuri, GCompareFunc cmp)
+filter_rename_uri(ERuleContext *rc, const gchar *olduri, const gchar *newuri, GCompareFunc cmp)
{
- FilterRule *rule;
+ EFilterRule *rule;
GList *l, *el;
- FilterPart *action;
- FilterElement *element;
+ EFilterPart *action;
+ EFilterElement *element;
gint count = 0;
GList *changed = NULL;
@@ -172,7 +172,7 @@ filter_rename_uri(RuleContext *rc, const gchar *olduri, const gchar *newuri, GCo
/* For all rules, for all actions, for all elements, rename any folder elements */
/* Yes we could do this inside each part itself, but not today */
rule = NULL;
- while ((rule = rule_context_next_rule(rc, rule, NULL))) {
+ while ((rule = e_rule_context_next_rule(rc, rule, NULL))) {
gint rulecount = 0;
d(printf("checking rule '%s'\n", rule->name));
@@ -206,7 +206,7 @@ filter_rename_uri(RuleContext *rc, const gchar *olduri, const gchar *newuri, GCo
if (rulecount) {
changed = g_list_append(changed, g_strdup(rule->name));
- filter_rule_emit_changed(rule);
+ e_filter_rule_emit_changed(rule);
}
count += rulecount;
@@ -218,15 +218,15 @@ filter_rename_uri(RuleContext *rc, const gchar *olduri, const gchar *newuri, GCo
}
static GList *
-filter_delete_uri(RuleContext *rc, const gchar *uri, GCompareFunc cmp)
+filter_delete_uri(ERuleContext *rc, const gchar *uri, GCompareFunc cmp)
{
/* We basically do similar to above, but when we find it,
Remove the action, and if thats the last action, this might create an empty rule? remove the rule? */
- FilterRule *rule;
+ EFilterRule *rule;
GList *l, *el;
- FilterPart *action;
- FilterElement *element;
+ EFilterPart *action;
+ EFilterElement *element;
gint count = 0;
GList *deleted = NULL;
@@ -235,7 +235,7 @@ filter_delete_uri(RuleContext *rc, const gchar *uri, GCompareFunc cmp)
/* For all rules, for all actions, for all elements, check deleted folder elements */
/* Yes we could do this inside each part itself, but not today */
rule = NULL;
- while ((rule = rule_context_next_rule(rc, rule, NULL))) {
+ while ((rule = e_rule_context_next_rule(rc, rule, NULL))) {
gint recorded = 0;
d(printf("checking rule '%s'\n", rule->name));
@@ -281,17 +281,17 @@ filter_delete_uri(RuleContext *rc, const gchar *uri, GCompareFunc cmp)
return deleted;
}
-static FilterElement *
-filter_new_element(RuleContext *rc, const gchar *type)
+static EFilterElement *
+filter_new_element(ERuleContext *rc, const gchar *type)
{
if (!strcmp(type, "folder")) {
- return (FilterElement *) em_filter_folder_element_new();
+ return (EFilterElement *) em_filter_folder_element_new();
} else if (!strcmp(type, "system-flag")) {
- return (FilterElement *) filter_option_new();
+ return (EFilterElement *) e_filter_option_new();
} else if (!strcmp(type, "score")) {
- return (FilterElement *) filter_int_new_type("score", -3, 3);
+ return (EFilterElement *) e_filter_int_new_type("score", -3, 3);
} else if (!strcmp(type, "source")) {
- return (FilterElement *) em_filter_source_element_new();
+ return (EFilterElement *) em_filter_source_element_new();
} else {
return parent_class->new_element(rc, type);
}
diff --git a/mail/em-filter-context.h b/mail/em-filter-context.h
index 31431b4a34..d5eda2ab21 100644
--- a/mail/em-filter-context.h
+++ b/mail/em-filter-context.h
@@ -25,7 +25,7 @@
#ifndef _EM_FILTER_CONTEXT_H
#define _EM_FILTER_CONTEXT_H
-#include "filter/rule-context.h"
+#include "filter/e-rule-context.h"
#define EM_TYPE_FILTER_CONTEXT (em_filter_context_get_type ())
#define EM_FILTER_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FILTER_TYPE_CONTEXT, EMFilterContext))
@@ -38,22 +38,22 @@ typedef struct _EMFilterContext EMFilterContext;
typedef struct _EMFilterContextClass EMFilterContextClass;
struct _EMFilterContext {
- RuleContext parent_object;
+ ERuleContext parent_object;
GList *actions;
};
struct _EMFilterContextClass {
- RuleContextClass parent_class;
+ ERuleContextClass parent_class;
};
GType em_filter_context_get_type (void);
EMFilterContext *em_filter_context_new (void);
/* methods */
-void em_filter_context_add_action (EMFilterContext *fc, FilterPart *action);
-FilterPart *em_filter_context_find_action (EMFilterContext *fc, const gchar *name);
-FilterPart *em_filter_context_create_action (EMFilterContext *fc, const gchar *name);
-FilterPart *em_filter_context_next_action (EMFilterContext *fc, FilterPart *last);
+void em_filter_context_add_action (EMFilterContext *fc, EFilterPart *action);
+EFilterPart *em_filter_context_find_action (EMFilterContext *fc, const gchar *name);
+EFilterPart *em_filter_context_create_action (EMFilterContext *fc, const gchar *name);
+EFilterPart *em_filter_context_next_action (EMFilterContext *fc, EFilterPart *last);
#endif /* ! _EM_FILTER_CONTEXT_H */
diff --git a/mail/em-filter-editor.c b/mail/em-filter-editor.c
index f4271bf6e0..c0e5725e77 100644
--- a/mail/em-filter-editor.c
+++ b/mail/em-filter-editor.c
@@ -36,20 +36,20 @@
static gpointer parent_class;
-static FilterRule *
-filter_editor_create_rule (RuleEditor *rule_editor)
+static EFilterRule *
+filter_editor_create_rule (ERuleEditor *rule_editor)
{
- FilterRule *rule = filter_rule_new ();
- FilterPart *part;
+ EFilterRule *rule = e_filter_rule_new ();
+ EFilterPart *part;
/* create a rule with 1 part & 1 action in it */
- rule = (FilterRule *)em_filter_rule_new ();
- part = rule_context_next_part (rule_editor->context, NULL);
- filter_rule_add_part (rule, filter_part_clone (part));
+ rule = (EFilterRule *)em_filter_rule_new ();
+ part = e_rule_context_next_part (rule_editor->context, NULL);
+ e_filter_rule_add_part (rule, e_filter_part_clone (part));
part = em_filter_context_next_action (
(EMFilterContext *)rule_editor->context, NULL);
em_filter_rule_add_action (
- (EMFilterRule *)rule, filter_part_clone (part));
+ (EMFilterRule *)rule, e_filter_part_clone (part));
return rule;
}
@@ -57,11 +57,11 @@ filter_editor_create_rule (RuleEditor *rule_editor)
static void
filter_editor_class_init (EMFilterEditorClass *class)
{
- RuleEditorClass *rule_editor_class;
+ ERuleEditorClass *rule_editor_class;
parent_class = g_type_class_peek_parent (class);
- rule_editor_class = RULE_EDITOR_CLASS (class);
+ rule_editor_class = E_RULE_EDITOR_CLASS (class);
rule_editor_class->create_rule = filter_editor_create_rule;
}
@@ -98,7 +98,7 @@ em_filter_editor_get_type (void)
};
type = g_type_register_static (
- RULE_TYPE_EDITOR, "EMFilterEditor", &type_info, 0);
+ E_TYPE_RULE_EDITOR, "EMFilterEditor", &type_info, 0);
}
return type;
@@ -158,7 +158,7 @@ select_source (GtkComboBox *combobox, EMFilterEditor *fe)
source = (gchar *) (g_slist_nth (sources, idx))->data;
g_return_if_fail (source);
- rule_editor_set_source ((RuleEditor *)fe, source);
+ e_rule_editor_set_source ((ERuleEditor *)fe, source);
}
void
@@ -185,9 +185,9 @@ em_filter_editor_construct (EMFilterEditor *fe,
g_object_set_data_full (G_OBJECT (combobox), "sources", sources, free_sources);
gtk_widget_show (combobox);
- rule_editor_construct ((RuleEditor *) fe, (RuleContext *) fc, gui, source_names[0].source, _("_Filter Rules"));
+ e_rule_editor_construct ((ERuleEditor *) fe, (ERuleContext *) fc, gui, source_names[0].source, _("_Filter Rules"));
/* Show the Enabled column, we support it here */
- column = gtk_tree_view_get_column (GTK_TREE_VIEW (RULE_EDITOR (fe)->list), 0);
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW (E_RULE_EDITOR (fe)->list), 0);
gtk_tree_view_column_set_visible (column, TRUE);
}
diff --git a/mail/em-filter-editor.h b/mail/em-filter-editor.h
index c725fd97b5..e70b346d02 100644
--- a/mail/em-filter-editor.h
+++ b/mail/em-filter-editor.h
@@ -25,7 +25,7 @@
#ifndef EM_FILTER_EDITOR_H
#define EM_FILTER_EDITOR_H
-#include "filter/rule-editor.h"
+#include "filter/e-rule-editor.h"
#include "em-filter-context.h"
/* Standard GObject macros */
@@ -60,11 +60,11 @@ struct _EMFilterSource {
};
struct _EMFilterEditor {
- RuleEditor parent;
+ ERuleEditor parent;
};
struct _EMFilterEditorClass {
- RuleEditorClass parent_class;
+ ERuleEditorClass parent_class;
};
GType em_filter_editor_get_type (void);
diff --git a/mail/em-filter-folder-element.c b/mail/em-filter-folder-element.c
index 8e07ef9c8c..b705bbde25 100644
--- a/mail/em-filter-folder-element.c
+++ b/mail/em-filter-folder-element.c
@@ -34,26 +34,27 @@
#include "em-filter-folder-element.h"
#include "mail/em-folder-selection-button.h"
#include "mail/em-utils.h"
+#include "filter/e-filter-part.h"
#include "libedataserver/e-sexp.h"
#include "e-util/e-error.h"
#define d(x)
-static gboolean validate(FilterElement *fe, GtkWindow *error_parent);
-static gint folder_eq(FilterElement *fe, FilterElement *cm);
-static void xml_create(FilterElement *fe, xmlNodePtr node);
-static xmlNodePtr xml_encode(FilterElement *fe);
-static gint 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 *, GString *);
-static void emff_copy_value(FilterElement *de, FilterElement *se);
+static gboolean validate(EFilterElement *fe, GtkWindow *error_parent);
+static gint folder_eq(EFilterElement *fe, EFilterElement *cm);
+static void xml_create(EFilterElement *fe, xmlNodePtr node);
+static xmlNodePtr xml_encode(EFilterElement *fe);
+static gint xml_decode(EFilterElement *fe, xmlNodePtr node);
+static GtkWidget *get_widget(EFilterElement *fe);
+static void build_code(EFilterElement *fe, GString *out, EFilterPart *ff);
+static void format_sexp(EFilterElement *, GString *);
+static void emff_copy_value(EFilterElement *de, EFilterElement *se);
static void em_filter_folder_element_class_init(EMFilterFolderElementClass *class);
static void em_filter_folder_element_init(EMFilterFolderElement *ff);
static void em_filter_folder_element_finalise(GObject *obj);
-static FilterElementClass *parent_class = NULL;
+static EFilterElementClass *parent_class = NULL;
GType
em_filter_folder_element_get_type(void)
@@ -73,7 +74,7 @@ em_filter_folder_element_get_type(void)
(GInstanceInitFunc)em_filter_folder_element_init,
};
- type = g_type_register_static(FILTER_TYPE_ELEMENT, "EMFilterFolderElement", &info, 0);
+ type = g_type_register_static(E_TYPE_FILTER_ELEMENT, "EMFilterFolderElement", &info, 0);
}
return type;
@@ -83,9 +84,9 @@ static void
em_filter_folder_element_class_init(EMFilterFolderElementClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
- FilterElementClass *fe_class = FILTER_ELEMENT_CLASS(klass);
+ EFilterElementClass *fe_class = E_FILTER_ELEMENT_CLASS(klass);
- parent_class = g_type_class_ref(FILTER_TYPE_ELEMENT);
+ parent_class = g_type_class_ref(E_TYPE_FILTER_ELEMENT);
object_class->finalize = em_filter_folder_element_finalise;
@@ -138,7 +139,7 @@ em_filter_folder_element_set_value(EMFilterFolderElement *ff, const gchar *uri)
}
static gboolean
-validate(FilterElement *fe, GtkWindow *error_parent)
+validate(EFilterElement *fe, GtkWindow *error_parent)
{
EMFilterFolderElement *ff = (EMFilterFolderElement *)fe;
@@ -152,21 +153,21 @@ validate(FilterElement *fe, GtkWindow *error_parent)
}
static gint
-folder_eq(FilterElement *fe, FilterElement *cm)
+folder_eq(EFilterElement *fe, EFilterElement *cm)
{
- return FILTER_ELEMENT_CLASS(parent_class)->eq(fe, cm)
+ return E_FILTER_ELEMENT_CLASS(parent_class)->eq(fe, cm)
&& strcmp(((EMFilterFolderElement *)fe)->uri, ((EMFilterFolderElement *)cm)->uri)== 0;
}
static void
-xml_create(FilterElement *fe, xmlNodePtr node)
+xml_create(EFilterElement *fe, xmlNodePtr node)
{
/* parent implementation */
- FILTER_ELEMENT_CLASS(parent_class)->xml_create(fe, node);
+ E_FILTER_ELEMENT_CLASS(parent_class)->xml_create(fe, node);
}
static xmlNodePtr
-xml_encode(FilterElement *fe)
+xml_encode(EFilterElement *fe)
{
xmlNodePtr value, work;
EMFilterFolderElement *ff = (EMFilterFolderElement *)fe;
@@ -187,7 +188,7 @@ xml_encode(FilterElement *fe)
}
static gint
-xml_decode(FilterElement *fe, xmlNodePtr node)
+xml_decode(EFilterElement *fe, xmlNodePtr node)
{
EMFilterFolderElement *ff = (EMFilterFolderElement *)fe;
xmlNodePtr n;
@@ -240,7 +241,7 @@ folder_selected(EMFolderSelectionButton *button, EMFilterFolderElement *ff)
}
static GtkWidget *
-get_widget(FilterElement *fe)
+get_widget(EFilterElement *fe)
{
EMFilterFolderElement *ff = (EMFilterFolderElement *)fe;
GtkWidget *button;
@@ -266,13 +267,13 @@ get_widget(FilterElement *fe)
}
static void
-build_code(FilterElement *fe, GString *out, struct _FilterPart *ff)
+build_code(EFilterElement *fe, GString *out, EFilterPart *ff)
{
return;
}
static void
-format_sexp(FilterElement *fe, GString *out)
+format_sexp(EFilterElement *fe, GString *out)
{
EMFilterFolderElement *ff = (EMFilterFolderElement *)fe;
@@ -280,7 +281,7 @@ format_sexp(FilterElement *fe, GString *out)
}
static void
-emff_copy_value(FilterElement *de, FilterElement *se)
+emff_copy_value(EFilterElement *de, EFilterElement *se)
{
if (EM_IS_FILTER_FOLDER_ELEMENT(se)) {
((EMFilterFolderElement *)de)->store_camel_uri = ((EMFilterFolderElement *)se)->store_camel_uri;
diff --git a/mail/em-filter-folder-element.h b/mail/em-filter-folder-element.h
index 149d0226e7..02fb34b09f 100644
--- a/mail/em-filter-folder-element.h
+++ b/mail/em-filter-folder-element.h
@@ -25,7 +25,7 @@
#ifndef _EM_FILTER_FOLDER_ELEMENT_H
#define _EM_FILTER_FOLDER_ELEMENT_H
-#include "filter/filter-element.h"
+#include "filter/e-filter-element.h"
#define EM_FILTER_FOLDER_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), em_filter_folder_element_get_type(), EMFilterFolderElement))
#define EM_FILTER_FOLDER_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), em_filter_folder_element_get_type(), EMFilterFolderElementClass))
@@ -37,14 +37,14 @@ typedef struct _EMFilterFolderElement EMFilterFolderElement;
typedef struct _EMFilterFolderElementClass EMFilterFolderElementClass;
struct _EMFilterFolderElement {
- FilterElement parent_object;
+ EFilterElement parent_object;
gchar *uri;
gboolean store_camel_uri; /* true if uri should contain camel uri, otherwise contains evolution's uri with an Account ID */
};
struct _EMFilterFolderElementClass {
- FilterElementClass parent_class;
+ EFilterElementClass parent_class;
};
GType em_filter_folder_element_get_type (void);
diff --git a/mail/em-filter-rule.c b/mail/em-filter-rule.c
index 8e95800e7a..d655e804be 100644
--- a/mail/em-filter-rule.c
+++ b/mail/em-filter-rule.c
@@ -35,19 +35,19 @@
#define d(x)
-static gint validate(FilterRule *fr, GtkWindow *error_parent);
-static gint filter_eq(FilterRule *fr, FilterRule *cm);
-static xmlNodePtr xml_encode(FilterRule *fr);
-static gint xml_decode(FilterRule *fr, xmlNodePtr, RuleContext *rc);
-static void rule_copy(FilterRule *dest, FilterRule *src);
-/*static void build_code(FilterRule *, GString *out);*/
-static GtkWidget *get_widget(FilterRule *fr, RuleContext *rc);
+static gint validate(EFilterRule *fr, GtkWindow *error_parent);
+static gint filter_eq(EFilterRule *fr, EFilterRule *cm);
+static xmlNodePtr xml_encode(EFilterRule *fr);
+static gint xml_decode(EFilterRule *fr, xmlNodePtr, ERuleContext *rc);
+static void rule_copy(EFilterRule *dest, EFilterRule *src);
+/*static void build_code(EFilterRule *, GString *out);*/
+static GtkWidget *get_widget(EFilterRule *fr, ERuleContext *rc);
static void em_filter_rule_class_init(EMFilterRuleClass *klass);
static void em_filter_rule_init(EMFilterRule *ff);
static void em_filter_rule_finalise(GObject *obj);
-static FilterRuleClass *parent_class = NULL;
+static EFilterRuleClass *parent_class = NULL;
GType
em_filter_rule_get_type(void)
@@ -67,7 +67,7 @@ em_filter_rule_get_type(void)
(GInstanceInitFunc)em_filter_rule_init,
};
- type = g_type_register_static(FILTER_TYPE_RULE, "EMFilterRule", &info, 0);
+ type = g_type_register_static(E_TYPE_FILTER_RULE, "EMFilterRule", &info, 0);
}
return type;
@@ -77,9 +77,9 @@ static void
em_filter_rule_class_init(EMFilterRuleClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
- FilterRuleClass *fr_class =(FilterRuleClass *)klass;
+ EFilterRuleClass *fr_class =(EFilterRuleClass *)klass;
- parent_class = g_type_class_ref(FILTER_TYPE_RULE);
+ parent_class = g_type_class_ref(E_TYPE_FILTER_RULE);
object_class->finalize = em_filter_rule_finalise;
@@ -133,23 +133,23 @@ em_filter_rule_new(void)
}
void
-em_filter_rule_add_action(EMFilterRule *fr, FilterPart *fp)
+em_filter_rule_add_action(EMFilterRule *fr, EFilterPart *fp)
{
fr->actions = g_list_append(fr->actions, fp);
- filter_rule_emit_changed((FilterRule *)fr);
+ e_filter_rule_emit_changed((EFilterRule *)fr);
}
void
-em_filter_rule_remove_action(EMFilterRule *fr, FilterPart *fp)
+em_filter_rule_remove_action(EMFilterRule *fr, EFilterPart *fp)
{
fr->actions = g_list_remove(fr->actions, fp);
- filter_rule_emit_changed((FilterRule *)fr);
+ e_filter_rule_emit_changed((EFilterRule *)fr);
}
void
-em_filter_rule_replace_action(EMFilterRule *fr, FilterPart *fp, FilterPart *new)
+em_filter_rule_replace_action(EMFilterRule *fr, EFilterPart *fp, EFilterPart *new)
{
GList *l;
@@ -160,30 +160,30 @@ em_filter_rule_replace_action(EMFilterRule *fr, FilterPart *fp, FilterPart *new)
fr->actions = g_list_append(fr->actions, new);
}
- filter_rule_emit_changed((FilterRule *)fr);
+ e_filter_rule_emit_changed((EFilterRule *)fr);
}
void
em_filter_rule_build_action(EMFilterRule *fr, GString *out)
{
g_string_append(out, "(begin\n");
- filter_part_build_code_list(fr->actions, out);
+ e_filter_part_build_code_list(fr->actions, out);
g_string_append(out, ")\n");
}
static gint
-validate(FilterRule *fr, GtkWindow *error_parent)
+validate(EFilterRule *fr, GtkWindow *error_parent)
{
EMFilterRule *ff =(EMFilterRule *)fr;
GList *parts;
gint valid;
- valid = FILTER_RULE_CLASS(parent_class)->validate (fr, error_parent);
+ valid = E_FILTER_RULE_CLASS(parent_class)->validate (fr, error_parent);
/* validate rule actions */
parts = ff->actions;
while (parts && valid) {
- valid = filter_part_validate ((FilterPart *)parts->data, error_parent);
+ valid = e_filter_part_validate ((EFilterPart *)parts->data, error_parent);
parts = parts->next;
}
@@ -196,9 +196,9 @@ list_eq(GList *al, GList *bl)
gint truth = TRUE;
while (truth && al && bl) {
- FilterPart *a = al->data, *b = bl->data;
+ EFilterPart *a = al->data, *b = bl->data;
- truth = filter_part_eq(a, b);
+ truth = e_filter_part_eq(a, b);
al = al->next;
bl = bl->next;
}
@@ -207,26 +207,26 @@ list_eq(GList *al, GList *bl)
}
static gint
-filter_eq(FilterRule *fr, FilterRule *cm)
+filter_eq(EFilterRule *fr, EFilterRule *cm)
{
- return FILTER_RULE_CLASS(parent_class)->eq(fr, cm)
+ return E_FILTER_RULE_CLASS(parent_class)->eq(fr, cm)
&& list_eq(((EMFilterRule *)fr)->actions,((EMFilterRule *)cm)->actions);
}
static xmlNodePtr
-xml_encode(FilterRule *fr)
+xml_encode(EFilterRule *fr)
{
EMFilterRule *ff =(EMFilterRule *)fr;
xmlNodePtr node, set, work;
GList *l;
- node = FILTER_RULE_CLASS(parent_class)->xml_encode(fr);
+ node = E_FILTER_RULE_CLASS(parent_class)->xml_encode(fr);
g_return_val_if_fail (node != NULL, NULL);
set = xmlNewNode(NULL, (const guchar *)"actionset");
xmlAddChild(node, set);
l = ff->actions;
while (l) {
- work = filter_part_xml_encode((FilterPart *)l->data);
+ work = e_filter_part_xml_encode((EFilterPart *)l->data);
xmlAddChild(set, work);
l = l->next;
}
@@ -236,11 +236,11 @@ xml_encode(FilterRule *fr)
}
static void
-load_set(xmlNodePtr node, EMFilterRule *ff, RuleContext *rc)
+load_set(xmlNodePtr node, EMFilterRule *ff, ERuleContext *rc)
{
xmlNodePtr work;
gchar *rulename;
- FilterPart *part;
+ EFilterPart *part;
work = node->children;
while (work) {
@@ -248,8 +248,8 @@ load_set(xmlNodePtr node, EMFilterRule *ff, RuleContext *rc)
rulename = (gchar *)xmlGetProp(work, (const guchar *)"name");
part = em_filter_context_find_action((EMFilterContext *)rc, rulename);
if (part) {
- part = filter_part_clone(part);
- filter_part_xml_decode(part, work);
+ part = e_filter_part_clone(part);
+ e_filter_part_xml_decode(part, work);
em_filter_rule_add_action(ff, part);
} else {
g_warning("cannot find rule part '%s'\n", rulename);
@@ -263,13 +263,13 @@ load_set(xmlNodePtr node, EMFilterRule *ff, RuleContext *rc)
}
static gint
-xml_decode(FilterRule *fr, xmlNodePtr node, RuleContext *rc)
+xml_decode(EFilterRule *fr, xmlNodePtr node, ERuleContext *rc)
{
EMFilterRule *ff =(EMFilterRule *)fr;
xmlNodePtr work;
gint result;
- result = FILTER_RULE_CLASS(parent_class)->xml_decode(fr, node, rc);
+ result = E_FILTER_RULE_CLASS(parent_class)->xml_decode(fr, node, rc);
if (result != 0)
return result;
@@ -285,7 +285,7 @@ xml_decode(FilterRule *fr, xmlNodePtr node, RuleContext *rc)
}
static void
-rule_copy(FilterRule *dest, FilterRule *src)
+rule_copy(EFilterRule *dest, EFilterRule *src)
{
EMFilterRule *fdest, *fsrc;
GList *node;
@@ -301,33 +301,33 @@ rule_copy(FilterRule *dest, FilterRule *src)
node = fsrc->actions;
while (node) {
- FilterPart *part = node->data;
+ EFilterPart *part = node->data;
g_object_ref(part);
fdest->actions = g_list_append(fdest->actions, part);
node = node->next;
}
- FILTER_RULE_CLASS(parent_class)->copy(dest, src);
+ E_FILTER_RULE_CLASS(parent_class)->copy(dest, src);
}
-/*static void build_code(FilterRule *fr, GString *out)
+/*static void build_code(EFilterRule *fr, GString *out)
{
return FILTER_RULE_CLASS(parent_class)->build_code(fr, out);
}*/
struct _part_data {
- FilterRule *fr;
+ EFilterRule *fr;
EMFilterContext *f;
- FilterPart *part;
+ EFilterPart *part;
GtkWidget *partwidget, *container;
};
static void
part_combobox_changed (GtkComboBox *combobox, struct _part_data *data)
{
- FilterPart *part = NULL;
- FilterPart *newpart;
+ EFilterPart *part = NULL;
+ EFilterPart *newpart;
gint index, i;
index = gtk_combo_box_get_active (combobox);
@@ -347,20 +347,20 @@ part_combobox_changed (GtkComboBox *combobox, struct _part_data *data)
if (data->partwidget)
gtk_container_remove (GTK_CONTAINER (data->container), data->partwidget);
- newpart = filter_part_clone (part);
- filter_part_copy_values (newpart, data->part);
+ newpart = e_filter_part_clone (part);
+ e_filter_part_copy_values (newpart, data->part);
em_filter_rule_replace_action ((EMFilterRule *)data->fr, data->part, newpart);
g_object_unref (data->part);
data->part = newpart;
- data->partwidget = filter_part_get_widget (newpart);
+ data->partwidget = e_filter_part_get_widget (newpart);
if (data->partwidget)
gtk_box_pack_start (GTK_BOX (data->container), data->partwidget, TRUE, TRUE, 0);
}
static GtkWidget *
-get_rule_part_widget(EMFilterContext *f, FilterPart *newpart, FilterRule *fr)
+get_rule_part_widget(EMFilterContext *f, EFilterPart *newpart, EFilterRule *fr)
{
- FilterPart *part = NULL;
+ EFilterPart *part = NULL;
GtkWidget *combobox;
GtkWidget *hbox;
GtkWidget *p;
@@ -373,7 +373,7 @@ get_rule_part_widget(EMFilterContext *f, FilterPart *newpart, FilterRule *fr)
data->part = newpart;
hbox = gtk_hbox_new(FALSE, 0);
- p = filter_part_get_widget(newpart);
+ p = e_filter_part_get_widget(newpart);
data->partwidget = p;
data->container = hbox;
@@ -402,7 +402,7 @@ get_rule_part_widget(EMFilterContext *f, FilterPart *newpart, FilterRule *fr)
}
struct _rule_data {
- FilterRule *fr;
+ EFilterRule *fr;
EMFilterContext *f;
GtkWidget *parts;
};
@@ -410,7 +410,7 @@ struct _rule_data {
static void
less_parts(GtkWidget *button, struct _rule_data *data)
{
- FilterPart *part;
+ EFilterPart *part;
GtkWidget *rule;
GList *l;
@@ -431,7 +431,7 @@ less_parts(GtkWidget *button, struct _rule_data *data)
}
static void
-attach_rule(GtkWidget *rule, struct _rule_data *data, FilterPart *part, gint row)
+attach_rule(GtkWidget *rule, struct _rule_data *data, EFilterPart *part, gint row)
{
GtkWidget *remove;
@@ -465,7 +465,7 @@ do_grab_focus_cb (GtkWidget *widget, gpointer data)
static void
more_parts(GtkWidget *button, struct _rule_data *data)
{
- FilterPart *new;
+ EFilterPart *new;
/* create a new rule entry, use the first type of rule */
new = em_filter_context_next_action((EMFilterContext *)data->f, NULL);
@@ -473,7 +473,7 @@ more_parts(GtkWidget *button, struct _rule_data *data)
GtkWidget *w;
guint16 rows;
- new = filter_part_clone(new);
+ new = e_filter_part_clone(new);
em_filter_rule_add_action((EMFilterRule *)data->fr, new);
w = get_rule_part_widget(data->f, new, data->fr);
@@ -502,20 +502,20 @@ more_parts(GtkWidget *button, struct _rule_data *data)
}
static GtkWidget *
-get_widget(FilterRule *fr, RuleContext *rc)
+get_widget(EFilterRule *fr, ERuleContext *rc)
{
GtkWidget *widget, *hbox, *add, *label;
GtkWidget *parts, *inframe, *w;
GtkWidget *scrolledwindow;
GtkObject *hadj, *vadj;
GList *l;
- FilterPart *part;
+ EFilterPart *part;
struct _rule_data *data;
EMFilterRule *ff =(EMFilterRule *)fr;
gint rows, i = 0;
gchar *msg;
- widget = FILTER_RULE_CLASS(parent_class)->get_widget(fr, rc);
+ widget = E_FILTER_RULE_CLASS(parent_class)->get_widget(fr, rc);
/* and now for the action area */
msg = g_strdup_printf("<b>%s</b>", _("Then"));
diff --git a/mail/em-filter-rule.h b/mail/em-filter-rule.h
index 6ddaddc8d2..4ea49780b9 100644
--- a/mail/em-filter-rule.h
+++ b/mail/em-filter-rule.h
@@ -25,7 +25,7 @@
#ifndef _EM_FILTER_RULE_H
#define _EM_FILTER_RULE_H
-#include "filter/filter-rule.h"
+#include "filter/e-filter-rule.h"
#define EM_FILTER_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), em_filter_rule_get_type(), EMFilterRule))
#define EM_FILTER_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), em_filter_rule_get_type(), EMFilterRuleClass))
@@ -37,22 +37,22 @@ typedef struct _EMFilterRule EMFilterRule;
typedef struct _EMFilterRuleClass EMFilterRuleClass;
struct _EMFilterRule {
- FilterRule parent_object;
+ EFilterRule parent_object;
GList *actions;
};
struct _EMFilterRuleClass {
- FilterRuleClass parent_class;
+ EFilterRuleClass parent_class;
};
GType em_filter_rule_get_type (void);
EMFilterRule *em_filter_rule_new (void);
/* methods */
-void em_filter_rule_add_action (EMFilterRule *fr, FilterPart *fp);
-void em_filter_rule_remove_action (EMFilterRule *fr, FilterPart *fp);
-void em_filter_rule_replace_action (EMFilterRule *fr, FilterPart *fp, FilterPart *new);
+void em_filter_rule_add_action (EMFilterRule *fr, EFilterPart *fp);
+void em_filter_rule_remove_action (EMFilterRule *fr, EFilterPart *fp);
+void em_filter_rule_replace_action (EMFilterRule *fr, EFilterPart *fp, EFilterPart *new);
void em_filter_rule_build_action (EMFilterRule *fr, GString *out);
diff --git a/mail/em-filter-source-element.c b/mail/em-filter-source-element.c
index 40af002d29..d080076725 100644
--- a/mail/em-filter-source-element.c
+++ b/mail/em-filter-source-element.c
@@ -34,18 +34,20 @@
#include <libedataserver/e-account-list.h>
#include <camel/camel-url.h>
+#include "filter/e-filter-part.h"
+
static void em_filter_source_element_class_init(EMFilterSourceElementClass *klass);
static void em_filter_source_element_init(EMFilterSourceElement *fs);
static void em_filter_source_element_finalize(GObject *obj);
-static gint source_eq(FilterElement *fe, FilterElement *cm);
-static void xml_create(FilterElement *fe, xmlNodePtr node);
-static xmlNodePtr xml_encode(FilterElement *fe);
-static gint xml_decode(FilterElement *fe, xmlNodePtr node);
-static FilterElement *clone(FilterElement *fe);
-static GtkWidget *get_widget(FilterElement *fe);
-static void build_code(FilterElement *fe, GString *out, struct _FilterPart *ff);
-static void format_sexp(FilterElement *, GString *);
+static gint source_eq(EFilterElement *fe, EFilterElement *cm);
+static void xml_create(EFilterElement *fe, xmlNodePtr node);
+static xmlNodePtr xml_encode(EFilterElement *fe);
+static gint xml_decode(EFilterElement *fe, xmlNodePtr node);
+static EFilterElement *clone(EFilterElement *fe);
+static GtkWidget *get_widget(EFilterElement *fe);
+static void build_code(EFilterElement *fe, GString *out, EFilterPart *ff);
+static void format_sexp(EFilterElement *, GString *);
static void em_filter_source_element_add_source (EMFilterSourceElement *fs, const gchar *account_name, const gchar *name,
const gchar *addr, const gchar *url);
@@ -63,7 +65,7 @@ struct _EMFilterSourceElementPrivate {
gchar *current_url;
};
-static FilterElementClass *parent_class = NULL;
+static EFilterElementClass *parent_class = NULL;
GType
em_filter_source_element_get_type(void)
@@ -83,7 +85,7 @@ em_filter_source_element_get_type(void)
(GInstanceInitFunc)em_filter_source_element_init,
};
- type = g_type_register_static(FILTER_TYPE_ELEMENT, "EMFilterSourceElement", &info, 0);
+ type = g_type_register_static(E_TYPE_FILTER_ELEMENT, "EMFilterSourceElement", &info, 0);
}
return type;
@@ -93,9 +95,9 @@ static void
em_filter_source_element_class_init(EMFilterSourceElementClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
- FilterElementClass *fe_class = FILTER_ELEMENT_CLASS(klass);
+ EFilterElementClass *fe_class = E_FILTER_ELEMENT_CLASS(klass);
- parent_class = g_type_class_ref(FILTER_TYPE_ELEMENT);
+ parent_class = g_type_class_ref(E_TYPE_FILTER_ELEMENT);
object_class->finalize = em_filter_source_element_finalize;
@@ -149,25 +151,25 @@ em_filter_source_element_new(void)
}
static gint
-source_eq(FilterElement *fe, FilterElement *cm)
+source_eq(EFilterElement *fe, EFilterElement *cm)
{
EMFilterSourceElement *fs = (EMFilterSourceElement *)fe, *cs = (EMFilterSourceElement *)cm;
- return FILTER_ELEMENT_CLASS(parent_class)->eq(fe, cm)
+ return E_FILTER_ELEMENT_CLASS(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)
+xml_create(EFilterElement *fe, xmlNodePtr node)
{
/* Call parent implementation */
- FILTER_ELEMENT_CLASS(parent_class)->xml_create(fe, node);
+ E_FILTER_ELEMENT_CLASS(parent_class)->xml_create(fe, node);
}
static xmlNodePtr
-xml_encode(FilterElement *fe)
+xml_encode(EFilterElement *fe)
{
xmlNodePtr value;
@@ -184,7 +186,7 @@ xml_encode(FilterElement *fe)
}
static gint
-xml_decode(FilterElement *fe, xmlNodePtr node)
+xml_decode(EFilterElement *fe, xmlNodePtr node)
{
EMFilterSourceElement *fs = (EMFilterSourceElement *)fe;
CamelURL *url;
@@ -209,14 +211,14 @@ xml_decode(FilterElement *fe, xmlNodePtr node)
return 0;
}
-static FilterElement *
-clone(FilterElement *fe)
+static EFilterElement *
+clone(EFilterElement *fe)
{
EMFilterSourceElement *fs = (EMFilterSourceElement *)fe;
EMFilterSourceElement *cpy = em_filter_source_element_new();
GList *i;
- ((FilterElement *)cpy)->name = (gchar *)xmlStrdup((guchar *)fe->name);
+ ((EFilterElement *)cpy)->name = (gchar *)xmlStrdup((guchar *)fe->name);
cpy->priv->current_url = g_strdup(fs->priv->current_url);
@@ -225,7 +227,7 @@ clone(FilterElement *fe)
em_filter_source_element_add_source(cpy, info->account_name, info->name, info->address, info->url);
}
- return (FilterElement *)cpy;
+ return (EFilterElement *)cpy;
}
static void
@@ -245,7 +247,7 @@ source_changed(GtkComboBox *combobox, EMFilterSourceElement *fs)
}
static GtkWidget *
-get_widget(FilterElement *fe)
+get_widget(EFilterElement *fe)
{
EMFilterSourceElement *fs = (EMFilterSourceElement *)fe;
GtkWidget *combobox;
@@ -303,13 +305,13 @@ get_widget(FilterElement *fe)
}
static void
-build_code(FilterElement *fe, GString *out, struct _FilterPart *ff)
+build_code(EFilterElement *fe, GString *out, EFilterPart *ff)
{
/* We are doing nothing on purpose. */
}
static void
-format_sexp(FilterElement *fe, GString *out)
+format_sexp(EFilterElement *fe, GString *out)
{
EMFilterSourceElement *fs = (EMFilterSourceElement *)fe;
diff --git a/mail/em-filter-source-element.h b/mail/em-filter-source-element.h
index d4d6a75890..cb68552db2 100644
--- a/mail/em-filter-source-element.h
+++ b/mail/em-filter-source-element.h
@@ -24,7 +24,7 @@
#ifndef _EM_FILTER_SOURCE_ELEMENT_H
#define _EM_FILTER_SOURCE_ELEMENT_H
-#include "filter/filter-element.h"
+#include "filter/e-filter-element.h"
#define EM_FILTER_SOURCE_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), em_filter_source_element_get_type(), EMFilterSourceElement))
#define EM_FILTER_SOURCE_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), em_filter_source_element_get_type(), EMFilterSourceElementClass))
@@ -36,12 +36,12 @@ typedef struct _EMFilterSourceElement EMFilterSourceElement;
typedef struct _EMFilterSourceElementClass EMFilterSourceElementClass;
struct _EMFilterSourceElement {
- FilterElement parent_object;
+ EFilterElement parent_object;
struct _EMFilterSourceElementPrivate *priv;
};
struct _EMFilterSourceElementClass {
- FilterElementClass parent_class;
+ EFilterElementClass parent_class;
};
GType em_filter_source_element_get_type (void);
diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c
index c2850daaf1..8b1dab9388 100644
--- a/mail/em-folder-utils.c
+++ b/mail/em-folder-utils.c
@@ -625,7 +625,7 @@ emfu_popup_new_folder_response (EMFolderSelector *emfs, gint response, gpointer
vfolder_load_storage ();
rule = em_vfolder_rule_new();
- filter_rule_set_name((FilterRule *)rule, path);
+ e_filter_rule_set_name((EFilterRule *)rule, path);
vfolder_gui_add_rule(rule);
gtk_widget_destroy((GtkWidget *)emfs);
} else {
diff --git a/mail/em-search-context.c b/mail/em-search-context.c
index 7bc43a18be..f4b817b6b6 100644
--- a/mail/em-search-context.c
+++ b/mail/em-search-context.c
@@ -29,44 +29,44 @@
#include <string.h>
#include "em-search-context.h"
-#include "filter/filter-rule.h"
-#include "filter/filter-option.h"
-#include "filter/filter-int.h"
+#include "filter/e-filter-rule.h"
+#include "filter/e-filter-option.h"
+#include "filter/e-filter-int.h"
static gpointer parent_class;
-static FilterElement *
-search_context_new_element (RuleContext *context,
+static EFilterElement *
+search_context_new_element (ERuleContext *context,
const gchar *type)
{
if (strcmp (type, "system-flag") == 0)
- return (FilterElement *) filter_option_new ();
+ return (EFilterElement *) e_filter_option_new ();
if (strcmp (type, "score") == 0)
- return (FilterElement *) filter_int_new_type ("score", -3, 3);
+ return (EFilterElement *) e_filter_int_new_type ("score", -3, 3);
/* Chain up to parent's new_element() method. */
- return RULE_CONTEXT_CLASS (parent_class)->new_element (context, type);
+ return E_RULE_CONTEXT_CLASS (parent_class)->new_element (context, type);
}
static void
search_context_class_init (EMSearchContextClass *class)
{
- RuleContextClass *rule_context_class;
+ ERuleContextClass *rule_context_class;
parent_class = g_type_class_peek_parent (class);
- rule_context_class = RULE_CONTEXT_CLASS (class);
+ rule_context_class = E_RULE_CONTEXT_CLASS (class);
rule_context_class->new_element = search_context_new_element;
}
static void
search_context_init (EMSearchContext *vc)
{
- RuleContext *rule_context;
+ ERuleContext *rule_context;
- rule_context = RULE_CONTEXT (vc);
- rule_context->flags = RULE_CONTEXT_THREADING | RULE_CONTEXT_GROUPING;
+ rule_context = E_RULE_CONTEXT (vc);
+ rule_context->flags = E_RULE_CONTEXT_THREADING | E_RULE_CONTEXT_GROUPING;
}
GType
@@ -89,13 +89,13 @@ em_search_context_get_type (void)
};
type = g_type_register_static (
- RULE_TYPE_CONTEXT, "EMSearchContext", &type_info, 0);
+ E_TYPE_RULE_CONTEXT, "EMSearchContext", &type_info, 0);
}
return type;
}
-RuleContext *
+ERuleContext *
em_search_context_new (void)
{
return g_object_new (EM_SEARCH_TYPE_CONTEXT, NULL);
diff --git a/mail/em-search-context.h b/mail/em-search-context.h
index d8b890270c..316a53a909 100644
--- a/mail/em-search-context.h
+++ b/mail/em-search-context.h
@@ -25,7 +25,7 @@
#ifndef EM_SEARCH_CONTEXT_H
#define EM_SEARCH_CONTEXT_H
-#include <filter/rule-context.h>
+#include <filter/e-rule-context.h>
/* Standard GObject macros */
#define EM_SEARCH_TYPE_CONTEXT \
@@ -52,15 +52,15 @@ typedef struct _EMSearchContext EMSearchContext;
typedef struct _EMSearchContextClass EMSearchContextClass;
struct _EMSearchContext {
- RuleContext parent;
+ ERuleContext parent;
};
struct _EMSearchContextClass {
- RuleContextClass parent_class;
+ ERuleContextClass parent_class;
};
GType em_search_context_get_type (void);
-RuleContext * em_search_context_new (void);
+ERuleContext * em_search_context_new (void);
G_END_DECLS
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 3c6c4ffee7..2154c62e57 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -243,7 +243,7 @@ em_filter_editor_response (GtkWidget *dialog, gint button, gpointer user_data)
data_dir = em_utils_get_data_dir ();
fc = g_object_get_data ((GObject *) dialog, "context");
user = g_strdup_printf ("%s/filters.xml", data_dir);
- rule_context_save ((RuleContext *) fc, user);
+ e_rule_context_save ((ERuleContext *) fc, user);
g_free (user);
}
@@ -283,12 +283,12 @@ em_utils_edit_filters (GtkWidget *parent)
fc = em_filter_context_new ();
user = g_build_filename (data_dir, "filters.xml", NULL);
system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL);
- rule_context_load ((RuleContext *) fc, system, user);
+ e_rule_context_load ((ERuleContext *) fc, system, user);
g_free (user);
g_free (system);
- if (((RuleContext *) fc)->error) {
- GtkWidget *w = e_error_new((GtkWindow *)parent, "mail:filter-load-error", ((RuleContext *)fc)->error, NULL);
+ if (((ERuleContext *) fc)->error) {
+ GtkWidget *w = e_error_new((GtkWindow *)parent, "mail:filter-load-error", ((ERuleContext *)fc)->error, NULL);
em_utils_show_error_silent (w);
return;
}
diff --git a/mail/em-vfolder-context.c b/mail/em-vfolder-context.c
index b111376b20..789735683c 100644
--- a/mail/em-vfolder-context.c
+++ b/mail/em-vfolder-context.c
@@ -30,14 +30,14 @@
#include "em-vfolder-context.h"
#include "em-vfolder-rule.h"
-#include "filter/filter-option.h"
-#include "filter/filter-int.h"
+#include "filter/e-filter-option.h"
+#include "filter/e-filter-int.h"
#include "em-filter-folder-element.h"
-static FilterElement *vfolder_new_element(RuleContext *rc, const gchar *type);
+static EFilterElement *vfolder_new_element(ERuleContext *rc, const gchar *type);
-static RuleContextClass *parent_class = NULL;
+static ERuleContextClass *parent_class = NULL;
static void
em_vfolder_context_finalise(GObject *obj)
@@ -48,22 +48,22 @@ em_vfolder_context_finalise(GObject *obj)
static void
em_vfolder_context_class_init(EMVFolderContextClass *klass)
{
- parent_class = g_type_class_ref(RULE_TYPE_CONTEXT);
+ parent_class = g_type_class_ref(E_TYPE_RULE_CONTEXT);
((GObjectClass *)klass)->finalize = em_vfolder_context_finalise;
- ((RuleContextClass *)klass)->new_element = vfolder_new_element;
+ ((ERuleContextClass *)klass)->new_element = vfolder_new_element;
}
static void
em_vfolder_context_init(EMVFolderContext *vc)
{
- rule_context_add_part_set((RuleContext *) vc, "partset", filter_part_get_type(),
- rule_context_add_part, rule_context_next_part);
+ e_rule_context_add_part_set((ERuleContext *) vc, "partset", E_TYPE_FILTER_PART,
+ e_rule_context_add_part, e_rule_context_next_part);
- rule_context_add_rule_set((RuleContext *) vc, "ruleset", em_vfolder_rule_get_type(),
- rule_context_add_rule, rule_context_next_rule);
+ e_rule_context_add_rule_set((ERuleContext *) vc, "ruleset", em_vfolder_rule_get_type(),
+ e_rule_context_add_rule, e_rule_context_next_rule);
- ((RuleContext *)vc)->flags = RULE_CONTEXT_THREADING | RULE_CONTEXT_GROUPING;
+ ((ERuleContext *)vc)->flags = E_RULE_CONTEXT_THREADING | E_RULE_CONTEXT_GROUPING;
}
GType
@@ -84,7 +84,7 @@ em_vfolder_context_get_type(void)
(GInstanceInitFunc) em_vfolder_context_init,
};
- type = g_type_register_static(RULE_TYPE_CONTEXT, "EMVFolderContext", &info, 0);
+ type = g_type_register_static(E_TYPE_RULE_CONTEXT, "EMVFolderContext", &info, 0);
}
return type;
@@ -103,20 +103,20 @@ em_vfolder_context_new(void)
return (EMVFolderContext *)g_object_new(em_vfolder_context_get_type(), NULL, NULL);
}
-static FilterElement *
-vfolder_new_element(RuleContext *rc, const gchar *type)
+static EFilterElement *
+vfolder_new_element(ERuleContext *rc, const gchar *type)
{
if (!strcmp(type, "system-flag")) {
- return (FilterElement *) filter_option_new();
+ return (EFilterElement *) e_filter_option_new();
} else if (!strcmp(type, "score")) {
- return (FilterElement *) filter_int_new_type("score", -3, 3);
+ return (EFilterElement *) e_filter_int_new_type("score", -3, 3);
} else if (!strcmp(type, "folder-curi")) {
EMFilterFolderElement *ff = em_filter_folder_element_new ();
if (ff)
ff->store_camel_uri = TRUE;
- return (FilterElement *) ff;
+ return (EFilterElement *) ff;
} else if (!strcmp(type, "folder")) {
- return (FilterElement *) em_filter_folder_element_new();
+ return (EFilterElement *) em_filter_folder_element_new();
} else {
return parent_class->new_element(rc, type);
}
diff --git a/mail/em-vfolder-context.h b/mail/em-vfolder-context.h
index 7f17f4e2b4..baf3f5ff32 100644
--- a/mail/em-vfolder-context.h
+++ b/mail/em-vfolder-context.h
@@ -25,7 +25,7 @@
#ifndef _EM_VFOLDER_CONTEXT_H
#define _EM_VFOLDER_CONTEXT_H
-#include "filter/rule-context.h"
+#include "filter/e-rule-context.h"
#define EM_VFOLDER_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), em_vfolder_context_get_type(), EMVFolderContext))
#define EM_VFOLDER_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), em_vfolder_context_get_type(), EMVFolderContextClass))
@@ -37,12 +37,12 @@ typedef struct _EMVFolderContext EMVFolderContext;
typedef struct _EMVFolderContextClass EMVFolderContextClass;
struct _EMVFolderContext {
- RuleContext parent_object;
+ ERuleContext parent_object;
};
struct _EMVFolderContextClass {
- RuleContextClass parent_class;
+ ERuleContextClass parent_class;
};
GType em_vfolder_context_get_type (void);
diff --git a/mail/em-vfolder-editor.c b/mail/em-vfolder-editor.c
index 058ad0a957..073a4c5c90 100644
--- a/mail/em-vfolder-editor.c
+++ b/mail/em-vfolder-editor.c
@@ -38,16 +38,16 @@
static gpointer parent_class;
-static FilterRule *
-vfolder_editor_create_rule (RuleEditor *rule_editor)
+static EFilterRule *
+vfolder_editor_create_rule (ERuleEditor *rule_editor)
{
- FilterRule *rule = filter_rule_new ();
- FilterPart *part;
+ EFilterRule *rule = e_filter_rule_new ();
+ EFilterPart *part;
/* create a rule with 1 part in it */
- rule = (FilterRule *) em_vfolder_rule_new ();
- part = rule_context_next_part (rule_editor->context, NULL);
- filter_rule_add_part (rule, filter_part_clone (part));
+ rule = (EFilterRule *) em_vfolder_rule_new ();
+ part = e_rule_context_next_part (rule_editor->context, NULL);
+ e_filter_rule_add_part (rule, e_filter_part_clone (part));
return rule;
}
@@ -55,11 +55,11 @@ vfolder_editor_create_rule (RuleEditor *rule_editor)
static void
vfolder_editor_class_init (EMVFolderEditorClass *class)
{
- RuleEditorClass *rule_editor_class;
+ ERuleEditorClass *rule_editor_class;
parent_class = g_type_class_peek_parent (class);
- rule_editor_class = RULE_EDITOR_CLASS (class);
+ rule_editor_class = E_RULE_EDITOR_CLASS (class);
rule_editor_class->create_rule = vfolder_editor_create_rule;
}
@@ -96,7 +96,7 @@ em_vfolder_editor_get_type (void)
};
type = g_type_register_static (
- RULE_TYPE_EDITOR, "EMVFolderEditor", &type_info, 0);
+ E_TYPE_RULE_EDITOR, "EMVFolderEditor", &type_info, 0);
}
return type;
@@ -123,7 +123,7 @@ em_vfolder_editor_new (EMVFolderContext *vc)
gui = glade_xml_new (gladefile, "rule_editor", NULL);
g_free (gladefile);
- rule_editor_construct ((RuleEditor *) ve, (RuleContext *) vc, gui, "incoming", _("Search _Folders"));
+ e_rule_editor_construct ((ERuleEditor *) ve, (ERuleContext *) vc, gui, "incoming", _("Search _Folders"));
gtk_widget_hide (glade_xml_get_widget (gui, "label17"));
gtk_widget_hide (glade_xml_get_widget (gui, "filter_source_combobox"));
g_object_unref (gui);
diff --git a/mail/em-vfolder-editor.h b/mail/em-vfolder-editor.h
index 2a48c46e87..2548582ad7 100644
--- a/mail/em-vfolder-editor.h
+++ b/mail/em-vfolder-editor.h
@@ -24,7 +24,7 @@
#ifndef EM_VFOLDER_EDITOR_H
#define EM_VFOLDER_EDITOR_H
-#include "filter/rule-editor.h"
+#include "filter/e-rule-editor.h"
#include "em-vfolder-context.h"
/* Standard GObject macros */
@@ -52,11 +52,11 @@ typedef struct _EMVFolderEditor EMVFolderEditor;
typedef struct _EMVFolderEditorClass EMVFolderEditorClass;
struct _EMVFolderEditor {
- RuleEditor parent;
+ ERuleEditor parent;
};
struct _EMVFolderEditorClass {
- RuleEditorClass parent_class;
+ ERuleEditorClass parent_class;
};
GType em_vfolder_editor_get_type (void);
diff --git a/mail/em-vfolder-rule.c b/mail/em-vfolder-rule.c
index 3a87c09751..50016d095d 100644
--- a/mail/em-vfolder-rule.c
+++ b/mail/em-vfolder-rule.c
@@ -43,13 +43,13 @@
#define d(x)
-static gint validate(FilterRule *, GtkWindow *error_parent);
-static gint vfolder_eq(FilterRule *fr, FilterRule *cm);
-static xmlNodePtr xml_encode(FilterRule *);
-static gint xml_decode(FilterRule *, xmlNodePtr, RuleContext *f);
-static void rule_copy(FilterRule *dest, FilterRule *src);
-/*static void build_code(FilterRule *, GString *out);*/
-static GtkWidget *get_widget(FilterRule *fr, RuleContext *f);
+static gint validate(EFilterRule *, GtkWindow *error_parent);
+static gint vfolder_eq(EFilterRule *fr, EFilterRule *cm);
+static xmlNodePtr xml_encode(EFilterRule *);
+static gint xml_decode(EFilterRule *, xmlNodePtr, ERuleContext *f);
+static void rule_copy(EFilterRule *dest, EFilterRule *src);
+/*static void build_code(EFilterRule *, GString *out);*/
+static GtkWidget *get_widget(EFilterRule *fr, ERuleContext *f);
static void em_vfolder_rule_class_init(EMVFolderRuleClass *klass);
static void em_vfolder_rule_init(EMVFolderRule *vr);
@@ -63,7 +63,7 @@ static const gchar *with_names[] = {
"local"
};
-static FilterRuleClass *parent_class = NULL;
+static EFilterRuleClass *parent_class = NULL;
GType
em_vfolder_rule_get_type(void)
@@ -83,7 +83,7 @@ em_vfolder_rule_get_type(void)
(GInstanceInitFunc)em_vfolder_rule_init,
};
- type = g_type_register_static(FILTER_TYPE_RULE, "EMVFolderRule", &info, 0);
+ type = g_type_register_static(E_TYPE_FILTER_RULE, "EMVFolderRule", &info, 0);
}
return type;
@@ -93,9 +93,9 @@ static void
em_vfolder_rule_class_init(EMVFolderRuleClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
- FilterRuleClass *fr_class =(FilterRuleClass *)klass;
+ EFilterRuleClass *fr_class =(EFilterRuleClass *)klass;
- parent_class = g_type_class_ref(FILTER_TYPE_RULE);
+ parent_class = g_type_class_ref(E_TYPE_FILTER_RULE);
object_class->finalize = em_vfolder_rule_finalise;
@@ -148,7 +148,7 @@ em_vfolder_rule_add_source(EMVFolderRule *vr, const gchar *uri)
vr->sources = g_list_append(vr->sources, g_strdup(uri));
- filter_rule_emit_changed((FilterRule *)vr);
+ e_filter_rule_emit_changed((EFilterRule *)vr);
}
const gchar *
@@ -181,7 +181,7 @@ em_vfolder_rule_remove_source(EMVFolderRule *vr, const gchar *uri)
if (found) {
vr->sources = g_list_remove(vr->sources, found);
g_free(found);
- filter_rule_emit_changed((FilterRule *)vr);
+ e_filter_rule_emit_changed((EFilterRule *)vr);
}
}
@@ -207,7 +207,7 @@ em_vfolder_rule_next_source(EMVFolderRule *vr, const gchar *last)
}
static gint
-validate(FilterRule *fr, GtkWindow *error_parent)
+validate(EFilterRule *fr, GtkWindow *error_parent)
{
g_return_val_if_fail(fr != NULL, 0);
@@ -223,7 +223,7 @@ validate(FilterRule *fr, GtkWindow *error_parent)
return 0;
}
- return FILTER_RULE_CLASS(parent_class)->validate (fr, error_parent);
+ return E_FILTER_RULE_CLASS(parent_class)->validate (fr, error_parent);
}
static gint
@@ -243,20 +243,20 @@ list_eq(GList *al, GList *bl)
}
static gint
-vfolder_eq(FilterRule *fr, FilterRule *cm)
+vfolder_eq(EFilterRule *fr, EFilterRule *cm)
{
- return FILTER_RULE_CLASS(parent_class)->eq(fr, cm)
+ return E_FILTER_RULE_CLASS(parent_class)->eq(fr, cm)
&& list_eq(((EMVFolderRule *)fr)->sources, ((EMVFolderRule *)cm)->sources);
}
static xmlNodePtr
-xml_encode(FilterRule *fr)
+xml_encode(EFilterRule *fr)
{
EMVFolderRule *vr =(EMVFolderRule *)fr;
xmlNodePtr node, set, work;
GList *l;
- node = FILTER_RULE_CLASS(parent_class)->xml_encode(fr);
+ node = E_FILTER_RULE_CLASS(parent_class)->xml_encode(fr);
g_return_val_if_fail (node != NULL, NULL);
g_return_val_if_fail (vr->with < G_N_ELEMENTS (with_names), NULL);
@@ -290,14 +290,14 @@ set_with(EMVFolderRule *vr, const gchar *name)
}
static gint
-xml_decode(FilterRule *fr, xmlNodePtr node, struct _RuleContext *f)
+xml_decode(EFilterRule *fr, xmlNodePtr node, struct _ERuleContext *f)
{
xmlNodePtr set, work;
gint result;
EMVFolderRule *vr =(EMVFolderRule *)fr;
gchar *tmp;
- result = FILTER_RULE_CLASS(parent_class)->xml_decode(fr, node, f);
+ result = E_FILTER_RULE_CLASS(parent_class)->xml_decode(fr, node, f);
if (result != 0)
return result;
@@ -334,7 +334,7 @@ xml_decode(FilterRule *fr, xmlNodePtr node, struct _RuleContext *f)
}
static void
-rule_copy(FilterRule *dest, FilterRule *src)
+rule_copy(EFilterRule *dest, EFilterRule *src)
{
EMVFolderRule *vdest, *vsrc;
GList *node;
@@ -358,7 +358,7 @@ rule_copy(FilterRule *dest, FilterRule *src)
vdest->with = vsrc->with;
- FILTER_RULE_CLASS(parent_class)->copy(dest, src);
+ E_FILTER_RULE_CLASS(parent_class)->copy(dest, src);
}
enum {
@@ -368,7 +368,7 @@ enum {
};
struct _source_data {
- RuleContext *rc;
+ ERuleContext *rc;
EMVFolderRule *vr;
const gchar *current;
GtkListStore *model;
@@ -611,7 +611,7 @@ em_vfolder_editor_sourcelist_new(gchar *widget_name, gchar *string1, gchar *stri
}
static GtkWidget *
-get_widget(FilterRule *fr, RuleContext *rc)
+get_widget(EFilterRule *fr, ERuleContext *rc)
{
EMVFolderRule *vr =(EMVFolderRule *)fr;
GtkWidget *widget, *frame, *list;
@@ -623,7 +623,7 @@ get_widget(FilterRule *fr, RuleContext *rc)
gint i;
gchar *gladefile;
- widget = FILTER_RULE_CLASS(parent_class)->get_widget(fr, rc);
+ widget = E_FILTER_RULE_CLASS(parent_class)->get_widget(fr, rc);
data = g_malloc0(sizeof(*data));
data->rc = rc;
diff --git a/mail/em-vfolder-rule.h b/mail/em-vfolder-rule.h
index 1c0b2a3113..a5c80356e7 100644
--- a/mail/em-vfolder-rule.h
+++ b/mail/em-vfolder-rule.h
@@ -24,7 +24,7 @@
#ifndef _EM_VFOLDER_RULE_H
#define _EM_VFOLDER_RULE_H
-#include "filter/filter-rule.h"
+#include "filter/e-filter-rule.h"
#define EM_VFOLDER_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), em_vfolder_rule_get_type(), EMVFolderRule))
#define EM_VFOLDER_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), em_vfolder_rule_get_type(), EMVFolderRuleClass))
@@ -46,14 +46,14 @@ typedef struct _EMVFolderRuleClass EMVFolderRuleClass;
typedef enum _em_vfolder_rule_with_t em_vfolder_rule_with_t;
struct _EMVFolderRule {
- FilterRule rule;
+ EFilterRule rule;
em_vfolder_rule_with_t with;
GList *sources; /* uri's of the source folders */
};
struct _EMVFolderRuleClass {
- FilterRuleClass parent_class;
+ EFilterRuleClass parent_class;
};
GType em_vfolder_rule_get_type (void);
diff --git a/mail/mail-autofilter.c b/mail/mail-autofilter.c
index cf6575d0c5..d64a4ae282 100644
--- a/mail/mail-autofilter.c
+++ b/mail/mail-autofilter.c
@@ -43,7 +43,7 @@
#include "em-filter-context.h"
#include "em-filter-rule.h"
#include "em-filter-editor.h"
-#include "filter/filter-option.h"
+#include "filter/e-filter-option.h"
#include <camel/camel-internet-address.h>
#include <camel/camel-mime-message.h>
@@ -51,25 +51,25 @@
#define d(x)
static void
-rule_match_recipients (RuleContext *context, FilterRule *rule, CamelInternetAddress *iaddr)
+rule_match_recipients (ERuleContext *context, EFilterRule *rule, CamelInternetAddress *iaddr)
{
- FilterPart *part;
- FilterElement *element;
+ EFilterPart *part;
+ EFilterElement *element;
gint i;
const gchar *real, *addr;
gchar *namestr;
/* address types etc should handle multiple values */
for (i = 0; camel_internet_address_get (iaddr, i, &real, &addr); i++) {
- part = rule_context_create_part (context, "to");
- filter_rule_add_part ((FilterRule *)rule, part);
- element = filter_part_find_element (part, "recipient-type");
- filter_option_set_current ((FilterOption *)element, "contains");
- element = filter_part_find_element (part, "recipient");
- filter_input_set_value ((FilterInput *)element, addr);
+ part = e_rule_context_create_part (context, "to");
+ e_filter_rule_add_part ((EFilterRule *)rule, part);
+ element = e_filter_part_find_element (part, "recipient-type");
+ e_filter_option_set_current ((EFilterOption *)element, "contains");
+ element = e_filter_part_find_element (part, "recipient");
+ e_filter_input_set_value ((EFilterInput *)element, addr);
namestr = g_strdup_printf (_("Mail to %s"), real && real[0] ? real : addr);
- filter_rule_set_name (rule, namestr);
+ e_filter_rule_set_name (rule, namestr);
g_free (namestr);
}
}
@@ -122,43 +122,43 @@ reg_match (gchar *str, gchar *regstr)
#endif
static void
-rule_add_subject (RuleContext *context, FilterRule *rule, const gchar *text)
+rule_add_subject (ERuleContext *context, EFilterRule *rule, const gchar *text)
{
- FilterPart *part;
- FilterElement *element;
+ EFilterPart *part;
+ EFilterElement *element;
/* dont match on empty strings ever */
if (*text == 0)
return;
- part = rule_context_create_part (context, "subject");
- filter_rule_add_part ((FilterRule *)rule, part);
- element = filter_part_find_element (part, "subject-type");
- filter_option_set_current ((FilterOption *)element, "contains");
- element = filter_part_find_element (part, "subject");
- filter_input_set_value ((FilterInput *)element, text);
+ part = e_rule_context_create_part (context, "subject");
+ e_filter_rule_add_part ((EFilterRule *)rule, part);
+ element = e_filter_part_find_element (part, "subject-type");
+ e_filter_option_set_current ((EFilterOption *)element, "contains");
+ element = e_filter_part_find_element (part, "subject");
+ e_filter_input_set_value ((EFilterInput *)element, text);
}
static void
-rule_add_sender (RuleContext *context, FilterRule *rule, const gchar *text)
+rule_add_sender (ERuleContext *context, EFilterRule *rule, const gchar *text)
{
- FilterPart *part;
- FilterElement *element;
+ EFilterPart *part;
+ EFilterElement *element;
/* dont match on empty strings ever */
if (*text == 0)
return;
- part = rule_context_create_part (context, "sender");
- filter_rule_add_part ((FilterRule *)rule, part);
- element = filter_part_find_element (part, "sender-type");
- filter_option_set_current ((FilterOption *)element, "contains");
- element = filter_part_find_element (part, "sender");
- filter_input_set_value ((FilterInput *)element, text);
+ part = e_rule_context_create_part (context, "sender");
+ e_filter_rule_add_part ((EFilterRule *)rule, part);
+ element = e_filter_part_find_element (part, "sender-type");
+ e_filter_option_set_current ((EFilterOption *)element, "contains");
+ element = e_filter_part_find_element (part, "sender");
+ e_filter_input_set_value ((EFilterInput *)element, text);
}
/* do a bunch of things on the subject to try and detect mailing lists, remove
unneeded stuff, etc */
static void
-rule_match_subject (RuleContext *context, FilterRule *rule, const gchar *subject)
+rule_match_subject (ERuleContext *context, EFilterRule *rule, const gchar *subject)
{
const gchar *s;
const gchar *s1, *s2;
@@ -200,28 +200,28 @@ rule_match_subject (RuleContext *context, FilterRule *rule, const gchar *subject
}
static void
-rule_match_mlist(RuleContext *context, FilterRule *rule, const gchar *mlist)
+rule_match_mlist(ERuleContext *context, EFilterRule *rule, const gchar *mlist)
{
- FilterPart *part;
- FilterElement *element;
+ EFilterPart *part;
+ EFilterElement *element;
if (mlist[0] == 0)
return;
- part = rule_context_create_part(context, "mlist");
- filter_rule_add_part(rule, part);
+ part = e_rule_context_create_part(context, "mlist");
+ e_filter_rule_add_part(rule, part);
- element = filter_part_find_element(part, "mlist-type");
- filter_option_set_current((FilterOption *)element, "is");
+ element = e_filter_part_find_element(part, "mlist-type");
+ e_filter_option_set_current((EFilterOption *)element, "is");
- element = filter_part_find_element (part, "mlist");
- filter_input_set_value((FilterInput *)element, mlist);
+ element = e_filter_part_find_element (part, "mlist");
+ e_filter_input_set_value((EFilterInput *)element, mlist);
}
static void
-rule_from_address (FilterRule *rule, RuleContext *context, CamelInternetAddress* addr, gint flags)
+rule_from_address (EFilterRule *rule, ERuleContext *context, CamelInternetAddress* addr, gint flags)
{
- rule->grouping = FILTER_GROUP_ANY;
+ rule->grouping = E_FILTER_GROUP_ANY;
if (flags & AUTO_FROM) {
const gchar *name, *address;
@@ -232,7 +232,7 @@ rule_from_address (FilterRule *rule, RuleContext *context, CamelInternetAddress*
if (name == NULL || name[0] == '\0')
name = address;
namestr = g_strdup_printf(_("Mail from %s"), name);
- filter_rule_set_name (rule, namestr);
+ e_filter_rule_set_name (rule, namestr);
g_free (namestr);
}
if (flags & AUTO_TO) {
@@ -242,11 +242,11 @@ rule_from_address (FilterRule *rule, RuleContext *context, CamelInternetAddress*
}
static void
-rule_from_message (FilterRule *rule, RuleContext *context, CamelMimeMessage *msg, gint flags)
+rule_from_message (EFilterRule *rule, ERuleContext *context, CamelMimeMessage *msg, gint flags)
{
CamelInternetAddress *addr;
- rule->grouping = FILTER_GROUP_ANY;
+ rule->grouping = E_FILTER_GROUP_ANY;
if (flags & AUTO_SUBJECT) {
const gchar *subject = msg->subject ? msg->subject : "";
@@ -255,7 +255,7 @@ rule_from_message (FilterRule *rule, RuleContext *context, CamelMimeMessage *msg
rule_match_subject (context, rule, subject);
namestr = g_strdup_printf (_("Subject is %s"), strip_re (subject));
- filter_rule_set_name (rule, namestr);
+ e_filter_rule_set_name (rule, namestr);
g_free (namestr);
}
/* should parse the from address into an internet address? */
@@ -271,7 +271,7 @@ rule_from_message (FilterRule *rule, RuleContext *context, CamelMimeMessage *msg
if (name == NULL || name[0] == '\0')
name = address;
namestr = g_strdup_printf(_("Mail from %s"), name);
- filter_rule_set_name (rule, namestr);
+ e_filter_rule_set_name (rule, namestr);
g_free (namestr);
}
}
@@ -290,14 +290,14 @@ rule_from_message (FilterRule *rule, RuleContext *context, CamelMimeMessage *msg
if (mlist) {
rule_match_mlist(context, rule, mlist);
name = g_strdup_printf (_("%s mailing list"), mlist);
- filter_rule_set_name(rule, name);
+ e_filter_rule_set_name(rule, name);
g_free(name);
}
g_free(mlist);
}
}
-FilterRule *
+EFilterRule *
em_vfolder_rule_from_message (EMVFolderContext *context, CamelMimeMessage *msg, gint flags, const gchar *source)
{
EMVFolderRule *rule;
@@ -305,13 +305,13 @@ em_vfolder_rule_from_message (EMVFolderContext *context, CamelMimeMessage *msg,
rule = em_vfolder_rule_new ();
em_vfolder_rule_add_source (rule, euri);
- rule_from_message ((FilterRule *)rule, (RuleContext *)context, msg, flags);
+ rule_from_message ((EFilterRule *)rule, (ERuleContext *)context, msg, flags);
g_free(euri);
- return (FilterRule *)rule;
+ return (EFilterRule *)rule;
}
-FilterRule *
+EFilterRule *
em_vfolder_rule_from_address (EMVFolderContext *context, CamelInternetAddress *addr, gint flags, const gchar *source)
{
EMVFolderRule *rule;
@@ -319,25 +319,25 @@ em_vfolder_rule_from_address (EMVFolderContext *context, CamelInternetAddress *a
rule = em_vfolder_rule_new ();
em_vfolder_rule_add_source (rule, euri);
- rule_from_address ((FilterRule *)rule, (RuleContext *)context, addr, flags);
+ rule_from_address ((EFilterRule *)rule, (ERuleContext *)context, addr, flags);
g_free(euri);
- return (FilterRule *)rule;
+ return (EFilterRule *)rule;
}
-FilterRule *
+EFilterRule *
filter_rule_from_message (EMFilterContext *context, CamelMimeMessage *msg, gint flags)
{
EMFilterRule *rule;
- FilterPart *part;
+ EFilterPart *part;
rule = em_filter_rule_new ();
- rule_from_message ((FilterRule *)rule, (RuleContext *)context, msg, flags);
+ rule_from_message ((EFilterRule *)rule, (ERuleContext *)context, msg, flags);
part = em_filter_context_next_action (context, NULL);
- em_filter_rule_add_action (rule, filter_part_clone (part));
+ em_filter_rule_add_action (rule, e_filter_part_clone (part));
- return (FilterRule *)rule;
+ return (EFilterRule *)rule;
}
void
@@ -346,7 +346,7 @@ filter_gui_add_from_message (CamelMimeMessage *msg, const gchar *source, gint fl
EMFilterContext *fc;
const gchar *data_dir;
gchar *user, *system;
- FilterRule *rule;
+ EFilterRule *rule;
g_return_if_fail (msg != NULL);
@@ -354,14 +354,14 @@ filter_gui_add_from_message (CamelMimeMessage *msg, const gchar *source, gint fl
data_dir = em_utils_get_data_dir ();
user = g_build_filename (data_dir, "filters.xml", NULL);
system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL);
- rule_context_load ((RuleContext *)fc, system, user);
+ e_rule_context_load ((ERuleContext *)fc, system, user);
g_free (system);
rule = filter_rule_from_message (fc, msg, flags);
- filter_rule_set_source (rule, source);
+ e_filter_rule_set_source (rule, source);
- rule_context_add_rule_gui ((RuleContext *)fc, rule, _("Add Filter Rule"), user);
+ e_rule_context_add_rule_gui ((ERuleContext *)fc, rule, _("Add Filter Rule"), user);
g_free (user);
g_object_unref (fc);
}
@@ -382,15 +382,15 @@ mail_filter_rename_uri(CamelStore *store, const gchar *olduri, const gchar *newu
data_dir = em_utils_get_data_dir ();
user = g_build_filename (data_dir, "filters.xml", NULL);
system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL);
- rule_context_load ((RuleContext *)fc, system, user);
+ e_rule_context_load ((ERuleContext *)fc, system, user);
g_free (system);
- changed = rule_context_rename_uri((RuleContext *)fc, eolduri, enewuri, g_str_equal);
+ changed = e_rule_context_rename_uri((ERuleContext *)fc, eolduri, enewuri, g_str_equal);
if (changed) {
d(printf("Folder rename '%s' -> '%s' changed filters, resaving\n", olduri, newuri));
- if (rule_context_save((RuleContext *)fc, user) == -1)
+ if (e_rule_context_save((ERuleContext *)fc, user) == -1)
g_warning("Could not write out changed filter rules\n");
- rule_context_free_uri_list((RuleContext *)fc, changed);
+ e_rule_context_free_uri_list((ERuleContext *)fc, changed);
}
g_free(user);
@@ -415,10 +415,10 @@ mail_filter_delete_uri(CamelStore *store, const gchar *uri)
data_dir = em_utils_get_data_dir ();
user = g_build_filename (data_dir, "filters.xml", NULL);
system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL);
- rule_context_load ((RuleContext *)fc, system, user);
+ e_rule_context_load ((ERuleContext *)fc, system, user);
g_free (system);
- deleted = rule_context_delete_uri ((RuleContext *) fc, euri, g_str_equal);
+ deleted = e_rule_context_delete_uri ((ERuleContext *) fc, euri, g_str_equal);
if (deleted) {
GtkWidget *dialog;
GString *s;
@@ -436,9 +436,9 @@ mail_filter_delete_uri(CamelStore *store, const gchar *uri)
em_utils_show_info_silent (dialog);
d(printf("Folder delete/rename '%s' changed filters, resaving\n", euri));
- if (rule_context_save ((RuleContext *) fc, user) == -1)
+ if (e_rule_context_save ((ERuleContext *) fc, user) == -1)
g_warning ("Could not write out changed filter rules\n");
- rule_context_free_uri_list ((RuleContext *) fc, deleted);
+ e_rule_context_free_uri_list ((ERuleContext *) fc, deleted);
}
g_free(user);
diff --git a/mail/mail-autofilter.h b/mail/mail-autofilter.h
index 8ad98589ef..fb474ab04d 100644
--- a/mail/mail-autofilter.h
+++ b/mail/mail-autofilter.h
@@ -26,7 +26,7 @@
#include <camel/camel-mime-message.h>
-#include <filter/filter-rule.h>
+#include <filter/e-filter-rule.h>
#include <mail/em-filter-context.h>
#include <mail/em-vfolder-context.h>
@@ -37,9 +37,9 @@ enum {
AUTO_MLIST = 8
};
-FilterRule *em_vfolder_rule_from_message(EMVFolderContext *context, CamelMimeMessage *msg, gint flags, const gchar *source);
-FilterRule *filter_rule_from_message(EMFilterContext *context, CamelMimeMessage *msg, gint flags);
-FilterRule *em_vfolder_rule_from_address(EMVFolderContext *context, CamelInternetAddress *addr, gint flags, const gchar *source);
+EFilterRule *em_vfolder_rule_from_message(EMVFolderContext *context, CamelMimeMessage *msg, gint flags, const gchar *source);
+EFilterRule *filter_rule_from_message(EMFilterContext *context, CamelMimeMessage *msg, gint flags);
+EFilterRule *em_vfolder_rule_from_address(EMVFolderContext *context, CamelInternetAddress *addr, gint flags, const gchar *source);
/* easiest place to put this */
void filter_gui_add_from_message(CamelMimeMessage *msg, const gchar *source, gint flags);
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index a251c871a9..27b5ef80ce 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -231,13 +231,13 @@ mail_filter_folder (CamelFolder *source_folder, GPtrArray *uids,
void
mail_filter_on_demand (CamelFolder *folder, GPtrArray *uids)
{
- mail_filter_folder (folder, uids, FILTER_SOURCE_DEMAND, FALSE, NULL);
+ mail_filter_folder (folder, uids, E_FILTER_SOURCE_DEMAND, FALSE, NULL);
}
void
mail_filter_junk (CamelFolder *folder, GPtrArray *uids)
{
- mail_filter_folder (folder, uids, FILTER_SOURCE_JUNKTEST, FALSE, NULL);
+ mail_filter_folder (folder, uids, E_FILTER_SOURCE_JUNKTEST, FALSE, NULL);
}
/* ********************************************************************** */
diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c
index b0cff31a9d..6244685842 100644
--- a/mail/mail-send-recv.c
+++ b/mail/mail-send-recv.c
@@ -741,7 +741,7 @@ receive_done (const gchar *uri, gpointer data)
info->again = 0;
mail_send_queue (local_outbox,
info->uri,
- FILTER_SOURCE_OUTGOING,
+ E_FILTER_SOURCE_OUTGOING,
info->cancel,
receive_get_folder, info,
receive_status, info,
@@ -1002,7 +1002,7 @@ mail_send_receive (GtkWindow *parent)
switch (info->type) {
case SEND_RECEIVE:
mail_fetch_mail(info->uri, info->keep_on_server,
- FILTER_SOURCE_INCOMING,
+ E_FILTER_SOURCE_INCOMING,
info->cancel,
receive_get_folder, info,
receive_status, info,
@@ -1011,7 +1011,7 @@ mail_send_receive (GtkWindow *parent)
case SEND_SEND:
/* todo, store the folder in info? */
mail_send_queue(local_outbox, info->uri,
- FILTER_SOURCE_OUTGOING,
+ E_FILTER_SOURCE_OUTGOING,
info->cancel,
receive_get_folder, info,
receive_status, info,
@@ -1217,7 +1217,7 @@ mail_receive_uri (const gchar *uri, gboolean keep_on_server)
switch (info->type) {
case SEND_RECEIVE:
mail_fetch_mail (info->uri, info->keep_on_server,
- FILTER_SOURCE_INCOMING,
+ E_FILTER_SOURCE_INCOMING,
info->cancel,
receive_get_folder, info,
receive_status, info,
@@ -1227,7 +1227,7 @@ mail_receive_uri (const gchar *uri, gboolean keep_on_server)
/* todo, store the folder in info? */
local_outbox = e_mail_local_get_folder (E_MAIL_FOLDER_OUTBOX);
mail_send_queue (local_outbox, info->uri,
- FILTER_SOURCE_OUTGOING,
+ E_FILTER_SOURCE_OUTGOING,
info->cancel,
receive_get_folder, info,
receive_status, info,
@@ -1289,7 +1289,7 @@ mail_send (void)
/* todo, store the folder in info? */
local_outbox = e_mail_local_get_folder (E_MAIL_FOLDER_OUTBOX);
mail_send_queue (local_outbox, info->uri,
- FILTER_SOURCE_OUTGOING,
+ E_FILTER_SOURCE_OUTGOING,
info->cancel,
receive_get_folder, info,
receive_status, info,
diff --git a/mail/mail-session.c b/mail/mail-session.c
index 2b6f902a20..967909d6e3 100644
--- a/mail/mail-session.c
+++ b/mail/mail-session.c
@@ -506,19 +506,19 @@ static CamelFilterDriver *
main_get_filter_driver (CamelSession *session, const gchar *type, CamelException *ex)
{
CamelFilterDriver *driver;
- FilterRule *rule = NULL;
+ EFilterRule *rule = NULL;
const gchar *data_dir;
gchar *user, *system;
GConfClient *gconf;
- RuleContext *fc;
+ ERuleContext *fc;
gconf = mail_config_get_gconf_client ();
data_dir = e_shell_backend_get_data_dir (session_shell_backend);
user = g_build_filename (data_dir, "filters.xml", NULL);
system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL);
- fc = (RuleContext *) em_filter_context_new ();
- rule_context_load (fc, system, user);
+ fc = (ERuleContext *) em_filter_context_new ();
+ e_rule_context_load (fc, system, user);
g_free (system);
g_free (user);
@@ -546,23 +546,23 @@ main_get_filter_driver (CamelSession *session, const gchar *type, CamelException
camel_filter_driver_set_play_sound_func (driver, session_play_sound, NULL);
camel_filter_driver_set_system_beep_func (driver, session_system_beep, NULL);
- if ((!strcmp (type, FILTER_SOURCE_INCOMING) || !strcmp (type, FILTER_SOURCE_JUNKTEST))
+ if ((!strcmp (type, E_FILTER_SOURCE_INCOMING) || !strcmp (type, E_FILTER_SOURCE_JUNKTEST))
&& camel_session_check_junk (session)) {
/* implicit junk check as 1st rule */
camel_filter_driver_add_rule (driver, "Junk check", "(junk-test)", "(begin (set-system-flag \"junk\"))");
}
- if (strcmp (type, FILTER_SOURCE_JUNKTEST) != 0) {
+ if (strcmp (type, E_FILTER_SOURCE_JUNKTEST) != 0) {
GString *fsearch, *faction;
fsearch = g_string_new ("");
faction = g_string_new ("");
- if (!strcmp (type, FILTER_SOURCE_DEMAND))
- type = FILTER_SOURCE_INCOMING;
+ if (!strcmp (type, E_FILTER_SOURCE_DEMAND))
+ type = E_FILTER_SOURCE_INCOMING;
/* add the user-defined rules next */
- while ((rule = rule_context_next_rule (fc, rule, type))) {
+ while ((rule = e_rule_context_next_rule (fc, rule, type))) {
g_string_truncate (fsearch, 0);
g_string_truncate (faction, 0);
@@ -570,7 +570,7 @@ main_get_filter_driver (CamelSession *session, const gchar *type, CamelException
if (!rule->enabled)
continue;
- filter_rule_build_code (rule, fsearch);
+ e_filter_rule_build_code (rule, fsearch);
em_filter_rule_build_action ((EMFilterRule *) rule, faction);
camel_filter_driver_add_rule (driver, rule->name, fsearch->str, faction->str);
}
diff --git a/mail/mail-tools.c b/mail/mail-tools.c
index 4c21a6db4c..1403605b33 100644
--- a/mail/mail-tools.c
+++ b/mail/mail-tools.c
@@ -44,8 +44,8 @@
#include <camel/camel-movemail.h>
#include <camel/camel-vee-folder.h>
-#include "filter/filter-option.h"
-#include "filter/filter-input.h"
+#include "filter/e-filter-option.h"
+#include "filter/e-filter-input.h"
#include <libedataserver/e-data-server-util.h>
#include "em-utils.h"
diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c
index 1612b283c2..9fed82744f 100644
--- a/mail/mail-vfolder.c
+++ b/mail/mail-vfolder.c
@@ -69,7 +69,7 @@ static volatile gint shutdown; /* are we shutting down? */
/* more globals ... */
extern CamelSession *session;
-static void rule_changed(FilterRule *rule, CamelFolder *folder);
+static void rule_changed(EFilterRule *rule, CamelFolder *folder);
/* ********************************************************************** */
@@ -427,7 +427,7 @@ uri_is_spethal(CamelStore *store, const gchar *uri)
void
mail_vfolder_add_uri(CamelStore *store, const gchar *curi, gint remove)
{
- FilterRule *rule;
+ EFilterRule *rule;
const gchar *source;
CamelVeeFolder *vf;
GList *folders = NULL, *link;
@@ -479,7 +479,7 @@ mail_vfolder_add_uri(CamelStore *store, const gchar *curi, gint remove)
goto done;
rule = NULL;
- while ((rule = rule_context_next_rule((RuleContext *)context, rule, NULL))) {
+ while ((rule = e_rule_context_next_rule((ERuleContext *)context, rule, NULL))) {
gint found = FALSE;
if (!rule->name) {
@@ -527,7 +527,7 @@ done:
void
mail_vfolder_delete_uri(CamelStore *store, const gchar *curi)
{
- FilterRule *rule;
+ EFilterRule *rule;
const gchar *source;
CamelVeeFolder *vf;
GString *changed;
@@ -552,7 +552,7 @@ mail_vfolder_delete_uri(CamelStore *store, const gchar *curi)
/* see if any rules directly reference this removed uri */
rule = NULL;
- while ((rule = rule_context_next_rule ((RuleContext *) context, rule, NULL))) {
+ while ((rule = e_rule_context_next_rule ((ERuleContext *) context, rule, NULL))) {
if (!rule->name) {
d(printf("invalid rule (%p): rule->name is set to NULL\n", rule));
@@ -605,7 +605,7 @@ done:
data_dir = em_utils_get_data_dir ();
user = g_build_filename (data_dir, "vfolders.xml", NULL);
- rule_context_save ((RuleContext *) context, user);
+ e_rule_context_save ((ERuleContext *) context, user);
g_free (user);
}
@@ -618,7 +618,7 @@ done:
void
mail_vfolder_rename_uri(CamelStore *store, const gchar *cfrom, const gchar *cto)
{
- FilterRule *rule;
+ EFilterRule *rule;
const gchar *source;
CamelVeeFolder *vf;
gint changed = 0;
@@ -638,7 +638,7 @@ mail_vfolder_rename_uri(CamelStore *store, const gchar *cfrom, const gchar *cto)
/* see if any rules directly reference this removed uri */
rule = NULL;
- while ( (rule = rule_context_next_rule((RuleContext *)context, rule, NULL)) ) {
+ while ( (rule = e_rule_context_next_rule((ERuleContext *)context, rule, NULL)) ) {
source = NULL;
while ( (source = em_vfolder_rule_next_source((EMVFolderRule *)rule, source)) ) {
gchar *csource = em_uri_to_camel(source);
@@ -673,7 +673,7 @@ mail_vfolder_rename_uri(CamelStore *store, const gchar *cfrom, const gchar *cto)
d(printf("Vfolders updated from renamed folder\n"));
data_dir = em_utils_get_data_dir ();
user = g_build_filename (data_dir, "vfolders.xml", NULL);
- rule_context_save((RuleContext *)context, user);
+ e_rule_context_save((ERuleContext *)context, user);
g_free(user);
}
@@ -695,7 +695,7 @@ mail_vfolder_get_sources_remote (void)
/* ********************************************************************** */
-static void context_rule_added(RuleContext *ctx, FilterRule *rule);
+static void context_rule_added(ERuleContext *ctx, EFilterRule *rule);
static void
rule_add_sources(GList *l, GList **sources_folderp, GList **sources_urip)
@@ -722,7 +722,7 @@ rule_add_sources(GList *l, GList **sources_folderp, GList **sources_urip)
}
static void
-rule_changed(FilterRule *rule, CamelFolder *folder)
+rule_changed(EFilterRule *rule, CamelFolder *folder)
{
GList *sources_uri = NULL, *sources_folder = NULL;
GString *query;
@@ -765,14 +765,14 @@ rule_changed(FilterRule *rule, CamelFolder *folder)
G_UNLOCK (vfolder);
query = g_string_new("");
- filter_rule_build_code(rule, query);
+ e_filter_rule_build_code(rule, query);
vfolder_setup(folder, query->str, sources_uri, sources_folder);
g_string_free(query, TRUE);
}
-static void context_rule_added(RuleContext *ctx, FilterRule *rule)
+static void context_rule_added(ERuleContext *ctx, EFilterRule *rule)
{
CamelFolder *folder;
@@ -791,7 +791,7 @@ static void context_rule_added(RuleContext *ctx, FilterRule *rule)
}
}
-static void context_rule_removed(RuleContext *ctx, FilterRule *rule)
+static void context_rule_removed(ERuleContext *ctx, EFilterRule *rule)
{
gpointer key, folder = NULL;
@@ -827,7 +827,7 @@ store_folder_deleted(CamelObject *o, gpointer event_data, gpointer data)
{
CamelStore *store = (CamelStore *)o;
CamelFolderInfo *info = event_data;
- FilterRule *rule;
+ EFilterRule *rule;
gchar *user;
d(printf("Folder deleted: %s\n", info->name));
@@ -838,20 +838,20 @@ store_folder_deleted(CamelObject *o, gpointer event_data, gpointer data)
G_LOCK (vfolder);
/* delete it from our list */
- rule = rule_context_find_rule((RuleContext *)context, info->full_name, NULL);
+ rule = e_rule_context_find_rule((ERuleContext *)context, info->full_name, NULL);
if (rule) {
const gchar *data_dir;
/* We need to stop listening to removed events, otherwise we'll try and remove it again */
g_signal_handlers_disconnect_matched(context, G_SIGNAL_MATCH_FUNC|G_SIGNAL_MATCH_DATA, 0,
0, NULL, context_rule_removed, context);
- rule_context_remove_rule((RuleContext *)context, rule);
+ e_rule_context_remove_rule((ERuleContext *)context, rule);
g_object_unref(rule);
g_signal_connect(context, "rule_removed", G_CALLBACK(context_rule_removed), context);
data_dir = em_utils_get_data_dir ();
user = g_build_filename (data_dir, "vfolders.xml", NULL);
- rule_context_save((RuleContext *)context, user);
+ e_rule_context_save((ERuleContext *)context, user);
g_free(user);
} else {
g_warning("Cannot find rule for deleted vfolder '%s'", info->name);
@@ -864,7 +864,7 @@ static void
store_folder_renamed(CamelObject *o, gpointer event_data, gpointer data)
{
CamelRenameInfo *info = event_data;
- FilterRule *rule;
+ EFilterRule *rule;
gchar *user;
gpointer key, folder;
@@ -883,7 +883,7 @@ store_folder_renamed(CamelObject *o, gpointer event_data, gpointer data)
g_free (key);
g_hash_table_insert (vfolder_hash, g_strdup(info->new->full_name), folder);
- rule = rule_context_find_rule((RuleContext *)context, info->old_base, NULL);
+ rule = e_rule_context_find_rule((ERuleContext *)context, info->old_base, NULL);
if (!rule) {
G_UNLOCK (vfolder);
g_warning ("Rule shouldn't be NULL\n");
@@ -892,12 +892,12 @@ store_folder_renamed(CamelObject *o, gpointer event_data, gpointer data)
g_signal_handlers_disconnect_matched(rule, G_SIGNAL_MATCH_FUNC|G_SIGNAL_MATCH_DATA, 0,
0, NULL, rule_changed, folder);
- filter_rule_set_name(rule, info->new->full_name);
+ e_filter_rule_set_name(rule, info->new->full_name);
g_signal_connect(rule, "changed", G_CALLBACK(rule_changed), folder);
data_dir = em_utils_get_data_dir ();
user = g_build_filename (data_dir, "vfolders.xml", NULL);
- rule_context_save((RuleContext *)context, user);
+ e_rule_context_save((ERuleContext *)context, user);
g_free(user);
G_UNLOCK (vfolder);
@@ -915,7 +915,7 @@ vfolder_load_storage(void)
const gchar *data_dir;
gchar *user, *storeuri;
- FilterRule *rule;
+ EFilterRule *rule;
gchar *xmlfile;
GConfClient *gconf;
@@ -954,9 +954,9 @@ vfolder_load_storage(void)
context = em_vfolder_context_new ();
xmlfile = g_build_filename (EVOLUTION_PRIVDATADIR, "vfoldertypes.xml", NULL);
- if (rule_context_load ((RuleContext *)context,
+ if (e_rule_context_load ((ERuleContext *)context,
xmlfile, user) != 0) {
- g_warning("cannot load vfolders: %s\n", ((RuleContext *)context)->error);
+ g_warning("cannot load vfolders: %s\n", ((ERuleContext *)context)->error);
}
g_free (xmlfile);
g_free (user);
@@ -969,10 +969,10 @@ vfolder_load_storage(void)
/* and setup the rules we have */
rule = NULL;
- while ( (rule = rule_context_next_rule((RuleContext *)context, rule, NULL)) ) {
+ while ( (rule = e_rule_context_next_rule((ERuleContext *)context, rule, NULL)) ) {
if (rule->name) {
d(printf("rule added: %s\n", rule->name));
- context_rule_added((RuleContext *)context, rule);
+ context_rule_added((ERuleContext *)context, rule);
} else {
d(printf("invalid rule (%p) encountered: rule->name is NULL\n", rule));
}
@@ -995,7 +995,7 @@ vfolder_revert(void)
d(printf("vfolder_revert\n"));
data_dir = em_utils_get_data_dir ();
user = g_build_filename (data_dir, "vfolders.xml", NULL);
- rule_context_revert((RuleContext *)context, user);
+ e_rule_context_revert((ERuleContext *)context, user);
g_free(user);
}
@@ -1027,10 +1027,10 @@ vfolder_edit (EShellView *shell_view)
switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
case GTK_RESPONSE_OK:
- rule_context_save ((RuleContext *) context, filename);
+ e_rule_context_save ((ERuleContext *) context, filename);
break;
default:
- rule_context_revert ((RuleContext *) context, filename);
+ e_rule_context_revert ((ERuleContext *) context, filename);
break;
}
@@ -1043,13 +1043,13 @@ edit_rule_response(GtkWidget *w, gint button, gpointer data)
if (button == GTK_RESPONSE_OK) {
const gchar *data_dir;
gchar *user;
- FilterRule *rule = g_object_get_data (G_OBJECT (w), "rule");
- FilterRule *orig = g_object_get_data (G_OBJECT (w), "orig");
+ EFilterRule *rule = g_object_get_data (G_OBJECT (w), "rule");
+ EFilterRule *orig = g_object_get_data (G_OBJECT (w), "orig");
- filter_rule_copy(orig, rule);
+ e_filter_rule_copy(orig, rule);
data_dir = em_utils_get_data_dir ();
user = g_build_filename (data_dir, "vfolders.xml", NULL);
- rule_context_save((RuleContext *)context, user);
+ e_rule_context_save((ERuleContext *)context, user);
g_free(user);
}
@@ -1061,16 +1061,16 @@ vfolder_edit_rule(const gchar *uri)
{
GtkWidget *w;
GtkDialog *gd;
- FilterRule *rule, *newrule;
+ EFilterRule *rule, *newrule;
CamelURL *url;
url = camel_url_new(uri, NULL);
if (url && url->fragment
- && (rule = rule_context_find_rule((RuleContext *)context, url->fragment, NULL))) {
+ && (rule = e_rule_context_find_rule((ERuleContext *)context, url->fragment, NULL))) {
g_object_ref((GtkObject *)rule);
- newrule = filter_rule_clone(rule);
+ newrule = e_filter_rule_clone(rule);
- w = filter_rule_get_widget((FilterRule *)newrule, (RuleContext *)context);
+ w = e_filter_rule_get_widget((EFilterRule *)newrule, (ERuleContext *)context);
gd = (GtkDialog *)gtk_dialog_new_with_buttons(_("Edit Search Folder"), NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -1108,44 +1108,44 @@ new_rule_clicked(GtkWidget *w, gint button, gpointer data)
if (button == GTK_RESPONSE_OK) {
const gchar *data_dir;
gchar *user;
- FilterRule *rule = g_object_get_data((GObject *)w, "rule");
+ EFilterRule *rule = g_object_get_data((GObject *)w, "rule");
- if (!filter_rule_validate (rule, GTK_WINDOW (w))) {
+ if (!e_filter_rule_validate (rule, GTK_WINDOW (w))) {
/* no need to popup a dialog because the validate code does that. */
return;
}
- if (rule_context_find_rule ((RuleContext *)context, rule->name, rule->source)) {
+ if (e_rule_context_find_rule ((ERuleContext *)context, rule->name, rule->source)) {
e_error_run ((GtkWindow *)w, "mail:vfolder-notunique", rule->name, NULL);
return;
}
g_object_ref(rule);
- rule_context_add_rule((RuleContext *)context, rule);
+ e_rule_context_add_rule((ERuleContext *)context, rule);
data_dir = em_utils_get_data_dir ();
user = g_build_filename (data_dir, "vfolders.xml", NULL);
- rule_context_save((RuleContext *)context, user);
+ e_rule_context_save((ERuleContext *)context, user);
g_free(user);
}
gtk_widget_destroy(w);
}
-FilterPart *
+EFilterPart *
vfolder_create_part(const gchar *name)
{
- return rule_context_create_part((RuleContext *)context, name);
+ return e_rule_context_create_part((ERuleContext *)context, name);
}
/* clones a filter/search rule into a matching vfolder rule (assuming the same system definitions) */
-FilterRule *
-vfolder_clone_rule(FilterRule *in)
+EFilterRule *
+vfolder_clone_rule(EFilterRule *in)
{
- FilterRule *rule = (FilterRule *)em_vfolder_rule_new();
+ EFilterRule *rule = (EFilterRule *)em_vfolder_rule_new();
xmlNodePtr xml;
- xml = filter_rule_xml_encode(in);
- filter_rule_xml_decode(rule, xml, (RuleContext *)context);
+ xml = e_filter_rule_xml_encode(in);
+ e_filter_rule_xml_decode(rule, xml, (ERuleContext *)context);
xmlFreeNodeList(xml);
return rule;
@@ -1161,7 +1161,7 @@ vfolder_gui_add_rule(EMVFolderRule *rule)
/* this should be done before we call this function */
vfolder_load_storage ();
- w = filter_rule_get_widget((FilterRule *)rule, (RuleContext *)context);
+ w = e_filter_rule_get_widget((EFilterRule *)rule, (ERuleContext *)context);
gd = (GtkDialog *)gtk_dialog_new_with_buttons(_("New Search Folder"),
NULL,
diff --git a/mail/mail-vfolder.h b/mail/mail-vfolder.h
index b3299ab834..725f7ec348 100644
--- a/mail/mail-vfolder.h
+++ b/mail/mail-vfolder.h
@@ -25,8 +25,8 @@
#include <camel/camel-internet-address.h>
#include <camel/camel-mime-message.h>
-#include <filter/filter-part.h>
-#include <filter/filter-rule.h>
+#include <filter/e-filter-part.h>
+#include <filter/e-filter-rule.h>
#include <mail/em-vfolder-rule.h>
#include <shell/e-shell-view.h>
@@ -35,8 +35,8 @@ void vfolder_revert(void);
void vfolder_edit (EShellView *shell_view);
void vfolder_edit_rule(const gchar *name);
-FilterPart *vfolder_create_part (const gchar *name);
-FilterRule *vfolder_clone_rule (FilterRule *in);
+EFilterPart *vfolder_create_part (const gchar *name);
+EFilterRule *vfolder_clone_rule (EFilterRule *in);
void vfolder_gui_add_rule (EMVFolderRule *rule);
void vfolder_gui_add_from_message (CamelMimeMessage *msg, gint flags, const gchar *source);
void vfolder_gui_add_from_address (CamelInternetAddress *addr, gint flags, const gchar *source);
diff --git a/modules/addressbook/e-book-shell-view-actions.c b/modules/addressbook/e-book-shell-view-actions.c
index 1d875ba91a..c680c64ede 100644
--- a/modules/addressbook/e-book-shell-view-actions.c
+++ b/modules/addressbook/e-book-shell-view-actions.c
@@ -23,7 +23,7 @@
#include <e-util/e-error.h>
#include <e-util/e-util.h>
-#include <filter/filter-rule.h>
+#include <filter/e-filter-rule.h>
#include <addressbook-config.h>
diff --git a/modules/addressbook/e-book-shell-view.c b/modules/addressbook/e-book-shell-view.c
index f7019b0b3a..4a09a14825 100644
--- a/modules/addressbook/e-book-shell-view.c
+++ b/modules/addressbook/e-book-shell-view.c
@@ -131,7 +131,7 @@ book_shell_view_execute_search (EShellView *shell_view)
GString *string;
EAddressbookView *view;
EAddressbookModel *model;
- FilterRule *rule;
+ EFilterRule *rule;
const gchar *format;
const gchar *text;
gchar *query;
@@ -208,10 +208,10 @@ book_shell_view_execute_search (EShellView *shell_view)
}
}
- /* XXX This is wrong. We need to programmatically construct a
- * FilterRule, tell it to build code, and pass the resulting
+ /* XXX This is wrong. We need to programmatically construct an
+ * EFilterRule, tell it to build code, and pass the resulting
* expression string to EAddressbookModel. */
- rule = filter_rule_new ();
+ rule = e_filter_rule_new ();
e_shell_content_set_search_rule (shell_content, rule);
g_object_unref (rule);
diff --git a/modules/calendar/e-cal-shell-view.c b/modules/calendar/e-cal-shell-view.c
index 32f12b605f..41782deb7f 100644
--- a/modules/calendar/e-cal-shell-view.c
+++ b/modules/calendar/e-cal-shell-view.c
@@ -63,7 +63,7 @@ cal_shell_view_execute_search (EShellView *shell_view)
ECalendar *date_navigator;
GtkRadioAction *action;
GString *string;
- FilterRule *rule;
+ EFilterRule *rule;
const gchar *format;
const gchar *text;
time_t start_range;
@@ -179,10 +179,10 @@ cal_shell_view_execute_search (EShellView *shell_view)
}
}
- /* XXX This is wrong. We need to programmatically construct a
- * FilterRule, tell it to build code, and pass the resulting
+ /* XXX This is wrong. We need to programmatically construct an
+ * EFilterRule, tell it to build code, and pass the resulting
* expressing string to ECalModel. */
- rule = filter_rule_new ();
+ rule = e_filter_rule_new ();
e_shell_content_set_search_rule (shell_content, rule);
g_object_unref (rule);
diff --git a/modules/calendar/e-memo-shell-view.c b/modules/calendar/e-memo-shell-view.c
index ea869b55c4..f5698fe9b7 100644
--- a/modules/calendar/e-memo-shell-view.c
+++ b/modules/calendar/e-memo-shell-view.c
@@ -62,7 +62,7 @@ memo_shell_view_execute_search (EShellView *shell_view)
ECalComponentPreview *memo_preview;
EMemoTable *memo_table;
ECalModel *model;
- FilterRule *rule;
+ EFilterRule *rule;
const gchar *format;
const gchar *text;
gchar *query;
@@ -135,10 +135,10 @@ memo_shell_view_execute_search (EShellView *shell_view)
}
}
- /* XXX This is wrong. We need to programmatically construct a
- * FilterRule, tell it to build code, and pass the resulting
+ /* XXX This is wrong. We need to programmatically construct an
+ * EFilterRule, tell it to build code, and pass the resulting
* expression string to ECalModel. */
- rule = filter_rule_new ();
+ rule = e_filter_rule_new ();
e_shell_content_set_search_rule (shell_content, rule);
g_object_unref (rule);
diff --git a/modules/calendar/e-task-shell-view.c b/modules/calendar/e-task-shell-view.c
index 650037b730..ec7d697a9d 100644
--- a/modules/calendar/e-task-shell-view.c
+++ b/modules/calendar/e-task-shell-view.c
@@ -101,7 +101,7 @@ task_shell_view_execute_search (EShellView *shell_view)
ECalComponentPreview *task_preview;
ECalendarTable *task_table;
ECalModel *model;
- FilterRule *rule;
+ EFilterRule *rule;
const gchar *format;
const gchar *text;
time_t start_range;
@@ -247,10 +247,10 @@ task_shell_view_execute_search (EShellView *shell_view)
query = temp2;
}
- /* XXX This is wrong. We need to programmatically construct a
- * FilterRule, tell it to build code, and pass the resulting
+ /* XXX This is wrong. We need to programmatically construct an
+ * EFilterRule, tell it to build code, and pass the resulting
* expression string to ECalModel. */
- rule = filter_rule_new ();
+ rule = e_filter_rule_new ();
e_shell_content_set_search_rule (shell_content, rule);
g_object_unref (rule);
diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c
index 877087c546..0572cfd762 100644
--- a/modules/mail/e-mail-shell-backend.c
+++ b/modules/mail/e-mail-shell-backend.c
@@ -935,7 +935,7 @@ e_mail_shell_backend_register_type (GTypeModule *type_module)
/******************* Code below here belongs elsewhere. *******************/
-#include "filter/filter-option.h"
+#include "filter/e-filter-option.h"
#include "shell/e-shell-settings.h"
#include "mail/e-mail-label-list-store.h"
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index 22aa88edcf..07fdf8f366 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -84,7 +84,7 @@ action_mail_create_search_folder_cb (GtkAction *action,
EShellView *shell_view;
EShellContent *shell_content;
MessageList *message_list;
- FilterRule *search_rule;
+ EFilterRule *search_rule;
EMVFolderRule *vfolder_rule;
const gchar *folder_uri;
const gchar *search_text;
@@ -108,8 +108,8 @@ action_mail_create_search_folder_cb (GtkAction *action,
search_rule = vfolder_clone_rule (search_rule);
rule_name = g_strdup_printf ("%s %s", search_rule->name, search_text);
- filter_rule_set_source (search_rule, FILTER_SOURCE_INCOMING);
- filter_rule_set_name (search_rule, rule_name);
+ e_filter_rule_set_source (search_rule, E_FILTER_SOURCE_INCOMING);
+ e_filter_rule_set_name (search_rule, rule_name);
g_free (rule_name);
vfolder_rule = EM_VFOLDER_RULE (search_rule);
@@ -969,7 +969,7 @@ action_search_quick_cb (GtkAction *action,
EShellView *shell_view;
EShellWindow *shell_window;
EShellContent *shell_content;
- FilterRule *search_rule;
+ EFilterRule *search_rule;
gint value;
/* Set the search rule in EShellContent so that "Create
diff --git a/modules/mail/e-mail-shell-view-private.c b/modules/mail/e-mail-shell-view-private.c
index e6c5417b9a..dd124f43c6 100644
--- a/modules/mail/e-mail-shell-view-private.c
+++ b/modules/mail/e-mail-shell-view-private.c
@@ -347,8 +347,8 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
EShellWindow *shell_window;
EMFormatHTMLDisplay *html_display;
EMFolderTree *folder_tree;
- RuleContext *context;
- FilterRule *rule = NULL;
+ ERuleContext *context;
+ EFilterRule *rule = NULL;
GtkTreeSelection *selection;
GtkTreeModel *tree_model;
GtkUIManager *ui_manager;
@@ -489,8 +489,8 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
* Keep the assertions, please. If the conditions aren't
* met we're going to crash anyway, just more mysteriously. */
context = e_shell_content_get_search_context (shell_content);
- source = FILTER_SOURCE_DEMAND;
- while ((rule = rule_context_next_rule (context, rule, source))) {
+ source = E_FILTER_SOURCE_DEMAND;
+ while ((rule = e_rule_context_next_rule (context, rule, source))) {
g_assert (ii < MAIL_NUM_SEARCH_RULES);
priv->search_rules[ii++] = g_object_ref (rule);
}
@@ -592,11 +592,11 @@ e_mail_shell_view_create_filter_from_selected (EMailShellView *mail_shell_view,
folder = message_list->folder;
if (em_utils_folder_is_sent (folder, folder_uri))
- filter_source = FILTER_SOURCE_OUTGOING;
+ filter_source = E_FILTER_SOURCE_OUTGOING;
else if (em_utils_folder_is_outbox (folder, folder_uri))
- filter_source = FILTER_SOURCE_OUTGOING;
+ filter_source = E_FILTER_SOURCE_OUTGOING;
else
- filter_source = FILTER_SOURCE_INCOMING;
+ filter_source = E_FILTER_SOURCE_INCOMING;
uids = message_list_get_selected (message_list);
diff --git a/modules/mail/e-mail-shell-view-private.h b/modules/mail/e-mail-shell-view-private.h
index a1c823c8f2..bf86f33720 100644
--- a/modules/mail/e-mail-shell-view-private.h
+++ b/modules/mail/e-mail-shell-view-private.h
@@ -35,7 +35,7 @@
#include "e-util/e-binding.h"
#include "e-util/gconf-bridge.h"
#include "e-util/e-account-utils.h"
-#include "filter/filter-part.h"
+#include "filter/e-filter-part.h"
#include "widgets/misc/e-web-view.h"
#include "widgets/misc/e-popup-action.h"
#include "widgets/menus/gal-view-instance.h"
@@ -137,7 +137,7 @@ struct _EMailShellViewPrivate {
guint label_merge_id;
/* Filter rules correspond to the search entry menu. */
- FilterRule *search_rules[MAIL_NUM_SEARCH_RULES];
+ EFilterRule *search_rules[MAIL_NUM_SEARCH_RULES];
guint show_deleted : 1;
};
diff --git a/modules/mail/e-mail-shell-view.c b/modules/mail/e-mail-shell-view.c
index b2ea509422..3c82e516bc 100644
--- a/modules/mail/e-mail-shell-view.c
+++ b/modules/mail/e-mail-shell-view.c
@@ -92,7 +92,7 @@ mail_shell_view_execute_search (EShellView *shell_view)
EMFormatHTMLDisplay *html_display;
EMailShellContent *mail_shell_content;
MessageList *message_list;
- FilterRule *rule;
+ EFilterRule *rule;
EMailReader *reader;
CamelFolder *folder;
GtkAction *action;
@@ -169,17 +169,17 @@ mail_shell_view_execute_search (EShellView *shell_view)
rule = priv->search_rules[value];
for (iter = rule->parts; iter != NULL; iter = iter->next) {
- FilterPart *part = iter->data;
- FilterElement *element = NULL;
+ EFilterPart *part = iter->data;
+ EFilterElement *element = NULL;
if (strcmp (part->name, "subject") == 0)
- element = filter_part_find_element (part, "subject");
+ element = e_filter_part_find_element (part, "subject");
else if (strcmp (part->name, "body") == 0)
- element = filter_part_find_element (part, "word");
+ element = e_filter_part_find_element (part, "word");
else if (strcmp (part->name, "sender") == 0)
- element = filter_part_find_element (part, "sender");
+ element = e_filter_part_find_element (part, "sender");
else if (strcmp (part->name, "to") == 0)
- element = filter_part_find_element (part, "recipient");
+ element = e_filter_part_find_element (part, "recipient");
if (strcmp (part->name, "body") == 0) {
struct _camel_search_words *words;
@@ -194,13 +194,13 @@ mail_shell_view_execute_search (EShellView *shell_view)
}
if (element != NULL) {
- FilterInput *input = FILTER_INPUT (element);
- filter_input_set_value (input, text);
+ EFilterInput *input = E_FILTER_INPUT (element);
+ e_filter_input_set_value (input, text);
}
}
string = g_string_sized_new (1024);
- filter_rule_build_code (rule, string);
+ e_filter_rule_build_code (rule, string);
query = g_string_free (string, FALSE);
filter:
diff --git a/plugins/groupwise-features/share-folder-common.c b/plugins/groupwise-features/share-folder-common.c
index 3856fcc7a3..b00559a81c 100644
--- a/plugins/groupwise-features/share-folder-common.c
+++ b/plugins/groupwise-features/share-folder-common.c
@@ -37,7 +37,7 @@
#include <mail/mail-config.h>
#include <mail/mail-vfolder.h>
#include <mail/em-vfolder-rule.h>
-#include <filter/filter-rule.h>
+#include <filter/e-filter-rule.h>
#include <camel/camel-store.h>
#include <camel/camel-session.h>
#include <camel/camel-store.h>
@@ -276,7 +276,7 @@ users_dialog_response(GtkWidget *dialog, gint response, struct ShareInfo *ssi)
vfolder_load_storage ();
rule = em_vfolder_rule_new();
- filter_rule_set_name((FilterRule *)rule, path);
+ e_filter_rule_set_name((EFilterRule *)rule, path);
vfolder_gui_add_rule(rule);
gtk_widget_destroy((GtkWidget *)emfs);
} else {
diff --git a/shell/e-shell-content.c b/shell/e-shell-content.c
index 6761af7296..5d2f3df61b 100644
--- a/shell/e-shell-content.c
+++ b/shell/e-shell-content.c
@@ -25,7 +25,7 @@
#include "e-util/e-binding.h"
#include "e-util/e-util.h"
-#include "filter/rule-editor.h"
+#include "filter/e-rule-editor.h"
#include "widgets/misc/e-action-combo-box.h"
#include "widgets/misc/e-hinted-entry.h"
@@ -45,8 +45,8 @@ struct _EShellContentPrivate {
gpointer shell_view; /* weak pointer */
- RuleContext *search_context;
- FilterRule *search_rule;
+ ERuleContext *search_context;
+ EFilterRule *search_rule;
gchar *system_filename;
gchar *user_filename;
@@ -81,7 +81,7 @@ static gpointer parent_class;
static void
shell_content_dialog_rule_changed (GtkWidget *dialog,
- FilterRule *rule)
+ EFilterRule *rule)
{
gboolean sensitive;
@@ -264,9 +264,9 @@ shell_content_init_search_context (EShellContent *shell_content)
EShellView *shell_view;
EShellViewClass *shell_view_class;
EShellBackend *shell_backend;
- RuleContext *context;
- FilterRule *rule;
- FilterPart *part;
+ ERuleContext *context;
+ EFilterRule *rule;
+ EFilterPart *part;
gchar *system_filename;
gchar *user_filename;
@@ -291,13 +291,13 @@ shell_content_init_search_context (EShellContent *shell_content)
"searches.xml", NULL);
context = shell_content_class->new_search_context ();
- rule_context_add_part_set (
- context, "partset", FILTER_TYPE_PART,
- rule_context_add_part, rule_context_next_part);
- rule_context_add_rule_set (
- context, "ruleset", FILTER_TYPE_RULE,
- rule_context_add_rule, rule_context_next_rule);
- rule_context_load (context, system_filename, user_filename);
+ e_rule_context_add_part_set (
+ context, "partset", E_TYPE_FILTER_PART,
+ e_rule_context_add_part, e_rule_context_next_part);
+ e_rule_context_add_rule_set (
+ context, "ruleset", E_TYPE_FILTER_RULE,
+ e_rule_context_add_rule, e_rule_context_next_rule);
+ e_rule_context_load (context, system_filename, user_filename);
/* XXX Not sure why this is necessary. */
g_object_set_data_full (
@@ -307,14 +307,14 @@ shell_content_init_search_context (EShellContent *shell_content)
G_OBJECT (context), "user",
g_strdup (user_filename), g_free);
- rule = filter_rule_new ();
- part = rule_context_next_part (context, NULL);
+ rule = e_filter_rule_new ();
+ part = e_rule_context_next_part (context, NULL);
if (part == NULL)
g_warning (
"Could not load %s search: no parts",
e_shell_view_get_name (shell_view));
else
- filter_rule_add_part (rule, filter_part_clone (part));
+ e_filter_rule_add_part (rule, e_filter_part_clone (part));
shell_content->priv->search_context = context;
shell_content->priv->system_filename = system_filename;
@@ -701,7 +701,7 @@ shell_content_class_init (EShellContentClass *class)
container_class = GTK_CONTAINER_CLASS (class);
container_class->forall = shell_content_forall;
- class->new_search_context = rule_context_new;
+ class->new_search_context = e_rule_context_new;
g_object_class_install_property (
object_class,
@@ -743,7 +743,7 @@ shell_content_class_init (EShellContentClass *class)
"search-context",
NULL,
NULL,
- RULE_TYPE_CONTEXT,
+ E_TYPE_RULE_CONTEXT,
G_PARAM_READABLE));
g_object_class_install_property (
@@ -763,7 +763,7 @@ shell_content_class_init (EShellContentClass *class)
"search-rule",
NULL,
NULL,
- FILTER_TYPE_RULE,
+ E_TYPE_FILTER_RULE,
G_PARAM_READWRITE));
g_object_class_install_property (
@@ -1138,7 +1138,7 @@ e_shell_content_add_filter_separator_after (EShellContent *shell_content,
e_action_combo_box_add_separator_after (combo_box, action_value);
}
-RuleContext *
+ERuleContext *
e_shell_content_get_search_context (EShellContent *shell_content)
{
g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL);
@@ -1173,7 +1173,7 @@ e_shell_content_set_search_hint (EShellContent *shell_content,
g_object_notify (G_OBJECT (shell_content), "search-hint");
}
-FilterRule *
+EFilterRule *
e_shell_content_get_search_rule (EShellContent *shell_content)
{
g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL);
@@ -1183,12 +1183,12 @@ e_shell_content_get_search_rule (EShellContent *shell_content)
void
e_shell_content_set_search_rule (EShellContent *shell_content,
- FilterRule *search_rule)
+ EFilterRule *search_rule)
{
g_return_if_fail (E_IS_SHELL_CONTENT (shell_content));
if (search_rule != NULL) {
- g_return_if_fail (IS_FILTER_RULE (search_rule));
+ g_return_if_fail (E_IS_FILTER_RULE (search_rule));
g_object_ref (search_rule);
}
@@ -1336,8 +1336,8 @@ e_shell_content_run_advanced_search_dialog (EShellContent *shell_content)
EShellWindow *shell_window;
GtkWidget *dialog;
GtkWidget *widget;
- FilterRule *rule;
- RuleContext *context;
+ EFilterRule *rule;
+ ERuleContext *context;
const gchar *user_filename;
gint response;
@@ -1350,13 +1350,13 @@ e_shell_content_run_advanced_search_dialog (EShellContent *shell_content)
rule = e_shell_content_get_search_rule (shell_content);
if (rule == NULL)
- rule = filter_rule_new ();
+ rule = e_filter_rule_new ();
else
- rule = filter_rule_clone (rule);
+ rule = e_filter_rule_clone (rule);
context = e_shell_content_get_search_context (shell_content);
- widget = filter_rule_get_widget (rule, context);
- filter_rule_set_source (rule, FILTER_SOURCE_INCOMING);
+ widget = e_filter_rule_get_widget (rule, context);
+ e_filter_rule_set_source (rule, E_FILTER_SOURCE_INCOMING);
dialog = gtk_dialog_new_with_buttons (
_("Advanced Search"), GTK_WINDOW (shell_window),
@@ -1384,7 +1384,7 @@ run:
if (response != GTK_RESPONSE_OK && response != GTK_RESPONSE_APPLY)
goto exit;
- if (!filter_rule_validate (rule, GTK_WINDOW (dialog)))
+ if (!e_filter_rule_validate (rule, GTK_WINDOW (dialog)))
goto run;
e_shell_content_set_search_rule (shell_content, rule);
@@ -1392,9 +1392,9 @@ run:
e_shell_view_execute_search (shell_view);
if (response == GTK_RESPONSE_APPLY) {
- if (!rule_context_find_rule (context, rule->name, rule->source))
- rule_context_add_rule (context, rule);
- rule_context_save (context, user_filename);
+ if (!e_rule_context_find_rule (context, rule->name, rule->source))
+ e_rule_context_add_rule (context, rule);
+ e_rule_context_save (context, user_filename);
goto run;
}
@@ -1406,8 +1406,8 @@ exit:
void
e_shell_content_run_edit_searches_dialog (EShellContent *shell_content)
{
- RuleContext *context;
- RuleEditor *editor;
+ ERuleContext *context;
+ ERuleEditor *editor;
const gchar *user_filename;
g_return_if_fail (E_IS_SHELL_CONTENT (shell_content));
@@ -1415,12 +1415,12 @@ e_shell_content_run_edit_searches_dialog (EShellContent *shell_content)
context = e_shell_content_get_search_context (shell_content);
user_filename = shell_content->priv->user_filename;
- editor = rule_editor_new (
- context, FILTER_SOURCE_INCOMING, _("Searches"));
+ editor = e_rule_editor_new (
+ context, E_FILTER_SOURCE_INCOMING, _("Searches"));
gtk_window_set_title (GTK_WINDOW (editor), _("Searches"));
if (gtk_dialog_run (GTK_DIALOG (editor)) == GTK_RESPONSE_OK)
- rule_context_save (context, user_filename);
+ e_rule_context_save (context, user_filename);
gtk_widget_destroy (GTK_WIDGET (editor));
}
@@ -1432,8 +1432,8 @@ e_shell_content_run_save_search_dialog (EShellContent *shell_content)
EShellWindow *shell_window;
GtkWidget *dialog;
GtkWidget *widget;
- FilterRule *rule;
- RuleContext *context;
+ EFilterRule *rule;
+ ERuleContext *context;
const gchar *search_text;
const gchar *user_filename;
gchar *search_name;
@@ -1446,20 +1446,20 @@ e_shell_content_run_save_search_dialog (EShellContent *shell_content)
user_filename = shell_content->priv->user_filename;
rule = e_shell_content_get_search_rule (shell_content);
- g_return_if_fail (IS_FILTER_RULE (rule));
- rule = filter_rule_clone (rule);
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
+ rule = e_filter_rule_clone (rule);
search_text = e_shell_content_get_search_text (shell_content);
if (search_text == NULL || *search_text == '\0')
search_text = "''";
search_name = g_strdup_printf ("%s %s", rule->name, search_text);
- filter_rule_set_name (rule, search_name);
+ e_filter_rule_set_name (rule, search_name);
g_free (search_name);
context = e_shell_content_get_search_context (shell_content);
- widget = filter_rule_get_widget (rule, context);
- filter_rule_set_source (rule, FILTER_SOURCE_INCOMING);
+ widget = e_filter_rule_get_widget (rule, context);
+ e_filter_rule_set_source (rule, E_FILTER_SOURCE_INCOMING);
dialog = gtk_dialog_new_with_buttons (
_("Save Search"), GTK_WINDOW (shell_window),
@@ -1486,11 +1486,11 @@ run:
if (response != GTK_RESPONSE_OK)
goto exit;
- if (!filter_rule_validate (rule, GTK_WINDOW (dialog)))
+ if (!e_filter_rule_validate (rule, GTK_WINDOW (dialog)))
goto run;
- rule_context_add_rule (context, rule);
- rule_context_save (context, user_filename);
+ e_rule_context_add_rule (context, rule);
+ e_rule_context_save (context, user_filename);
exit:
g_object_unref (rule);
diff --git a/shell/e-shell-content.h b/shell/e-shell-content.h
index 8e754fff26..9449040072 100644
--- a/shell/e-shell-content.h
+++ b/shell/e-shell-content.h
@@ -29,8 +29,8 @@
#define E_SHELL_CONTENT_H
#include <shell/e-shell-common.h>
-#include <filter/filter-rule.h>
-#include <filter/rule-context.h>
+#include <filter/e-filter-rule.h>
+#include <filter/e-rule-context.h>
/* Standard GObject macros */
#define E_TYPE_SHELL_CONTENT \
@@ -75,7 +75,7 @@ struct _EShellContentClass {
GtkBinClass parent_class;
/* Factory Methods */
- RuleContext * (*new_search_context) (void);
+ ERuleContext * (*new_search_context) (void);
guint32 (*check_state) (EShellContent *shell_content);
};
@@ -104,14 +104,14 @@ void e_shell_content_add_filter_separator_before
void e_shell_content_add_filter_separator_after
(EShellContent *shell_content,
gint action_value);
-RuleContext * e_shell_content_get_search_context
+ERuleContext * e_shell_content_get_search_context
(EShellContent *shell_content);
const gchar * e_shell_content_get_search_hint (EShellContent *shell_content);
void e_shell_content_set_search_hint (EShellContent *shell_content,
const gchar *search_hint);
-FilterRule * e_shell_content_get_search_rule (EShellContent *shell_content);
+EFilterRule * e_shell_content_get_search_rule (EShellContent *shell_content);
void e_shell_content_set_search_rule (EShellContent *shell_content,
- FilterRule *search_rule);
+ EFilterRule *search_rule);
const gchar * e_shell_content_get_search_text (EShellContent *shell_content);
void e_shell_content_set_search_text (EShellContent *shell_content,
const gchar *search_text);
diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c
index 3eb25e23b5..46cb321248 100644
--- a/shell/e-shell-window-actions.c
+++ b/shell/e-shell-window-actions.c
@@ -702,7 +702,7 @@ static void
action_custom_rule_cb (GtkAction *action,
EShellWindow *shell_window)
{
- FilterRule *rule;
+ EFilterRule *rule;
EShellView *shell_view;
EShellContent *shell_content;
const gchar *view_name;
@@ -715,7 +715,7 @@ action_custom_rule_cb (GtkAction *action,
shell_content = e_shell_view_get_shell_content (shell_view);
rule = g_object_get_data (G_OBJECT (action), "rule");
- g_return_if_fail (IS_FILTER_RULE (rule));
+ g_return_if_fail (E_IS_FILTER_RULE (rule));
e_shell_content_set_search_rule (shell_content, rule);
@@ -2231,8 +2231,8 @@ e_shell_window_update_search_menu (EShellWindow *shell_window)
EShellContent *shell_content;
EShellView *shell_view;
EShellViewClass *shell_view_class;
- RuleContext *context;
- FilterRule *rule;
+ ERuleContext *context;
+ EFilterRule *rule;
GtkUIManager *ui_manager;
GtkActionGroup *action_group;
const gchar *source;
@@ -2247,7 +2247,7 @@ e_shell_window_update_search_menu (EShellWindow *shell_window)
shell_content = e_shell_view_get_shell_content (shell_view);
context = e_shell_content_get_search_context (shell_content);
shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view);
- source = FILTER_SOURCE_INCOMING;
+ source = E_FILTER_SOURCE_INCOMING;
/* Update sensitivity of search actions. */
@@ -2267,7 +2267,7 @@ e_shell_window_update_search_menu (EShellWindow *shell_window)
gtk_ui_manager_remove_ui (ui_manager, merge_id);
e_action_group_remove_all_actions (action_group);
- rule = rule_context_next_rule (context, NULL, source);
+ rule = e_rule_context_next_rule (context, NULL, source);
while (rule != NULL) {
GtkAction *action;
gchar *action_name;
@@ -2304,6 +2304,6 @@ e_shell_window_update_search_menu (EShellWindow *shell_window)
g_free (action_name);
g_free (action_label);
- rule = rule_context_next_rule (context, rule, source);
+ rule = e_rule_context_next_rule (context, rule, source);
}
}