aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--filter/ChangeLog26
-rw-r--r--filter/Makefile.am4
-rw-r--r--filter/filter-filter.c2
-rw-r--r--filter/filter-folder.c2
-rw-r--r--filter/filter-input.c14
-rw-r--r--filter/filter-option.c7
-rw-r--r--filter/filter-option.h1
-rw-r--r--filter/filter-rule.c18
-rw-r--r--filter/filter-rule.h3
-rw-r--r--filter/filter.glade160
-rw-r--r--filter/rule-context.c17
-rw-r--r--filter/rule-context.h5
-rw-r--r--filter/vfolder-context.c3
-rw-r--r--filter/vfolder-rule.c354
-rw-r--r--filter/vfolder-rule.h59
15 files changed, 668 insertions, 7 deletions
diff --git a/filter/ChangeLog b/filter/ChangeLog
index c2008adab9..70ef7fe69d 100644
--- a/filter/ChangeLog
+++ b/filter/ChangeLog
@@ -1,3 +1,29 @@
+2000-07-31 Not Zed <NotZed@HelixCode.com>
+
+ * filter-input.c (filter_input_set_value): Set value of a simple
+ type to a new string.
+
+ * filter-option.c (filter_option_set_current): New function to set
+ the current value of an option.
+
+ * filter-rule.c (filter_rule_find_list): New function to find a
+ rule in a list, by name.
+ (filter_rule_set_name): Let you set the name of a rule.
+
+ * rule-context.c (rule_context_find_rule): Find a rule by name.
+ (rule_context_create_part): Helper to find and clone a part by
+ name.
+
+ * filter-folder.c (button_clicked): Fix warning.
+
+ * filter.glade: Add new widgets for vfolder rule editor.
+
+ * vfolder-context.c (vfolder_context_init): Changed to use vfolder
+ rule as the rule type.
+
+ * vfolder-rule.c: New class to encode extra information required
+ for vfolder rules.
+
2000-07-30 Not Zed <NotZed@HelixCode.com>
** Almost a total rewrite of every file, except for filter-driver
diff --git a/filter/Makefile.am b/filter/Makefile.am
index f6b31dcfc8..e8195559ee 100644
--- a/filter/Makefile.am
+++ b/filter/Makefile.am
@@ -55,7 +55,9 @@ libfilter_la_SOURCES = \
vfolder-context.c \
vfolder-context.h \
vfolder-editor.c \
- vfolder-editor.h
+ vfolder-editor.h \
+ vfolder-rule.c \
+ vfolder-rule.h
EXTRA_DIST = blank.xpm check.xpm \
filtertypes.xml vfoldertypes.xml
diff --git a/filter/filter-filter.c b/filter/filter-filter.c
index 9e902dbbd8..db974ef029 100644
--- a/filter/filter-filter.c
+++ b/filter/filter-filter.c
@@ -25,7 +25,7 @@
#include "filter-filter.h"
#include "filter-context.h"
-#define d(x) x
+#define d(x)
static xmlNodePtr xml_encode(FilterRule *);
static int xml_decode(FilterRule *, xmlNodePtr, struct _RuleContext *f);
diff --git a/filter/filter-folder.c b/filter/filter-folder.c
index fa3fe913ae..b5be1be8a9 100644
--- a/filter/filter-folder.c
+++ b/filter/filter-folder.c
@@ -196,7 +196,7 @@ static void button_clicked(GtkButton *button, FilterFolder *ff)
str = uri;
ff->name = g_strdup(str);
- gtk_label_set_text(GTK_BIN(button)->child, ff->name);
+ gtk_label_set_text((GtkLabel *)GTK_BIN(button)->child, ff->name);
} else {
g_free(uri);
}
diff --git a/filter/filter-input.c b/filter/filter-input.c
index eca5afd2ff..f422a091b1 100644
--- a/filter/filter-input.c
+++ b/filter/filter-input.c
@@ -135,6 +135,20 @@ FilterInput *filter_input_new_type_name (const char *type)
return o;
}
+void filter_input_set_value(FilterInput *fi, const char *value)
+{
+ GList *l;
+
+ 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 void xml_create(FilterElement *fe, xmlNodePtr node)
{
/* parent implementation */
diff --git a/filter/filter-option.c b/filter/filter-option.c
index 31be216f25..bbf1a8ef90 100644
--- a/filter/filter-option.c
+++ b/filter/filter-option.c
@@ -146,6 +146,13 @@ find_option(FilterOption *fo, const char *name)
return NULL;
}
+void filter_option_set_current(FilterOption *option, const char *name)
+{
+ g_assert(IS_FILTER_OPTION(option));
+
+ option->current = find_option(option, name);
+}
+
static void xml_create(FilterElement *fe, xmlNodePtr node)
{
FilterOption *fo = (FilterOption *)fe;
diff --git a/filter/filter-option.h b/filter/filter-option.h
index 1645b333a1..1bbec79d84 100644
--- a/filter/filter-option.h
+++ b/filter/filter-option.h
@@ -58,6 +58,7 @@ guint filter_option_get_type (void);
FilterOption *filter_option_new (void);
/* methods */
+void filter_option_set_current(FilterOption *option, const char *name);
#endif /* ! _FILTER_OPTION_H */
diff --git a/filter/filter-rule.c b/filter/filter-rule.c
index 9e1da43164..9c47af6daf 100644
--- a/filter/filter-rule.c
+++ b/filter/filter-rule.c
@@ -133,6 +133,12 @@ filter_rule_new(void)
return o;
}
+void filter_rule_set_name (FilterRule *fr, const char *name)
+{
+ g_free(fr->name);
+ fr->name = g_strdup(name);
+}
+
xmlNodePtr filter_rule_xml_encode (FilterRule *fr)
{
return ((FilterRuleClass *)((GtkObject *)fr)->klass)->xml_encode(fr);
@@ -523,3 +529,15 @@ FilterRule *filter_rule_next_list (GList *l, FilterRule *last)
return node->data;
return NULL;
}
+
+FilterRule *filter_rule_find_list (GList *l, const char *name)
+{
+ while (l) {
+ FilterRule *rule = l->data;
+ if (!strcmp(rule->name, name))
+ return rule;
+ l = g_list_next(l);
+ }
+ return NULL;
+}
+
diff --git a/filter/filter-rule.h b/filter/filter-rule.h
index ca5b1ddfb7..396af19e59 100644
--- a/filter/filter-rule.h
+++ b/filter/filter-rule.h
@@ -67,6 +67,8 @@ guint filter_rule_get_type (void);
FilterRule *filter_rule_new (void);
/* methods */
+void filter_rule_set_name (FilterRule *fr, const char *name);
+
xmlNodePtr filter_rule_xml_encode (FilterRule *fr);
int filter_rule_xml_decode (FilterRule *fr, xmlNodePtr node, struct _RuleContext *f);
@@ -83,6 +85,7 @@ void filter_rule_build_action(FilterRule *fr, GString *out);
/* static functions */
FilterRule *filter_rule_next_list (GList *l, FilterRule *last);
+FilterRule *filter_rule_find_list (GList *l, const char *name);
#endif /* ! _FILTER_RULE_H */
diff --git a/filter/filter.glade b/filter/filter.glade
index 7592bc30fd..ff40068aa7 100644
--- a/filter/filter.glade
+++ b/filter/filter.glade
@@ -380,4 +380,164 @@ Outgoing
</widget>
</widget>
+<widget>
+ <class>GnomeDialog</class>
+ <name>vfolder_source</name>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>False</allow_grow>
+ <auto_shrink>False</auto_shrink>
+ <auto_close>False</auto_close>
+ <hide_on_close>False</hide_on_close>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>GnomeDialog:vbox</child_name>
+ <name>dialog-vbox3</name>
+ <homogeneous>False</homogeneous>
+ <spacing>8</spacing>
+ <child>
+ <padding>4</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHButtonBox</class>
+ <child_name>GnomeDialog:action_area</child_name>
+ <name>dialog-action_area3</name>
+ <layout_style>GTK_BUTTONBOX_END</layout_style>
+ <spacing>8</spacing>
+ <child_min_width>85</child_min_width>
+ <child_min_height>27</child_min_height>
+ <child_ipad_x>7</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button16</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button17</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <stock_button>GNOME_STOCK_BUTTON_APPLY</stock_button>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button18</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>vfolder_source_frame</name>
+ <label>vFolder Sources</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox3</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>scrolledwindow3</name>
+ <width>256</width>
+ <height>125</height>
+ <hscrollbar_policy>GTK_POLICY_AUTOMATIC</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkViewport</class>
+ <name>viewport3</name>
+ <shadow_type>GTK_SHADOW_IN</shadow_type>
+
+ <widget>
+ <class>GtkList</class>
+ <name>source_list</name>
+ <selection_mode>GTK_SELECTION_SINGLE</selection_mode>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox3</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkVButtonBox</class>
+ <name>vbuttonbox3</name>
+ <layout_style>GTK_BUTTONBOX_DEFAULT_STYLE</layout_style>
+ <spacing>0</spacing>
+ <child_min_width>85</child_min_width>
+ <child_min_height>27</child_min_height>
+ <child_ipad_x>6</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>source_add</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <label>Add</label>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>source_remove</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <label>Remove</label>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
</GTK-Interface>
diff --git a/filter/rule-context.c b/filter/rule-context.c
index e6a18d078a..5335882932 100644
--- a/filter/rule-context.c
+++ b/filter/rule-context.c
@@ -306,12 +306,22 @@ static int save(RuleContext *f, const char *user)
return 0;
}
-FilterPart *rule_context_find_part(RuleContext *f, char *name)
+FilterPart *rule_context_find_part(RuleContext *f, const char *name)
{
d(printf("find part : "));
return filter_part_find_list(f->parts, name);
}
+FilterPart *rule_context_create_part(RuleContext *f, const char *name)
+{
+ FilterPart *part;
+
+ part = rule_context_find_part(f, name);
+ if (part)
+ part = filter_part_clone(part);
+ return part;
+}
+
FilterPart *rule_context_next_part(RuleContext *f, FilterPart *last)
{
return filter_part_next_list(f->parts, last);
@@ -322,6 +332,11 @@ FilterRule *rule_context_next_rule(RuleContext *f, FilterRule *last)
return filter_rule_next_list(f->rules, last);
}
+FilterRule *rule_context_find_rule(RuleContext *f, const char *name)
+{
+ return filter_rule_find_list(f->rules, name);
+}
+
void rule_context_add_part(RuleContext *f, FilterPart *part)
{
f->parts = g_list_append(f->parts, part);
diff --git a/filter/rule-context.h b/filter/rule-context.h
index f2b59cd3c0..6a442d504b 100644
--- a/filter/rule-context.h
+++ b/filter/rule-context.h
@@ -89,11 +89,12 @@ int rule_context_load(RuleContext *f, const char *system, const char *user);
int rule_context_save(RuleContext *f, const char *user);
void rule_context_add_part(RuleContext *f, FilterPart *new);
-FilterPart *rule_context_find_part(RuleContext *f, char *name);
-/*FilterPart *rule_context_create_part(RuleContext *f, char *name);*/
+FilterPart *rule_context_find_part(RuleContext *f, const char *name);
+FilterPart *rule_context_create_part(RuleContext *f, const char *name);
FilterPart *rule_context_next_part(RuleContext *f, FilterPart *last);
FilterRule *rule_context_next_rule(RuleContext *f, FilterRule *last);
+FilterRule *rule_context_find_rule(RuleContext *f, const char *name);
void rule_context_add_rule(RuleContext *f, FilterRule *new);
void rule_context_remove_rule(RuleContext *f, FilterRule *rule);
diff --git a/filter/vfolder-context.c b/filter/vfolder-context.c
index 0202c71847..41453ea310 100644
--- a/filter/vfolder-context.c
+++ b/filter/vfolder-context.c
@@ -22,6 +22,7 @@
#include <gnome.h>
#include "vfolder-context.h"
+#include "vfolder-rule.h"
static void vfolder_context_class_init (VfolderContextClass *class);
static void vfolder_context_init (VfolderContext *gspaper);
@@ -86,7 +87,7 @@ vfolder_context_init (VfolderContext *o)
rule_context_add_part_set((RuleContext *)o, "partset", filter_part_get_type(),
rule_context_add_part, rule_context_next_part);
- rule_context_add_rule_set((RuleContext *)o, "ruleset", filter_rule_get_type(),
+ rule_context_add_rule_set((RuleContext *)o, "ruleset", vfolder_rule_get_type(),
rule_context_add_rule, rule_context_next_rule);
}
diff --git a/filter/vfolder-rule.c b/filter/vfolder-rule.c
new file mode 100644
index 0000000000..d6da471b07
--- /dev/null
+++ b/filter/vfolder-rule.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2000 Helix Code Inc.
+ *
+ * Authors: Not Zed <notzed@lostzed.mmc.com.au>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gnome.h>
+#include <glade/glade.h>
+
+#include "vfolder-context.h"
+#include "vfolder-rule.h"
+#include "shell/evolution-shell-client.h"
+
+#define d(x) x
+
+static xmlNodePtr xml_encode(FilterRule *);
+static int xml_decode(FilterRule *, xmlNodePtr, struct _RuleContext *f);
+/*static void build_code(FilterRule *, GString *out);*/
+static GtkWidget *get_widget(FilterRule *fr, struct _RuleContext *f);
+
+extern EvolutionShellClient *global_shell_client;
+
+static void vfolder_rule_class_init (VfolderRuleClass *class);
+static void vfolder_rule_init (VfolderRule *gspaper);
+static void vfolder_rule_finalise (GtkObject *obj);
+
+#define _PRIVATE(x) (((VfolderRule *)(x))->priv)
+
+struct _VfolderRulePrivate {
+};
+
+static FilterRuleClass *parent_class;
+
+guint
+vfolder_rule_get_type (void)
+{
+ static guint type = 0;
+
+ if (!type) {
+ GtkTypeInfo type_info = {
+ "VfolderRule",
+ sizeof(VfolderRule),
+ sizeof(VfolderRuleClass),
+ (GtkClassInitFunc)vfolder_rule_class_init,
+ (GtkObjectInitFunc)vfolder_rule_init,
+ (GtkArgSetFunc)NULL,
+ (GtkArgGetFunc)NULL
+ };
+
+ type = gtk_type_unique(filter_rule_get_type (), &type_info);
+ }
+
+ return type;
+}
+
+static void
+vfolder_rule_class_init (VfolderRuleClass *class)
+{
+ GtkObjectClass *object_class;
+ FilterRuleClass *filter_rule = (FilterRuleClass *)class;
+
+ object_class = (GtkObjectClass *)class;
+ parent_class = gtk_type_class(filter_rule_get_type ());
+
+ object_class->finalize = vfolder_rule_finalise;
+
+ /* override methods */
+ filter_rule->xml_encode = xml_encode;
+ filter_rule->xml_decode = xml_decode;
+ /*filter_rule->build_code = build_code;*/
+ filter_rule->get_widget = get_widget;
+}
+
+static void
+vfolder_rule_init (VfolderRule *o)
+{
+ o->priv = g_malloc0(sizeof(*o->priv));
+}
+
+static void
+vfolder_rule_finalise(GtkObject *obj)
+{
+ VfolderRule *o = (VfolderRule *)obj;
+ o = o;
+ ((GtkObjectClass *)(parent_class))->finalize(obj);
+}
+
+/**
+ * vfolder_rule_new:
+ *
+ * Create a new VfolderRule object.
+ *
+ * Return value: A new #VfolderRule object.
+ **/
+VfolderRule *
+vfolder_rule_new(void)
+{
+ VfolderRule *o = (VfolderRule *)gtk_type_new(vfolder_rule_get_type ());
+ return o;
+}
+
+void vfolder_rule_add_source (VfolderRule *vr, const char *uri)
+{
+ g_assert(IS_VFOLDER_RULE(vr));
+
+ vr->sources = g_list_append(vr->sources, g_strdup(uri));
+}
+
+const char *vfolder_rule_find_source (VfolderRule *vr, const char *uri)
+{
+ GList *l;
+
+ g_assert(IS_VFOLDER_RULE(vr));
+
+ /* only does a simple string or address comparison, should
+ probably do a decoded url comparison */
+ l = vr->sources;
+ while (l) {
+ if (l->data == uri || !strcmp(l->data, uri))
+ return l->data;
+ l = g_list_next(l);
+ }
+ return NULL;
+}
+
+void vfolder_rule_remove_source (VfolderRule *vr, const char *uri)
+{
+ char *found;
+
+ g_assert(IS_VFOLDER_RULE(vr));
+
+ found = (char *)vfolder_rule_find_source(vr, uri);
+ if (found) {
+ vr->sources = g_list_remove(vr->sources, found);
+ g_free(found);
+ }
+}
+
+const char *vfolder_rule_next_source (VfolderRule *vr, const char *last)
+{
+ GList *node;
+
+ if (last == NULL) {
+ node = vr->sources;
+ } else {
+ node = g_list_find(vr->sources, (char *)last);
+ if (node == NULL)
+ node = vr->sources;
+ else
+ node = g_list_next(node);
+ }
+ if (node)
+ return (const char *)node->data;
+ return NULL;
+}
+
+static xmlNodePtr xml_encode(FilterRule *fr)
+{
+ xmlNodePtr node, set, work;
+ GList *l;
+ VfolderRule *vr = (VfolderRule *)fr;
+
+ node = ((FilterRuleClass *)(parent_class))->xml_encode(fr);
+ g_assert(node != NULL);
+ set = xmlNewNode(NULL, "sources");
+ xmlAddChild(node, set);
+ l = vr->sources;
+ while (l) {
+ work = xmlNewNode(NULL, "folder");
+ xmlSetProp(work, "uri", l->data);
+ xmlAddChild(set, work);
+ l = g_list_next(l);
+ }
+ return node;
+}
+
+static int xml_decode(FilterRule *fr, xmlNodePtr node, struct _RuleContext *f)
+{
+ xmlNodePtr set, work;
+ int result;
+ VfolderRule *vr = (VfolderRule *)fr;
+ char *uri;
+
+ result = ((FilterRuleClass *)(parent_class))->xml_decode(fr, node, f);
+ if (result != 0)
+ return result;
+
+ set = node->childs;
+ while (set) {
+ if (!strcmp(set->name, "sources")) {
+ work = set->childs;
+ while (work) {
+ if (!strcmp(work->name, "folder")) {
+ uri = xmlGetProp(work, "uri");
+ if (uri)
+ vr->sources = g_list_append(vr->sources, uri);
+ }
+ work = work->next;
+ }
+ }
+ set = set->next;
+ }
+ return 0;
+}
+
+enum {
+ BUTTON_ADD,
+ BUTTON_REMOVE,
+ BUTTON_LAST,
+};
+
+struct _source_data {
+ RuleContext *f;
+ VfolderRule *vr;
+ const char *current;
+ GtkList *list;
+ GtkButton *buttons[BUTTON_LAST];
+};
+
+static void source_add(GtkWidget *widget, struct _source_data *data);
+static void source_remove(GtkWidget *widget, struct _source_data *data);
+
+static struct {
+ char *name;
+ GtkSignalFunc func;
+} edit_buttons[] = {
+ { "source_add", source_add },
+ { "source_remove", source_remove },
+};
+
+static void
+set_sensitive(struct _source_data *data)
+{
+ gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_ADD], TRUE);
+ gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_REMOVE], data->current != NULL);
+}
+
+static void
+select_source(GtkWidget *w, GtkWidget *child, struct _source_data *data)
+{
+ data->current = gtk_object_get_data((GtkObject *)child, "source");
+ set_sensitive(data);
+}
+
+static void source_add(GtkWidget *widget, struct _source_data *data)
+{
+ const char *allowed_types[] = { "mail", NULL };
+ char *def, *uri;
+ GtkListItem *item;
+ GList *l;
+
+ def = "";
+ evolution_shell_client_user_select_folder (global_shell_client,
+ _("Select Folder"),
+ def, allowed_types, NULL, &uri);
+
+ if (uri != NULL && uri[0] != '\0') {
+ data->vr->sources = g_list_append(data->vr->sources, uri);
+
+ l = NULL;
+ item = (GtkListItem *)gtk_list_item_new_with_label(uri);
+ gtk_object_set_data((GtkObject *)item, "source", uri);
+ gtk_widget_show((GtkWidget *)item);
+ l = g_list_append(NULL, item);
+ gtk_list_append_items(data->list, l);
+ gtk_list_select_child(data->list, (GtkWidget *)item);
+ data->current = uri;
+ } else {
+ g_free(uri);
+ }
+ set_sensitive(data);
+}
+
+static void source_remove(GtkWidget *widget, struct _source_data *data)
+{
+ const char *source;
+ int index = 0;
+ GList *l;
+ GtkListItem *item;
+
+ source = NULL;
+ while ((source = vfolder_rule_next_source(data->vr, source))) {
+ if (data->current == source) {
+ vfolder_rule_remove_source(data->vr, source);
+ item = g_list_nth_data(data->list->children, index);
+ l = g_list_append(NULL, item);
+ gtk_list_remove_items(data->list, l);
+ g_list_free(l);
+ data->current = NULL;
+ break;
+ }
+ index++;
+ }
+ set_sensitive(data);
+}
+
+static GtkWidget *get_widget(FilterRule *fr, struct _RuleContext *f)
+{
+ GtkWidget *widget, *frame, *w;
+ GladeXML *gui;
+ const char *source;
+ VfolderRule *vr = (VfolderRule *)fr;
+ struct _source_data *data;
+ int i;
+ GList *l;
+
+ widget = ((FilterRuleClass *)(parent_class))->get_widget(fr, f);
+
+ data = g_malloc0(sizeof(*data));
+ data->f = f;
+ data->vr = vr;
+
+ gui = glade_xml_new(FILTER_GLADEDIR "/filter.glade", "vfolder_source_frame");
+ frame = glade_xml_get_widget (gui, "vfolder_source_frame");
+
+ gtk_object_set_data_full((GtkObject *)frame, "data", data, g_free);
+
+ for (i=0;i<BUTTON_LAST;i++) {
+ data->buttons[i] = (GtkButton *)w = glade_xml_get_widget (gui, edit_buttons[i].name);
+ gtk_signal_connect((GtkObject *)w, "clicked", edit_buttons[i].func, data);
+ }
+
+ w = glade_xml_get_widget (gui, "source_list");
+ data->list = (GtkList *)w;
+ l = NULL;
+ source = NULL;
+ while ((source = vfolder_rule_next_source(vr, source))) {
+ GtkListItem *item = (GtkListItem *)gtk_list_item_new_with_label(source);
+ gtk_object_set_data((GtkObject *)item, "source", (void *)source);
+ gtk_widget_show((GtkWidget *)item);
+ l = g_list_append(l, item);
+ }
+ gtk_list_append_items(data->list, l);
+ gtk_signal_connect((GtkObject *)w, "select_child", select_source, data);
+ set_sensitive(data);
+
+ gtk_box_pack_start(GTK_BOX(widget), frame, TRUE, TRUE, 3);
+ return widget;
+}
diff --git a/filter/vfolder-rule.h b/filter/vfolder-rule.h
new file mode 100644
index 0000000000..c3fa130c84
--- /dev/null
+++ b/filter/vfolder-rule.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2000 Helix Code Inc.
+ *
+ * Authors: Not Zed <notzed@lostzed.mmc.com.au>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _VFOLDER_RULE_H
+#define _VFOLDER_RULE_H
+
+#include <gtk/gtk.h>
+#include "filter-rule.h"
+
+#define VFOLDER_RULE(obj) GTK_CHECK_CAST (obj, vfolder_rule_get_type (), VfolderRule)
+#define VFOLDER_RULE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, vfolder_rule_get_type (), VfolderRuleClass)
+#define IS_VFOLDER_RULE(obj) GTK_CHECK_TYPE (obj, vfolder_rule_get_type ())
+
+typedef struct _VfolderRule VfolderRule;
+typedef struct _VfolderRuleClass VfolderRuleClass;
+
+struct _VfolderRule {
+ FilterRule parent;
+ struct _VfolderRulePrivate *priv;
+
+ GList *sources; /* uri's of the source folders */
+};
+
+struct _VfolderRuleClass {
+ FilterRuleClass parent_class;
+
+ /* virtual methods */
+
+ /* signals */
+};
+
+guint vfolder_rule_get_type (void);
+VfolderRule *vfolder_rule_new (void);
+
+/* methods */
+void vfolder_rule_add_source (VfolderRule *vr, const char *uri);
+void vfolder_rule_remove_source (VfolderRule *vr, const char *uri);
+const char *vfolder_rule_find_source (VfolderRule *vr, const char *uri);
+const char *vfolder_rule_next_source (VfolderRule *vr, const char *last);
+
+#endif /* ! _VFOLDER_RULE_H */
+