diff options
author | Not Zed <NotZed@HelixCode.com> | 2000-07-30 11:23:41 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2000-07-30 11:23:41 +0800 |
commit | a44d1c188b0bc166e5966ae3854a1c0bc8c44afd (patch) | |
tree | df30c85510f2b55384f95f184ae4768eedc0bac7 /filter | |
parent | 4f1ecbb64b04048e1765f25e65799830316021d1 (diff) | |
download | gsoc2013-evolution-a44d1c188b0bc166e5966ae3854a1c0bc8c44afd.tar.gz gsoc2013-evolution-a44d1c188b0bc166e5966ae3854a1c0bc8c44afd.tar.zst gsoc2013-evolution-a44d1c188b0bc166e5966ae3854a1c0bc8c44afd.zip |
** Almost a total rewrite of every file, except for filter-driver which
2000-07-30 Not Zed <NotZed@HelixCode.com>
** Almost a total rewrite of every file, except for filter-driver
which just had minor updates.
The rule format has changed.
svn path=/trunk/; revision=4418
Diffstat (limited to 'filter')
53 files changed, 6294 insertions, 3905 deletions
diff --git a/filter/ChangeLog b/filter/ChangeLog index 093a092723..c2008adab9 100644 --- a/filter/ChangeLog +++ b/filter/ChangeLog @@ -1,3 +1,10 @@ +2000-07-30 Not Zed <NotZed@HelixCode.com> + + ** Almost a total rewrite of every file, except for filter-driver + which just had minor updates. + + The rule format has changed. + 2000-07-24 Dan Winship <danw@helixcode.com> * filter-driver.c (do_delete, filter_driver_run): Update for diff --git a/filter/Makefile.am b/filter/Makefile.am index 2362e42c82..f6b31dcfc8 100644 --- a/filter/Makefile.am +++ b/filter/Makefile.am @@ -1,3 +1,7 @@ + +gladedir = $(prefix)/share/evolution/glade +glade_DATA = filter.glade + INCLUDES = \ -I $(top_srcdir) \ -I $(top_srcdir)/libibex \ @@ -8,6 +12,7 @@ INCLUDES = \ -I $(top_builddir)/shell \ -I $(GNOME_INCLUDEDIR) \ $(GTKHTML_CFLAGS) \ + -DFILTER_GLADEDIR=\"$(gladedir)\" \ -DG_LOG_DOMAIN=\"filter\" ## @@ -15,20 +20,42 @@ noinst_LTLIBRARIES = \ libfilter.la libfilter_la_SOURCES = \ - filter-arg-types.c \ - filter-arg-types.h \ - filter-arg.c \ - filter-arg.h \ - filter-xml.c \ - filter-xml.h \ - filter-format.c \ - filter-format.h \ - filter-druid.c \ - filter-druid.h \ + filter-code.c \ + filter-code.h \ + filter-colour.c \ + filter-colour.h \ + filter-context.c \ + filter-context.h \ + filter-driver.c \ + filter-driver.h \ filter-editor.c \ filter-editor.h \ - filter-driver.c \ - filter-driver.h + filter-element.c \ + filter-element.h \ + filter-filter.c \ + filter-filter.h \ + filter-folder.c \ + filter-folder.h \ + filter-input.c \ + filter-input.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 \ + score-context.c \ + score-context.h \ + score-editor.c \ + score-editor.h \ + score-rule.c \ + score-rule.h \ + vfolder-context.c \ + vfolder-context.h \ + vfolder-editor.c \ + vfolder-editor.h EXTRA_DIST = blank.xpm check.xpm \ filtertypes.xml vfoldertypes.xml diff --git a/filter/blank.xpm b/filter/blank.xpm deleted file mode 100755 index 499f7a04fc..0000000000 --- a/filter/blank.xpm +++ /dev/null @@ -1,22 +0,0 @@ -/* XPM */ -static char * blank_xpm[] = { -"16 16 3 1", -" c None", -". c #000000", -"+ c #FFFFFF", -" ", -" .............. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .............. ", -" "}; diff --git a/filter/check.xpm b/filter/check.xpm deleted file mode 100755 index 74f9b56122..0000000000 --- a/filter/check.xpm +++ /dev/null @@ -1,22 +0,0 @@ -/* XPM */ -static char * check_xpm[] = { -"16 16 3 1", -" c None", -". c #000000", -"+ c #FFFFFF", -" ", -" .............. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .+++++++++.++. ", -" .++++++++..++. ", -" .+++++++...++. ", -" .++.+++...+++. ", -" .++..+...++++. ", -" .++.....+++++. ", -" .+++...++++++. ", -" .++++.+++++++. ", -" .++++++++++++. ", -" .++++++++++++. ", -" .............. ", -" "}; diff --git a/filter/filter-arg-types.c b/filter/filter-arg-types.c deleted file mode 100644 index 5d09b4817b..0000000000 --- a/filter/filter-arg-types.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * Copyright (C) 2000 Helix Code Inc. - * - * Authors: Michael Zucchi <notzed@helixcode.com> - * - * Implementations of the filter-arg types. - * - * 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 <gnome.h> - -#include "evolution-shell-client.h" - -#include "filter-arg-types.h" - -/* ********************************************************************** */ -/* String */ -/* ********************************************************************** */ - -/* Use for a superclass of any items which are simple strings */ - -static void filter_arg_string_class_init (FilterArgStringClass *class); -static void filter_arg_string_init (FilterArgString *gspaper); - -static FilterArg *string_parent_class; - -guint -filter_arg_string_get_type (void) -{ - static guint type = 0; - - if (!type) { - GtkTypeInfo type_info = { - "FilterArgString", - sizeof (FilterArgString), - sizeof (FilterArgStringClass), - (GtkClassInitFunc) filter_arg_string_class_init, - (GtkObjectInitFunc) filter_arg_string_init, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) NULL - }; - - type = gtk_type_unique (filter_arg_get_type (), &type_info); - } - - return type; -} - -static void -arg_string_write_html(FilterArg *argin, GtkHTML *html, GtkHTMLStream *stream) -{ - /* empty */ -} - -static void -arg_string_write_text(FilterArg *argin, GString *string) -{ - GList *l; - char *a; - - l = argin->values; - if (l == NULL) { - g_string_append(string, "text"); - } - while (l) { - a = l->data; - g_string_append(string, a); - if (l->next) { - g_string_append(string, ", "); - } - l = g_list_next(l); - } -} - -static void -arg_string_edit_values(FilterArg *arg) -{ - printf("edit string values!\n"); -} - -/* pop up a dialogue, asking for a new string value */ -static int -arg_string_edit_value (FilterArg *arg, int index) -{ - GnomeDialog *dialogue; - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *entry; - char *text = NULL; - char *newtext; - - dialogue = (GnomeDialog *)gnome_dialog_new ("Edit value", "Ok", "Cancel", 0); - - hbox = gtk_hbox_new (FALSE, 0); - label = gtk_label_new ("Text"); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - entry = gtk_entry_new(); - gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); - if (index >= 0) { - text = filter_arg_get_value (arg, index); - } - if (text) { - gtk_entry_set_text (GTK_ENTRY (entry), text); - } - gtk_box_pack_start (GTK_BOX (dialogue->vbox), hbox, TRUE, TRUE, 0); - gtk_widget_show_all (hbox); - gtk_object_ref (GTK_OBJECT (entry)); /* so we can get the text back afterwards */ - if (gnome_dialog_run_and_close (dialogue) == 0) { - GList *node; - - newtext = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); - gtk_object_unref (GTK_OBJECT (entry)); - if (index >= 0 && (node = g_list_find (arg->values, text))) { - node->data = newtext; - } else { - arg->values = g_list_append (arg->values, newtext); - } - g_free (text); - return g_list_index (arg->values, newtext); - } - return -1; -} - -static xmlNodePtr -arg_string_values_get_xml(FilterArg *argin) -{ - xmlNodePtr value; - GList *l; - char *a; - - value = xmlNewNode(NULL, "optionvalue"); - xmlSetProp(value, "name", argin->name); - - l = argin->values; - while (l) { - xmlNodePtr cur; - - a = l->data; - - cur = xmlNewChild(value, NULL, "folder", NULL); - if (a) - xmlSetProp(cur, "folder", a); - l = g_list_next(l); - } - - return value; -} - -static void -arg_string_values_add_xml(FilterArg *arg, xmlNodePtr node) -{ - xmlNodePtr n; - - n = node->childs; - while (n) { - if (!strcmp(n->name, "folder")) { - filter_arg_string_add(arg, xmlGetProp(n, "folder")); - } else { - g_warning("Loading folders from xml, wrong node encountered: %s\n", n->name); - } - n = n->next; - } -} - -static char * -arg_string_get_value_as_string(FilterArg *argin, void *data) -{ - char *a = (char *)data; - - return a; -} - -static void -arg_string_free_value(FilterArg *arg, void *a) -{ - g_free(a); -} - -static void -filter_arg_string_class_init (FilterArgStringClass *class) -{ - GtkObjectClass *object_class; - - object_class = (GtkObjectClass *) class; - if (string_parent_class == NULL) - string_parent_class = gtk_type_class (gtk_object_get_type ()); - - class->parent_class.write_html = arg_string_write_html; - class->parent_class.write_text = arg_string_write_text; - class->parent_class.edit_values = arg_string_edit_values; - class->parent_class.edit_value = arg_string_edit_value; - class->parent_class.free_value = arg_string_free_value; - class->parent_class.get_value_as_string = arg_string_get_value_as_string; - - class->parent_class.values_get_xml = arg_string_values_get_xml; - class->parent_class.values_add_xml = arg_string_values_add_xml; -} - -static void -filter_arg_string_init (FilterArgString *arg) -{ - arg->arg.values = NULL; -} - -/** - * filter_arg_string_new: - * - * Create a new FilterArgString widget. - * - * Return value: A new FilterArgString widget. - **/ -FilterArg * -filter_arg_string_new (char *name) -{ - FilterArg *a = FILTER_ARG ( gtk_type_new (filter_arg_string_get_type ())); - a->name = g_strdup(name); - return a; -} - - -void -filter_arg_string_add(FilterArg *arg, char *name) -{ - filter_arg_add(arg, g_strdup(name)); -} - -void -filter_arg_string_remove(FilterArg *arg, char *name) -{ - /* do it */ -} - - -/* ********************************************************************** */ -/* Address */ -/* ********************************************************************** */ - -static void filter_arg_address_class_init (FilterArgAddressClass *class); -static void filter_arg_address_init (FilterArgAddress *gspaper); - -static FilterArg *parent_class; - -guint -filter_arg_address_get_type (void) -{ - static guint type = 0; - - if (!type) { - GtkTypeInfo type_info = { - "FilterArgAddress", - sizeof (FilterArgAddress), - sizeof (FilterArgAddressClass), - (GtkClassInitFunc) filter_arg_address_class_init, - (GtkObjectInitFunc) filter_arg_address_init, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) NULL - }; - - type = gtk_type_unique (filter_arg_get_type (), &type_info); - } - - return type; -} - -static void -arg_address_write_html (FilterArg *argin, GtkHTML *html, GtkHTMLStream *stream) -{ - /* empty */ -} - -static void -arg_address_write_text (FilterArg *argin, GString *string) -{ - GList *l; - struct filter_arg_address *a; - - l = argin->values; - if (l == NULL) { - g_string_append (string, "email address"); - } - while (l) { - a = l->data; - g_string_append (string, a->name); - if (l->next) { - g_string_append (string, ", "); - } - l = g_list_next (l); - } -} - -static void -arg_address_edit_values(FilterArg *arg) -{ - printf ("edit it!\n"); -} - -static int -arg_address_edit_value (FilterArg *arg, int index) -{ - GnomeDialog *dialogue; - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *entry; - char *text = NULL; - char *newtext; - struct filter_arg_address *ad = NULL; - - dialogue = (GnomeDialog *)gnome_dialog_new ("Edit Address value", "Ok", "Cancel", 0); - - hbox = gtk_hbox_new (FALSE, 0); - label = gtk_label_new ("Address"); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - entry = gtk_entry_new (); - gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); - if (index >= 0 && (ad = filter_arg_get_value (arg, index))) { - text = ad->email; - } - if (text) { - gtk_entry_set_text (GTK_ENTRY (entry), text); - } - gtk_box_pack_start (GTK_BOX (dialogue->vbox), hbox, TRUE, TRUE, 0); - gtk_widget_show_all (hbox); - gtk_object_ref (GTK_OBJECT (entry)); /* so we can get the text back afterwards */ - if (gnome_dialog_run_and_close (dialogue) == 0) { - GList *node; - - newtext = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); - gtk_object_unref (GTK_OBJECT (entry)); - if (index >= 0 && ad && (node = g_list_find(arg->values, ad))) { - ad = node->data; - g_free (ad->email); - ad->email = newtext; - } else { - ad = g_malloc0 (sizeof(*ad)); - ad->email = newtext; - arg->values = g_list_append (arg->values, ad); - } - g_free (text); - return g_list_index (arg->values, ad); - } - return -1; -} - -static xmlNodePtr -arg_address_values_get_xml(FilterArg *argin) -{ - xmlNodePtr value; - GList *l; - struct filter_arg_address *a; - - /* hmm, perhaps this overhead should be in FilterArg, and this function just returns the base node?? */ - value = xmlNewNode(NULL, "optionvalue"); - xmlSetProp(value, "name", argin->name); - - l = argin->values; - while (l) { - xmlNodePtr cur; - - a = l->data; - - cur = xmlNewChild(value, NULL, "address", NULL); - if (a->name) - xmlSetProp(cur, "name", a->name); - if (a->email) - xmlSetProp(cur, "email", a->email); - l = g_list_next(l); - } - - return value; -} - -static void -arg_address_values_add_xml(FilterArg *arg, xmlNodePtr node) -{ - xmlNodePtr n; - - n = node->childs; - while (n) { - if (!strcmp(n->name, "address")) { - char *nm, *e; - nm = xmlGetProp(n, "name"); - e = xmlGetProp(n, "email"); - filter_arg_address_add(arg, nm, e); - free(nm); - free(e); - } else { - g_warning("Loading address from xml, wrong node encountered: %s\n", n->name); - } - n = n->next; - } -} - -/* the search string is just the raw email address */ -static char * -arg_address_get_value_as_string(FilterArg *argin, void *data) -{ - struct filter_arg_address *a = (struct filter_arg_address *)data; - - if (a->email == NULL - || a->email[0] == '\0') { - if (a->name == NULL - || a->name[0] == '\0') - return ""; - return a->name; - } else - return a->email; -} - -static void -arg_address_free_value(FilterArg *arg, void *v) -{ - struct filter_arg_address *a = v; - - g_free(a->name); - g_free(a->email); - g_free(a); -} - -static void -filter_arg_address_class_init (FilterArgAddressClass *class) -{ - GtkObjectClass *object_class; - - object_class = (GtkObjectClass *) class; - if (parent_class == NULL) - parent_class = gtk_type_class (gtk_object_get_type ()); - - class->parent_class.write_html = arg_address_write_html; - class->parent_class.write_text = arg_address_write_text; - class->parent_class.edit_values= arg_address_edit_values; - class->parent_class.edit_value= arg_address_edit_value; - class->parent_class.free_value = arg_address_free_value; - - class->parent_class.values_get_xml = arg_address_values_get_xml; - class->parent_class.values_add_xml = arg_address_values_add_xml; - - class->parent_class.get_value_as_string = arg_address_get_value_as_string; -} - -static void -filter_arg_address_init (FilterArgAddress *arg) -{ -} - -/** - * filter_arg_address_new: - * - * Create a new FilterArgAddress widget. - * - * Return value: A new FilterArgAddress widget. - **/ -FilterArg * -filter_arg_address_new (char *name) -{ - FilterArg *a = FILTER_ARG ( gtk_type_new (filter_arg_address_get_type ())); - a->name = g_strdup(name); - return a; -} - -void -filter_arg_address_add(FilterArg *arg, char *name, char *email) -{ - struct filter_arg_address *a; - - a = g_malloc0(sizeof(*a)); - - a->name = g_strdup(name); - a->email = g_strdup(email); - - filter_arg_add(arg, a); -} - -void -filter_arg_address_remove(FilterArg *arg, char *name, char *email) -{ - -} - -/* ********************************************************************** */ -/* Folder */ -/* ********************************************************************** */ - - -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-control.h> - -#include "Evolution.h" - -static void filter_arg_folder_class_init (FilterArgFolderClass *class); -static void filter_arg_folder_init (FilterArgFolder *gspaper); - -static FilterArg *folder_parent_class; -extern EvolutionShellClient *global_shell_client; - -guint -filter_arg_folder_get_type (void) -{ - static guint type = 0; - - if (!type) { - GtkTypeInfo type_info = { - "FilterArgFolder", - sizeof (FilterArgFolder), - sizeof (FilterArgFolderClass), - (GtkClassInitFunc) filter_arg_folder_class_init, - (GtkObjectInitFunc) filter_arg_folder_init, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) NULL - }; - - type = gtk_type_unique (filter_arg_string_get_type (), &type_info); - } - - return type; -} - -static void -arg_folder_write_html(FilterArg *argin, GtkHTML *html, GtkHTMLStream *stream) -{ - /* empty */ -} - -static void -arg_folder_write_text(FilterArg *argin, GString *string) -{ - GList *l; - char *a; - - l = argin->values; - if (l == NULL) { - g_string_append(string, "folder"); - } - while (l) { - a = l->data; - g_string_append(string, a); - if (l->next) { - g_string_append(string, ", "); - } - l = g_list_next(l); - } -} - -static int -arg_folder_edit_value (FilterArg *arg, int index) -{ - const char *allowed_types[] = { "mail", NULL }; - char *def; - char *physical_uri; - - printf ("folder edit value %d\n", index); - - if (index < 0) { - def = ""; - } else { - def = filter_arg_get_value (arg, index); - } - - evolution_shell_client_user_select_folder (global_shell_client, - _("Select Folder"), - def, allowed_types, NULL, &physical_uri); - - if (physical_uri != NULL && physical_uri[0] != '\0') { - GList *node; - - if (index >= 0 && (node = g_list_nth (arg->values, index))) - node->data = physical_uri; - else - arg->values = g_list_append (arg->values, physical_uri); - - gtk_signal_emit_by_name (GTK_OBJECT (arg), "changed"); - } else { - g_free (physical_uri); - } - -#warning "What do we really want to return here???" - return 0; -} - -static void -arg_folder_edit_values(FilterArg *argin) -{ - /*FilterArgFolder *arg = (FilterArgFolder *)argin;*/ - GList *l; - char *a, *start, *ptr, *ptrend, *ptrgap; - char outbuf[128], *outptr; /* FIXME: dont use a bounded buffer! */ - GtkWidget *dialogue; - GtkWidget *text; - guint i; - - dialogue = gnome_dialog_new ("Edit addresses", "Ok", "Cancel", NULL); - text = gtk_text_new (NULL, NULL); - gtk_object_ref (GTK_OBJECT (text)); - - l = argin->values; - while (l) { - a = l->data; - gtk_text_insert(GTK_TEXT (text), NULL, NULL, NULL, a, strlen(a)); - gtk_text_insert(GTK_TEXT (text), NULL, NULL, NULL, "\n", 1); - l = g_list_next(l); - } - - gtk_box_pack_start(GTK_BOX (GNOME_DIALOG(dialogue)->vbox), text, TRUE, TRUE, 2); - gtk_widget_show(text); - gtk_text_set_editable(GTK_TEXT (text), TRUE); - - gnome_dialog_run_and_close(GNOME_DIALOG (dialogue)); - - for (i = 0; i < g_list_length (argin->values); i++) - g_free (g_list_nth_data (argin->values, i)); - g_list_free (argin->values); - - argin->values = NULL; - ptr = GTK_TEXT(text)->text.ch; - ptrend = ptr + GTK_TEXT(text)->text_end; - ptrgap = ptr + GTK_TEXT(text)->gap_position; - - start = ptr; - outptr = outbuf; - while (ptr < ptrend) { - printf("%c", *ptr); - if (*ptr == '\n') { - int len = outptr - outbuf; - char *new; - - printf("(len = %d)", len); - - if (len>0) { - new = g_malloc(len+1); - new[len]=0; - memcpy(new, outbuf, len); - printf("(appending '%s')", new); - argin->values = g_list_append(argin->values, new); - } - outptr = outbuf; - } else { - *outptr++ = *ptr; - } - ptr++; - if (ptr==ptrgap) { - ptr += GTK_TEXT(text)->gap_size; - } - } - if (outptr > outbuf) { - int len = outptr-outbuf; - char *new; - - printf("(lastlen = %d)", len); - - new = g_malloc(len+1); - new[len] = 0; - memcpy(new, start, len); - argin->values = g_list_append(argin->values, new); - } - printf("\n"); -} - -static xmlNodePtr -arg_folder_values_get_xml(FilterArg *argin) -{ - xmlNodePtr value; - /*FilterArgFolder *arg = (FilterArgFolder *)argin;*/ - GList *l; - char *a; - - value = xmlNewNode(NULL, "optionvalue"); - xmlSetProp(value, "name", argin->name); - - l = argin->values; - while (l) { - xmlNodePtr cur; - - a = l->data; - - cur = xmlNewChild(value, NULL, "folder", NULL); - if (a) - xmlSetProp(cur, "name", a); - l = g_list_next(l); - } - - return value; -} - -static void -arg_folder_values_add_xml(FilterArg *arg, xmlNodePtr node) -{ - xmlNodePtr n; - - n = node->childs; - while (n) { - if (!strcmp(n->name, "folder")) { - char *name = xmlGetProp(n, "name"); - if (name) { - filter_arg_folder_add(arg, name); - free(name); - } else - g_warning("no xml prop 'name' on '%s'\n", n->name); - } else { - g_warning("Loading folders from xml, wrong node encountered: %s\n", n->name); - } - n = n->next; - } -} - -static char * -arg_folder_get_value_as_string(FilterArg *argin, void *data) -{ - /*FilterArgFolder *arg = (FilterArgFolder *)argin;*/ - char *a = (char *)data; - - return a; -} - -static void -arg_folder_free_value(FilterArg *arg, void *a) -{ - g_free(a); -} - -static void -filter_arg_folder_class_init (FilterArgFolderClass *class) -{ - GtkObjectClass *object_class; - FilterArgClass *filter_class; - - object_class = (GtkObjectClass *) class; - filter_class = (FilterArgClass *) class; - if (folder_parent_class == NULL) - folder_parent_class = gtk_type_class (filter_arg_string_get_type ()); - - /* FIXME: only need to over-ride the edit values right? */ - filter_class->edit_value = arg_folder_edit_value; - - filter_class->write_html = arg_folder_write_html; - filter_class->write_text = arg_folder_write_text; - filter_class->edit_values = arg_folder_edit_values; - filter_class->free_value = arg_folder_free_value; - - filter_class->values_get_xml = arg_folder_values_get_xml; - filter_class->values_add_xml = arg_folder_values_add_xml; - - filter_class->get_value_as_string = arg_folder_get_value_as_string; -} - -static void -filter_arg_folder_init (FilterArgFolder *arg) -{ -} - -/** - * filter_arg_folder_new: - * - * Create a new FilterArgFolder widget. - * - * Return value: A new FilterArgFolder widget. - **/ -FilterArg * -filter_arg_folder_new (char *name) -{ - FilterArg *a = FILTER_ARG ( gtk_type_new (filter_arg_folder_get_type ())); - a->name = g_strdup(name); - return a; -} - - -void -filter_arg_folder_add(FilterArg *arg, char *name) -{ - filter_arg_add(arg, g_strdup(name)); -} - -void -filter_arg_folder_remove(FilterArg *arg, char *name) -{ - /* do it */ -} diff --git a/filter/filter-arg-types.h b/filter/filter-arg-types.h deleted file mode 100644 index 6a1d80bfae..0000000000 --- a/filter/filter-arg-types.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2000 Helix Code Inc. - * - * Authors: Michael Zucchi <notzed@helixcode.com> - * - * Implementations of the filter-args. - * - * 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 _FILTER_ARG_TYPES_H -#define _FILTER_ARG_TYPES_H - -#include "filter-arg.h" - -/* An Address */ -#define FILTER_ARG_ADDRESS(obj) GTK_CHECK_CAST (obj, filter_arg_address_get_type (), FilterArgAddress) -#define FILTER_ARG_ADDRESS_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_arg_address_get_type (), FilterArgAddressClass) -#define IS_FILTER_ARG_ADDRESS(obj) GTK_CHECK_TYPE (obj, filter_arg_address_get_type ()) - -typedef struct _FilterArgAddress FilterArgAddress; -typedef struct _FilterArgAddressClass FilterArgAddressClass; - -struct _FilterArgAddress { - FilterArg arg; -}; - -struct _FilterArgAddressClass { - FilterArgClass parent_class; -}; - -struct filter_arg_address { - char *name; - char *email; -}; - -guint filter_arg_address_get_type (void); -FilterArg *filter_arg_address_new (char *name); -void filter_arg_address_add(FilterArg *, char *name, char *email); -void filter_arg_address_remove(FilterArg *, char *name, char *email); - -/* A simple String */ -#define FILTER_ARG_STRING(obj) GTK_CHECK_CAST (obj, filter_arg_string_get_type (), FilterArgString) -#define FILTER_ARG_STRING_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_arg_string_get_type (), FilterArgStringClass) -#define IS_FILTER_ARG_STRING(obj) GTK_CHECK_TYPE (obj, filter_arg_string_get_type ()) - -typedef struct _FilterArgString FilterArgString; -typedef struct _FilterArgStringClass FilterArgStringClass; - -struct _FilterArgString { - FilterArg arg; - - /* Name/property to save/load to xml */ - /* char *xmlname; */ - /* char *xmlprop; */ -}; - -struct _FilterArgStringClass { - FilterArgClass parent_class; -}; - -guint filter_arg_string_get_type (void); -FilterArg *filter_arg_string_new (char *name); -void filter_arg_string_add(FilterArg *, char *name); -void filter_arg_string_remove(FilterArg *, char *name); - -/* A Folder, subclass of a string */ -#define FILTER_ARG_FOLDER(obj) GTK_CHECK_CAST (obj, filter_arg_folder_get_type (), FilterArgFolder) -#define FILTER_ARG_FOLDER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_arg_folder_get_type (), FilterArgFolderClass) -#define IS_FILTER_ARG_FOLDER(obj) GTK_CHECK_TYPE (obj, filter_arg_folder_get_type ()) - -typedef struct _FilterArgFolder FilterArgFolder; -typedef struct _FilterArgFolderClass FilterArgFolderClass; - -struct _FilterArgFolder { - FilterArgString arg; -}; - -struct _FilterArgFolderClass { - FilterArgStringClass parent_class; -}; - -guint filter_arg_folder_get_type (void); -FilterArg *filter_arg_folder_new (char *name); -void filter_arg_folder_add(FilterArg *, char *name); -void filter_arg_folder_remove(FilterArg *, char *name); - -#endif /* ! _FILTER_ARG_TYPES_H */ - diff --git a/filter/filter-arg.c b/filter/filter-arg.c deleted file mode 100644 index 622986ce43..0000000000 --- a/filter/filter-arg.c +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Copyright (C) 2000 Helix Code Inc. - * - * Authors: Michael Zucchi <notzed@helixcode.com> - * - * Abstract filter argument class. - * - * 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 "filter-arg.h" - - -static void filter_arg_class_init (FilterArgClass *class); -static void filter_arg_init (FilterArg *gspaper); - -#define _PRIVATE(x) (((FilterArg *)(x))->priv) - -struct _FilterArgPrivate { - GtkWidget *dialogue; /* editor widget */ - xmlNodePtr oldargs; -}; - -static GtkObjectClass *parent_class; - -enum { - CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -guint -filter_arg_get_type (void) -{ - static guint type = 0; - - if (!type) { - GtkTypeInfo type_info = { - "FilterArg", - sizeof (FilterArg), - sizeof (FilterArgClass), - (GtkClassInitFunc) filter_arg_class_init, - (GtkObjectInitFunc) filter_arg_init, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) NULL - }; - - type = gtk_type_unique (gtk_object_get_type (), &type_info); - } - - return type; -} - -static FilterArg * -clone_default(FilterArg *a) -{ - xmlNodePtr values; - FilterArg *new = FILTER_ARG ( gtk_type_new (((GtkObject *)a)->klass->type) ); - - /* clone values */ - new->name = g_strdup(a->name); - values = filter_arg_values_get_xml(a); - filter_arg_values_add_xml(new, values); - xmlFreeNodeList(values); - - return new; -} - -static void -write_html_nothing(FilterArg *arg, GtkHTML *html, GtkHTMLStream *stream) -{ - /* empty */ -} - -static void -write_text_nothing(FilterArg *arg, GString *string) -{ - /* empty */ -} - -static void -edit_values_nothing(FilterArg *arg) -{ - /* empty */ -} - -static int -edit_value_nothing(FilterArg *arg, int index) -{ - return index; -} - -static void -free_value_nothing(FilterArg *arg, void *v) -{ - /* empty */ -} - -static void -filter_arg_class_init (FilterArgClass *class) -{ - GtkObjectClass *object_class; - - object_class = (GtkObjectClass *) class; - parent_class = gtk_type_class (gtk_object_get_type ()); - - class->write_html = write_html_nothing; - class->write_text = write_text_nothing; - class->edit_values = edit_values_nothing; - class->edit_value = edit_value_nothing; - class->free_value = free_value_nothing; - class->clone = clone_default; - - signals[CHANGED] = - gtk_signal_new ("changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (FilterArgClass, changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); -} - -static void -filter_arg_init (FilterArg *arg) -{ - arg->values = NULL; - arg->priv = g_malloc0(sizeof(*arg->priv)); -} - -/** - * filter_arg_new: - * - * Create a new FilterArg widget. - * - * Return value: A new FilterArg widget. - **/ -FilterArg * -filter_arg_new (char *name) -{ - FilterArg *a = FILTER_ARG ( gtk_type_new (filter_arg_get_type ())); - if (name) - a->name = g_strdup(name); - return a; -} - -FilterArg * -filter_arg_clone (FilterArg *arg) -{ - return ((FilterArgClass *)(arg->object.klass))->clone(arg); -} - -void -filter_arg_copy(FilterArg *dst, FilterArg *src) -{ - xmlNodePtr values; - - g_return_if_fail( ((GtkObject *)src)->klass->type == ((GtkObject *)dst)->klass->type ); - - /* remove old values */ - while (dst->values) { - filter_arg_remove(dst, dst->values->data); - } - - /* clone values */ - values = filter_arg_values_get_xml(src); - filter_arg_values_add_xml(dst, values); - xmlFreeNodeList(values); -} - -void -filter_arg_add(FilterArg *arg, void *v) -{ - g_return_if_fail(v != NULL); - - arg->values = g_list_append(arg->values, v); - gtk_signal_emit(GTK_OBJECT(arg), signals[CHANGED]); -} - -void -filter_arg_remove(FilterArg *arg, void *v) -{ - arg->values = g_list_remove(arg->values, v); - ((FilterArgClass *)(arg->object.klass))->free_value(arg, v); - gtk_signal_emit(GTK_OBJECT(arg), signals[CHANGED]); -} - - -void -filter_arg_write_html(FilterArg *arg, GtkHTML *html, GtkHTMLStream *stream) -{ - ((FilterArgClass *)(arg->object.klass))->write_html(arg, html, stream); -} - -void -filter_arg_write_text(FilterArg *arg, GString *string) -{ - int count, i; - - count = filter_arg_get_count(arg); - for (i=0;i<count;i++) { - g_string_append(string, filter_arg_get_value_as_string(arg, i)); - if (i<count-1) { - g_string_append(string, ", "); - } - if (i==count-2 && count>1) { - g_string_append(string, "or "); - } - } - -#if 0 - ((FilterArgClass *)(arg->object.klass))->write_text(arg, string); -#endif -} -void -filter_arg_edit_values(FilterArg *arg) -{ - void filter_arg_edit_values_1(FilterArg *arg); - - g_return_if_fail(arg != NULL); - - -#if 1 - filter_arg_edit_values_1(arg); -#else - - if (((FilterArgClass *)(arg->object.klass))->edit_values) - ((FilterArgClass *)(arg->object.klass))->edit_values(arg); - else - g_warning("No implementation of virtual method edit_values"); -#endif -} - -int -filter_arg_edit_value(FilterArg *arg, int index) -{ - return ((FilterArgClass *)(arg->object.klass))->edit_value(arg, index); -} - -xmlNodePtr -filter_arg_values_get_xml(FilterArg *arg) -{ - return ((FilterArgClass *)(arg->object.klass))->values_get_xml(arg); -} -void -filter_arg_values_add_xml(FilterArg *arg, xmlNodePtr node) -{ - ((FilterArgClass *)(arg->object.klass))->values_add_xml(arg, node); -} - -/* returns the number of args in the arg list */ -int -filter_arg_get_count(FilterArg *arg) -{ - int count=0; - GList *l; - - for (l = arg->values;l;l=g_list_next(l)) - count++; - return count; -} - -void * -filter_arg_get_value(FilterArg *arg, int index) -{ - int count = 0; - GList *l; - - for (l = arg->values; l && count < index; l = g_list_next(l)) - count++; - if (l) - return l->data; - return NULL; -} - -char * -filter_arg_get_value_as_string(FilterArg *arg, int index) -{ - void *data; - - data = filter_arg_get_value(arg, index); - if (data) { - return ((FilterArgClass *)(arg->object.klass))->get_value_as_string(arg, data); - } else { - return ""; - } -} - - -struct filter_arg_edit { - FilterArg *arg; - GtkList *list; - GList *items; - GnomeDialog *dialogue; - GtkWidget *add, *remove, *edit; - GtkWidget *item_current; -}; - -static void -filter_arg_edit_add(GtkWidget *w, struct filter_arg_edit *edata) -{ - GtkWidget *listitem; - int i; - - i = filter_arg_edit_value(edata->arg, -1); - if (i>=0) { - gtk_list_remove_items_no_unref(edata->list, edata->items); - listitem = gtk_list_item_new_with_label(filter_arg_get_value_as_string(edata->arg, i)); - gtk_object_set_data(GTK_OBJECT (listitem), "arg_i", filter_arg_get_value(edata->arg, i)); - edata->items = g_list_append(edata->items, listitem); - gtk_widget_show(listitem); - - /* this api is nonsense */ - gtk_list_append_items(edata->list, g_list_copy(edata->items)); - } -} - -void dump_list(GList *list) -{ - printf("dumping list:\n"); - for (;list;list = g_list_next(list)) { - printf(" %p %p\n", list, list->data); - } -} - -static void -fill_list(struct filter_arg_edit *edata) -{ - GList *items = NULL; - int i, count; - GtkListItem *listitem; - - gtk_list_remove_items(edata->list, edata->items); - g_list_free(edata->items); - - count = filter_arg_get_count(edata->arg); - for (i=0;i<count;i++) { - char *labeltext; - labeltext = filter_arg_get_value_as_string(edata->arg, i); - listitem = (GtkListItem *)gtk_list_item_new_with_label(labeltext); - gtk_object_set_data((GtkObject *)listitem, "arg_i", filter_arg_get_value(edata->arg, i)); - items = g_list_append(items, listitem); - gtk_widget_show(GTK_WIDGET(listitem)); - } - - edata->item_current = NULL; - edata->items = items; - - gtk_list_append_items(edata->list, g_list_copy(edata->items)); -} - -static void -filter_arg_edit_edit(GtkWidget *w, struct filter_arg_edit *edata) -{ - char *name; - int i; - - /* yurck */ - if (edata->item_current - && (name = gtk_object_get_data(GTK_OBJECT (edata->item_current), "arg_i")) - && (i = g_list_index(edata->arg->values, name)) >= 0 - && (i = filter_arg_edit_value(edata->arg, i)) >= 0) { - - fill_list(edata); - } -} - -static void -filter_arg_edit_delete(GtkWidget *w, struct filter_arg_edit *edata) -{ - char *name; - - /* yurck */ - name = gtk_object_get_data(GTK_OBJECT (edata->item_current), "arg_i"); - if (edata->item_current && name) { - filter_arg_remove(edata->arg, name); - fill_list(edata); - } -} - -static void -edit_sensitise(struct filter_arg_edit *edata) -{ - int state = edata->item_current != NULL; - gtk_widget_set_sensitive(edata->remove, state); - gtk_widget_set_sensitive(edata->edit, state); -} - -static void -filter_arg_edit_select(GtkWidget *w, GtkListItem *list, struct filter_arg_edit *edata) -{ - edata->item_current = GTK_WIDGET (list); - edit_sensitise(edata); -} - -static void -filter_arg_edit_unselect(GtkWidget *w, GtkListItem *list, struct filter_arg_edit *edata) -{ - edata->item_current = NULL; - edit_sensitise(edata); -} - -static void -filter_arg_edit_clicked(GnomeDialog *d, int button, struct filter_arg_edit *edata) -{ - struct _FilterArgPrivate *p = _PRIVATE(edata->arg); - - if (button == 0) { - gtk_signal_emit(GTK_OBJECT(edata->arg), signals[CHANGED]); - } else { - /* cancel button, restore old values ... */ - while (edata->arg->values) { - filter_arg_remove(edata->arg, edata->arg->values->data); - } - filter_arg_values_add_xml(edata->arg, p->oldargs); - } - xmlFreeNodeList(p->oldargs); - p->oldargs = NULL; - p->dialogue = NULL; - gnome_dialog_close(d); -} - -static void -filter_arg_edit_destroy(GnomeDialog *d, struct filter_arg_edit *edata) -{ - struct _FilterArgPrivate *p = _PRIVATE(edata->arg); - - if (p->oldargs) { - while (edata->arg->values) { - filter_arg_remove(edata->arg, edata->arg->values->data); - } - filter_arg_values_add_xml(edata->arg, p->oldargs); - xmlFreeNodeList(p->oldargs); - p->oldargs = NULL; - } - - if (p->dialogue) { - p->dialogue = NULL; - gnome_dialog_close(d); - } - g_free(edata); -} - -void -filter_arg_edit_values_1(FilterArg *arg) -{ - GtkWidget *list; - GnomeDialog *dialogue; - GtkWidget *hbox; - GtkWidget *vbox; - GtkWidget *button; - GtkWidget *scrolled_window, *frame; - struct filter_arg_edit * edata; - struct _FilterArgPrivate *p = _PRIVATE(arg); - - /* dont show more than 1 editor for each type */ - if (p->dialogue) { - gdk_window_raise(GTK_WIDGET(p->dialogue)->window); - return; - } - - /* copy the current state */ - p->oldargs = filter_arg_values_get_xml(arg); - - edata = g_malloc0(sizeof(*edata)); - edata->item_current = NULL; - edata->arg = arg; - - dialogue = (GnomeDialog *)gnome_dialog_new("Edit values", "Ok", "Cancel", 0); - edata->dialogue = dialogue; - - p->dialogue = GTK_WIDGET (dialogue); - - hbox = gtk_hbox_new(FALSE, 0); - - list = gtk_list_new(); - edata->list = GTK_LIST (list); - edata->items = NULL; - fill_list(edata); - - scrolled_window = gtk_scrolled_window_new(NULL, NULL); - frame = gtk_frame_new("Option values"); - - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), list); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_container_set_focus_vadjustment(GTK_CONTAINER (list), - gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window))); - gtk_container_add(GTK_CONTAINER(frame), scrolled_window); - gtk_widget_set_usize(frame, 200, 300); - gtk_box_pack_start(GTK_BOX (hbox), frame, TRUE, TRUE, 0); - - /* buttons */ - vbox = gtk_vbox_new(FALSE, 0); - - button = gtk_button_new_with_label ("Add"); - gtk_box_pack_start(GTK_BOX (vbox), button, FALSE, TRUE, 0); - edata->add = button; - button = gtk_button_new_with_label ("Remove"); - gtk_box_pack_start(GTK_BOX (vbox), button, FALSE, TRUE, 0); - edata->remove = button; - button = gtk_button_new_with_label ("Edit"); - gtk_box_pack_start(GTK_BOX (vbox), button, FALSE, TRUE, 0); - edata->edit = button; - - gtk_box_pack_start(GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - - gtk_signal_connect(GTK_OBJECT (edata->add), "clicked", filter_arg_edit_add, edata); - gtk_signal_connect(GTK_OBJECT (edata->edit), "clicked", filter_arg_edit_edit, edata); - gtk_signal_connect(GTK_OBJECT (edata->remove), "clicked", filter_arg_edit_delete, edata); - gtk_signal_connect(GTK_OBJECT (edata->list), "select_child", filter_arg_edit_select, edata); - gtk_signal_connect(GTK_OBJECT (edata->list), "unselect_child", filter_arg_edit_unselect, edata); - - gtk_widget_show(list); - gtk_widget_show_all(hbox); - gtk_box_pack_start(GTK_BOX (dialogue->vbox), hbox, TRUE, TRUE, 0); - - gtk_signal_connect(GTK_OBJECT (dialogue), "clicked", filter_arg_edit_clicked, edata); - gtk_signal_connect(GTK_OBJECT (dialogue), "destroy", filter_arg_edit_destroy, edata); - - edit_sensitise(edata); - - gtk_widget_show(GTK_WIDGET (dialogue)); -} - - diff --git a/filter/filter-arg.h b/filter/filter-arg.h deleted file mode 100644 index c7b038a996..0000000000 --- a/filter/filter-arg.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2000 Helix Code Inc. - * - * Authors: Michael Zucchi <notzed@helixcode.com> - * - * Abstract class to hold filter arguments. - * - * 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 _FILTER_ARG_H -#define _FILTER_ARG_H - -#include <gtk/gtk.h> -#include <gtkhtml/gtkhtml.h> -#include <gnome-xml/tree.h> /* gnome-xml */ - -#define FILTER_ARG(obj) GTK_CHECK_CAST (obj, filter_arg_get_type (), FilterArg) -#define FILTER_ARG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_arg_get_type (), FilterArgClass) -#define IS_FILTER_ARG(obj) GTK_CHECK_TYPE (obj, filter_arg_get_type ()) - -typedef struct _FilterArg FilterArg; -typedef struct _FilterArgClass FilterArgClass; - -struct _FilterArg { - GtkObject object; - - struct _FilterArgPrivate *priv; - - char *name; - GList *values; -}; - -struct _FilterArgClass { - GtkObjectClass parent_class; - - /* make a copy of yourself */ - struct _FilterArg * (*clone)(FilterArg *arg); - - /* virtual methods */ - void (*write_html)(FilterArg *arg, GtkHTML *html, GtkHTMLStream *stream); - void (*write_text)(FilterArg *arg, GString *string); - void (*free_value)(FilterArg *arg, void *v); - - void (*edit_values)(FilterArg *arg); - int (*edit_value)(FilterArg *arg, int index); - - void (*values_add_xml)(FilterArg *arg, xmlNodePtr node); - xmlNodePtr (*values_get_xml)(FilterArg *arg); - - char * (*get_value_as_string)(FilterArg *arg, void *data); - - /* signals */ - void (*changed)(FilterArg *arg); -}; - -guint filter_arg_get_type (void); -FilterArg *filter_arg_new (char *name); -FilterArg *filter_arg_clone(FilterArg *arg); -void filter_arg_copy (FilterArg *dst, FilterArg *src); -void filter_arg_value_add(FilterArg *a, void *v); - -void filter_arg_write_html(FilterArg *arg, GtkHTML *html, - GtkHTMLStream *stream); -void filter_arg_write_text(FilterArg *arg, GString *string); - -void filter_arg_edit_values(FilterArg *arg); -int filter_arg_edit_value(FilterArg *arg, int index); - -void filter_arg_remove(FilterArg *arg, void *v); -void filter_arg_add(FilterArg *arg, void *v); - -xmlNodePtr filter_arg_values_get_xml(FilterArg *arg); -void filter_arg_values_add_xml(FilterArg *arg, xmlNodePtr node); -int filter_arg_get_count(FilterArg *arg); -void *filter_arg_get_value(FilterArg *arg, int index); -char *filter_arg_get_value_as_string(FilterArg *arg, int index); - -#endif /* ! _FILTER_ARG_H */ - diff --git a/filter/filter-code.c b/filter/filter-code.c new file mode 100644 index 0000000000..cbab60359e --- /dev/null +++ b/filter/filter-code.c @@ -0,0 +1,121 @@ +/* + * 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 "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 *gspaper); +static void filter_code_finalise (GtkObject *obj); + +static FilterInputClass *parent_class; + +guint +filter_code_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "FilterCode", + sizeof(FilterCode), + sizeof(FilterCodeClass), + (GtkClassInitFunc)filter_code_class_init, + (GtkObjectInitFunc)filter_code_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(filter_input_get_type (), &type_info); + } + + return type; +} + +static void +filter_code_class_init (FilterCodeClass *class) +{ + GtkObjectClass *object_class; + FilterElementClass *filter_element = (FilterElementClass *)class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(filter_input_get_type ()); + + filter_element->build_code = build_code; + filter_element->format_sexp = format_sexp; + + object_class->finalize = filter_code_finalise; + /* override methods */ + +} + +static void +filter_code_init (FilterCode *o) +{ + ((FilterInput *)o)->type = g_strdup("code"); +} + +static void +filter_code_finalise(GtkObject *obj) +{ + FilterCode *o = (FilterCode *)obj; + + o = o; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * filter_code_new: + * + * Create a new FilterCode object. + * + * Return value: A new #FilterCode object. + **/ +FilterCode * +filter_code_new(void) +{ + FilterCode *o = (FilterCode *)gtk_type_new(filter_code_get_type ()); + return o; +} + +/* here, the string IS the code */ +static void build_code(FilterElement *fe, GString *out, struct _FilterPart *ff) +{ + GList *l; + FilterInput *fi = (FilterInput *)fe; + + l = fi->values; + while (l) { + g_string_append(out, (char *)l->data); + l = g_list_next(l); + } +} + +/* and we have no value */ +static void format_sexp(FilterElement *fe, GString *out) +{ + return; +} diff --git a/filter/filter-code.h b/filter/filter-code.h new file mode 100644 index 0000000000..c4bb04caab --- /dev/null +++ b/filter/filter-code.h @@ -0,0 +1,53 @@ +/* + * 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 _FILTER_CODE_H +#define _FILTER_CODE_H + +#include <gtk/gtk.h> + +#include "filter-input.h" + +#define FILTER_CODE(obj) GTK_CHECK_CAST (obj, filter_code_get_type (), FilterCode) +#define FILTER_CODE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_code_get_type (), FilterCodeClass) +#define IS_FILTER_CODE(obj) GTK_CHECK_TYPE (obj, filter_code_get_type ()) + +typedef struct _FilterCode FilterCode; +typedef struct _FilterCodeClass FilterCodeClass; + +struct _FilterCode { + FilterInput parent; +}; + +struct _FilterCodeClass { + FilterInputClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint filter_code_get_type (void); +FilterCode *filter_code_new (void); + +/* methods */ + +#endif /* ! _FILTER_CODE_H */ + diff --git a/filter/filter-colour.c b/filter/filter-colour.c new file mode 100644 index 0000000000..202908d016 --- /dev/null +++ b/filter/filter-colour.c @@ -0,0 +1,220 @@ +/* + * 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 <gnome-xml/xmlmemory.h> + +#include "e-util/e-sexp.h" +#include "filter-colour.h" + +#define d(x) + +static void xml_create(FilterElement *fe, xmlNodePtr node); +static xmlNodePtr xml_encode(FilterElement *fe); +static int xml_decode(FilterElement *fe, xmlNodePtr node); +static GtkWidget *get_widget(FilterElement *fe); +static void build_code(FilterElement *fe, GString *out, struct _FilterPart *ff); +static void format_sexp(FilterElement *, GString *); + +static void filter_colour_class_init (FilterColourClass *class); +static void filter_colour_init (FilterColour *gspaper); +static void filter_colour_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((FilterColour *)(x))->priv) + +struct _FilterColourPrivate { +}; + +static FilterElementClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +filter_colour_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "FilterColour", + sizeof(FilterColour), + sizeof(FilterColourClass), + (GtkClassInitFunc)filter_colour_class_init, + (GtkObjectInitFunc)filter_colour_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(filter_element_get_type (), &type_info); + } + + return type; +} + +static void +filter_colour_class_init (FilterColourClass *class) +{ + GtkObjectClass *object_class; + FilterElementClass *filter_element = (FilterElementClass *)class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(filter_element_get_type ()); + + object_class->finalize = filter_colour_finalise; + + /* override methods */ + filter_element->xml_create = xml_create; + filter_element->xml_encode = xml_encode; + filter_element->xml_decode = xml_decode; + filter_element->get_widget = get_widget; + filter_element->build_code = build_code; + filter_element->format_sexp = format_sexp; + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +filter_colour_init (FilterColour *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); +} + +static void +filter_colour_finalise(GtkObject *obj) +{ + FilterColour *o = (FilterColour *)obj; + + o = o; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * filter_colour_new: + * + * Create a new FilterColour object. + * + * Return value: A new #FilterColour object. + **/ +FilterColour * +filter_colour_new(void) +{ + FilterColour *o = (FilterColour *)gtk_type_new(filter_colour_get_type ()); + return o; +} + +static void xml_create(FilterElement *fe, xmlNodePtr node) +{ + /*FilterColour *fc = (FilterColour *)fe;*/ + + /* parent implementation */ + ((FilterElementClass *)(parent_class))->xml_create(fe, node); +} + +static xmlNodePtr xml_encode(FilterElement *fe) +{ + xmlNodePtr value; + FilterColour *fc = (FilterColour *)fe; + char hex[16]; + + d(printf("Encoding colour as xml\n")); + value = xmlNewNode(NULL, "value"); + xmlSetProp(value, "name", fe->name); + xmlSetProp(value, "type", "colour"); + + sprintf(hex, "%04x", fc->r); + xmlSetProp(value, "red", hex); + sprintf(hex, "%04x", fc->g); + xmlSetProp(value, "green", hex); + sprintf(hex, "%04x", fc->b); + xmlSetProp(value, "blue", hex); + sprintf(hex, "%04x", fc->a); + xmlSetProp(value, "alpha", hex); + + return value; +} + +static guint16 +get_value(xmlNodePtr node, char *name) +{ + unsigned int ret; + char *value; + + value = xmlGetProp(node, name); + sscanf(value, "%04x", &ret); + xmlFree(value); + return ret; +} + + +static int xml_decode(FilterElement *fe, xmlNodePtr node) +{ + FilterColour *fc = (FilterColour *)fe; + + fe->name = xmlGetProp(node, "name"); + fc->r = get_value(node, "red"); + fc->g = get_value(node, "green"); + fc->b = get_value(node, "blue"); + fc->a = get_value(node, "alpha"); + + return 0; +} + +static void set_colour(GnomeColorPicker *cp, guint r, guint g, guint b, guint a, FilterColour *fc) +{ + fc->r = r; + fc->g = g; + fc->b = b; + fc->a = a; +} + +static GtkWidget *get_widget(FilterElement *fe) +{ + FilterColour *fc = (FilterColour *)fe; + GnomeColorPicker *cp; + + cp = (GnomeColorPicker *)gnome_color_picker_new(); + gnome_color_picker_set_i16(cp, fc->r, fc->g, fc->b, fc->a); + gtk_widget_show((GtkWidget *)cp); + gtk_signal_connect((GtkObject *)cp, "color_set", set_colour, fe); + return (GtkWidget *)cp; +} + +static void build_code(FilterElement *fe, GString *out, struct _FilterPart *ff) +{ + return; +} + +static void format_sexp(FilterElement *fe, GString *out) +{ + char *str; + FilterColour *fc = (FilterColour *)fe; + + str =g_strdup_printf("rgb:%04x/%04x/%04x", fc->r, fc->g, fc->b); + e_sexp_encode_string(out, str); + g_free(str); +} diff --git a/filter/filter-colour.h b/filter/filter-colour.h new file mode 100644 index 0000000000..3526dfcfda --- /dev/null +++ b/filter/filter-colour.h @@ -0,0 +1,55 @@ +/* + * 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 _FILTER_COLOUR_H +#define _FILTER_COLOUR_H + +#include <gtk/gtk.h> +#include "filter-element.h" + +#define FILTER_COLOUR(obj) GTK_CHECK_CAST (obj, filter_colour_get_type (), FilterColour) +#define FILTER_COLOUR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_colour_get_type (), FilterColourClass) +#define IS_FILTER_COLOUR(obj) GTK_CHECK_TYPE (obj, filter_colour_get_type ()) + +typedef struct _FilterColour FilterColour; +typedef struct _FilterColourClass FilterColourClass; + +struct _FilterColour { + FilterElement parent; + struct _FilterColourPrivate *priv; + + guint16 r,g,b,a; +}; + +struct _FilterColourClass { + FilterElementClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint filter_colour_get_type (void); +FilterColour *filter_colour_new (void); + +/* methods */ + +#endif /* ! _FILTER_COLOUR_H */ + diff --git a/filter/filter-context.c b/filter/filter-context.c new file mode 100644 index 0000000000..701010fde9 --- /dev/null +++ b/filter/filter-context.c @@ -0,0 +1,138 @@ +/* + * 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 "filter-context.h" +#include "filter-filter.h" + +#define d(x) + +static void filter_context_class_init (FilterContextClass *class); +static void filter_context_init (FilterContext *gspaper); +static void filter_context_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((FilterContext *)(x))->priv) + +struct _FilterContextPrivate { +}; + +static RuleContextClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +filter_context_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "FilterContext", + sizeof(FilterContext), + sizeof(FilterContextClass), + (GtkClassInitFunc)filter_context_class_init, + (GtkObjectInitFunc)filter_context_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(rule_context_get_type (), &type_info); + } + + return type; +} + +static void +filter_context_class_init (FilterContextClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(rule_context_get_type ()); + + object_class->finalize = filter_context_finalise; + /* override methods */ + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +filter_context_init (FilterContext *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); + + rule_context_add_part_set((RuleContext *)o, "partset", filter_part_get_type(), + rule_context_add_part, rule_context_next_part); + rule_context_add_part_set((RuleContext *)o, "actionset", filter_part_get_type(), + (RCPartFunc)filter_context_add_action, + (RCNextPartFunc)filter_context_next_action); + + rule_context_add_rule_set((RuleContext *)o, "ruleset", filter_filter_get_type(), + (RCRuleFunc)rule_context_add_rule, rule_context_next_rule); +} + +static void +filter_context_finalise(GtkObject *obj) +{ + FilterContext *o = (FilterContext *)obj; + + o = o; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * filter_context_new: + * + * Create a new FilterContext object. + * + * Return value: A new #FilterContext object. + **/ +FilterContext * +filter_context_new(void) +{ + FilterContext *o = (FilterContext *)gtk_type_new(filter_context_get_type ()); + return o; +} + +void filter_context_add_action(FilterContext *f, FilterPart *action) +{ + d(printf("find action : ")); + f->actions = g_list_append(f->actions, action); +} + +FilterPart *filter_context_find_action(FilterContext *f, char *name) +{ + d(printf("find action : ")); + return filter_part_find_list(f->actions, name); +} + +FilterPart *filter_context_next_action(FilterContext *f, FilterPart *last) +{ + return filter_part_next_list(f->actions, last); +} diff --git a/filter/filter-context.h b/filter/filter-context.h new file mode 100644 index 0000000000..57ce961aaf --- /dev/null +++ b/filter/filter-context.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 _FILTER_CONTEXT_H +#define _FILTER_CONTEXT_H + +#include <gtk/gtk.h> +#include "rule-context.h" + +#define FILTER_CONTEXT(obj) GTK_CHECK_CAST (obj, filter_context_get_type (), FilterContext) +#define FILTER_CONTEXT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_context_get_type (), FilterContextClass) +#define IS_FILTER_CONTEXT(obj) GTK_CHECK_TYPE (obj, filter_context_get_type ()) + +typedef struct _FilterContext FilterContext; +typedef struct _FilterContextClass FilterContextClass; + +struct _FilterContext { + RuleContext parent; + struct _FilterContextPrivate *priv; + + GList *actions; +}; + +struct _FilterContextClass { + RuleContextClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint filter_context_get_type (void); +FilterContext *filter_context_new (void); + +/* methods */ +void filter_context_add_action(FilterContext *f, FilterPart *action); +FilterPart *filter_context_find_action(FilterContext *f, char *name); +/*FilterPart *filter_context_create_action(FilterContext *f, char *name);*/ +FilterPart *filter_context_next_action(FilterContext *f, FilterPart *last); + +#endif /* ! _FILTER_CONTEXT_H */ + diff --git a/filter/filter-driver.c b/filter/filter-driver.c index baca92a6d4..abd11c76f0 100644 --- a/filter/filter-driver.c +++ b/filter/filter-driver.c @@ -29,17 +29,21 @@ #include <gnome-xml/tree.h> #include <gnome-xml/parser.h> -#include "filter-arg-types.h" -#include "filter-xml.h" -#include "e-sexp.h" -#include "filter-format.h" - #include <camel/camel.h> +#include "filter-context.h" +#include "filter-filter.h" + +#include "e-util/e-sexp.h" + struct _FilterDriverPrivate { - GList *rules, *options; GHashTable *globals; /* global variables */ - FilterFolderFetcher fetcher; + + FilterContext *context; + + /* for callback */ + FilterGetFolderFunc get_folder; + void *data; /* run-time data */ GHashTable *folders; /* currently open folders */ @@ -69,6 +73,7 @@ static ESExpResult *do_delete(struct _ESExp *f, int argc, struct _ESExpResult ** static ESExpResult *mark_forward(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *); static ESExpResult *mark_copy(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *); static ESExpResult *do_stop(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *); +static ESExpResult *do_colour(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *); static struct { char *name; @@ -80,6 +85,7 @@ static struct { { "forward-to", (ESExpFunc *)mark_forward, 0 }, { "copy-to", (ESExpFunc *)mark_copy, 0 }, { "stop", (ESExpFunc *)do_stop, 0 }, + { "set-colour", (ESExpFunc *)do_colour, 0 }, }; static GtkObjectClass *filter_driver_parent; @@ -176,33 +182,25 @@ filter_driver_finalise (GtkObject *obj) * filter_driver_new: * @system: path to system rules * @user: path to user rules - * @fetcher: function to call to fetch folders + * @get_folder: function to call to fetch folders * * Create a new FilterDriver object. * * Return value: A new FilterDriver widget. **/ FilterDriver * -filter_driver_new (const char *system, const char *user, FilterFolderFetcher fetcher) +filter_driver_new (FilterContext *context, FilterGetFolderFunc get_folder, void *data) { FilterDriver *new; struct _FilterDriverPrivate *p; - xmlDocPtr desc, filt; new = FILTER_DRIVER (gtk_type_new (filter_driver_get_type ())); p = _PRIVATE(new); - p->fetcher = fetcher; - -#warning "fix leaks, free xml docs here" - desc = xmlParseFile(system); - p->rules = filter_load_ruleset(desc); - - filt = xmlParseFile(user); - if (filt == NULL) - p->options = NULL; - else - p->options = filter_load_optionset(filt, p->rules); + p->get_folder = get_folder; + p->data = data; + p->context = context; + gtk_object_ref((GtkObject *)context); return new; } @@ -221,119 +219,6 @@ void filter_driver_set_global(FilterDriver *d, const char *name, const char *val } } -extern int filter_find_arg(FilterArg *a, char *name); - -/* - - foreach rule - find matches - - foreach action - get all matches - - */ - -/* - splices ${cc} lines into a single string -*/ -static int -expand_variables(GString *out, char *source, GList *args, GHashTable *globals) -{ - GList *argl; - FilterArg *arg; - char *name= alloca(32); - char *start, *end, *newstart, *tmp, *val; - int namelen=32; - int len=0; - int ok = 0; - - start = source; - while ( (newstart = strstr(start, "${")) - && (end = strstr(newstart+2, "}")) ) { - len = end-newstart-2; - if (len+1>namelen) { - namelen = (len+1)*2; - name = alloca(namelen); - } - memcpy(name, newstart+2, len); - name[len] = 0; - argl = g_list_find_custom(args, name, (GCompareFunc) filter_find_arg); - if (argl) { - int i, count; - - tmp = g_strdup_printf("%.*s", newstart-start, start); - g_string_append(out, tmp); - g_free(tmp); - - arg = argl->data; - count = filter_arg_get_count(arg); - for (i=0;i<count;i++) { - g_string_append(out, " \""); - g_string_append(out, filter_arg_get_value_as_string(arg, i)); - g_string_append(out, "\""); - } - } else if ( (val = g_hash_table_lookup(globals, name)) ) { - tmp = g_strdup_printf("%.*s", newstart-start, start); - g_string_append(out, tmp); - g_free(tmp); - g_string_append(out, " \""); - g_string_append(out, val); - g_string_append(out, "\""); - } else { - ok = 1; - tmp = g_strdup_printf("%.*s", end-start+1, start); - g_string_append(out, tmp); - g_free(tmp); - } - start = end+1; - } - g_string_append(out, start); - - return ok; -} - -/* - build an expression for the filter -*/ -void -filter_driver_expand_option(FilterDriver *d, GString *s, GString *action, struct filter_option *op) -{ - GList *optionl; - FilterArg *arg; - struct _FilterDriverPrivate *p = _PRIVATE(d); - - if (s) { - g_string_append(s, "(and "); - optionl = op->options; - while (optionl) { - struct filter_optionrule *or = optionl->data; - if (or->rule->type == FILTER_XML_MATCH - || or->rule->type == FILTER_XML_EXCEPT) { - if (or->args) - arg = or->args->data; - expand_variables(s, or->rule->code, or->args, p->globals); - } - optionl = g_list_next(optionl); - } - - g_string_append(s, ")"); - } - - if (action) { - g_string_append(action, "(begin "); - optionl = op->options; - while (optionl) { - struct filter_optionrule *or = optionl->data; - if (or->rule->type == FILTER_XML_ACTION) { - expand_variables(action, or->rule->code, or->args, p->globals); - g_string_append(action, " "); - } - optionl = g_list_next(optionl); - } - g_string_append(action, ")"); - } -} - static ESExpResult * do_delete(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *d) { @@ -414,6 +299,13 @@ do_stop(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *d) return NULL; } +static ESExpResult * +do_colour(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *d) +{ + /* FIXME: implement */ + return NULL; +} + static CamelFolder * open_folder(FilterDriver *d, const char *folder_url) { @@ -425,7 +317,7 @@ open_folder(FilterDriver *d, const char *folder_url) if (camelfolder) return camelfolder; - camelfolder = p->fetcher(folder_url); + camelfolder = p->get_folder(d, folder_url, p->data); if (camelfolder) { g_hash_table_insert(p->folders, g_strdup(folder_url), camelfolder); camel_folder_freeze(camelfolder); @@ -461,6 +353,7 @@ close_folders(FilterDriver *d) return 0; } +#if 0 int filter_driver_rule_count(FilterDriver *d) { @@ -474,6 +367,7 @@ filter_driver_rule_get(FilterDriver *d, int n) struct _FilterDriverPrivate *p = _PRIVATE(d); return g_list_nth_data(p->options, n); } +#endif static void free_key (gpointer key, gpointer value, gpointer user_data) @@ -486,13 +380,13 @@ filter_driver_run(FilterDriver *d, CamelFolder *source, CamelFolder *inbox) { struct _FilterDriverPrivate *p = _PRIVATE(d); ESExpResult *r; - GList *options; GString *s, *a; GPtrArray *all; char *uid; int i; + FilterFilter *rule; -#warning "This must be made mega-robust" + /* FIXME: needs to check all failure cases */ p->source = source; /* setup runtime data */ @@ -504,13 +398,18 @@ filter_driver_run(FilterDriver *d, CamelFolder *source, CamelFolder *inbox) camel_exception_init(p->ex); camel_folder_freeze(inbox); - options = p->options; - while (options) { - struct filter_option *fo = options->data; + s = g_string_new(""); + a = g_string_new(""); + + rule = NULL; + while ( (rule = (FilterFilter *)rule_context_next_rule((RuleContext *)p->context, (FilterRule *)rule)) ) { + g_string_truncate(s, 0); + g_string_truncate(a, 0); + + filter_rule_build_code((FilterRule *)rule, s); + filter_filter_build_action(rule, a); - s = g_string_new(""); - a = g_string_new(""); - filter_driver_expand_option(d, s, a, fo); + printf("applying rule %s\n action %s\n", s->str, a->str); p->matches = camel_folder_search_by_expression (p->source, s->str, p->ex); @@ -529,20 +428,19 @@ filter_driver_run(FilterDriver *d, CamelFolder *source, CamelFolder *inbox) } } +#warning "Must check expression parsed and executed properly?" e_sexp_input_text(p->eval, a->str, strlen(a->str)); e_sexp_parse(p->eval); r = e_sexp_eval(p->eval); e_sexp_result_free(r); - g_string_free(s, TRUE); - g_string_free(a, TRUE); - g_strfreev((char **)p->matches->pdata); g_ptr_array_free(p->matches, FALSE); - - options = g_list_next(options); } + g_string_free(s, TRUE); + g_string_free(a, TRUE); + /* Do any queued copies, and make sure everything is deleted from * the source. If we have an inbox, anything that didn't get * processed otherwise goes there. diff --git a/filter/filter-driver.h b/filter/filter-driver.h index a7a752aecd..9c3b56824a 100644 --- a/filter/filter-driver.h +++ b/filter/filter-driver.h @@ -25,7 +25,8 @@ #include <gtk/gtk.h> #include <camel/camel-session.h> #include <camel/camel-folder.h> -#include "filter-xml.h" + +#include "filter-context.h" #define FILTER_DRIVER(obj) GTK_CHECK_CAST (obj, filter_driver_get_type (), FilterDriver) #define FILTER_DRIVER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_driver_get_type (), FilterDriverClass) @@ -44,21 +45,24 @@ struct _FilterDriverClass { GtkObjectClass parent_class; }; -typedef CamelFolder *(*FilterFolderFetcher) (const char *uri); +typedef CamelFolder * (*FilterGetFolderFunc) (FilterDriver *, const char *uri, void *data); guint filter_driver_get_type (void); -FilterDriver *filter_driver_new (const char *system, const char *user, FilterFolderFetcher fetcher); +FilterDriver *filter_driver_new (FilterContext *ctx, FilterGetFolderFunc fetcher, void *data); -void filter_driver_set_global(FilterDriver *, const char *name, const char *value); +/* + void filter_driver_set_global(FilterDriver *, const char *name, const char *value);*/ /* apply rules to a folder, unmatched messages goto inbox, if not NULL */ int filter_driver_run(FilterDriver *d, CamelFolder *source, CamelFolder *inbox); +#if 0 /* generate the search query/action string for a filter option */ void filter_driver_expand_option(FilterDriver *d, GString *s, GString *action, struct filter_option *op); /* get info about rules (options) */ int filter_driver_rule_count(FilterDriver *d); struct filter_option *filter_driver_rule_get(FilterDriver *d, int n); +#endif #endif /* ! _FILTER_DRIVER_H */ diff --git a/filter/filter-druid.c b/filter/filter-druid.c deleted file mode 100644 index a90dd79a0e..0000000000 --- a/filter/filter-druid.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Copyright (C) 2000 Helix Code Inc. - * - * Authors: Michael Zucchi <notzed@helixcode.com> - * - * 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 <glib.h> -#include <gtk/gtk.h> -#include <gnome.h> -#include <gtkhtml/gtkhtml.h> -#include <string.h> - -#include <gnome-xml/tree.h> -#include <gnome-xml/parser.h> - -#include "widgets/misc/e-scroll-frame.h" - -#include "filter-arg-types.h" -#include "filter-xml.h" -#include "filter-format.h" - - -#include "filter-druid.h" - -static void filter_druid_class_init (FilterDruidClass *klass); -static void filter_druid_init (FilterDruid *obj); - -#define _PRIVATE(x) (((FilterDruid *)(x))->priv) - -struct _FilterDruidPrivate { - GtkWidget *notebook; - int page; - - char *default_html; - - /* page 0 */ - GtkWidget *list0; - GtkWidget *html0; - GtkWidget *add0, *remove0, *up0, *down0; - GList *items0; - GtkFrame *listframe0; - - /* page 1 */ - GtkWidget *name1; - GtkWidget *activate1; - GtkHTML *html1; -}; - -/* forward ref's */ -static void build_druid(FilterDruid *d); -static void update_display(FilterDruid *f, int initial); - -/* globals */ -static GtkNotebookClass *filter_druid_parent; - -enum SIGNALS { - OPTION_SELECTED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -guint -filter_druid_get_type (void) -{ - static guint type = 0; - - if (!type) { - GtkTypeInfo type_info = { - "FilterDruid", - sizeof (FilterDruid), - sizeof (FilterDruidClass), - (GtkClassInitFunc) filter_druid_class_init, - (GtkObjectInitFunc) filter_druid_init, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) NULL - }; - - type = gtk_type_unique (gtk_notebook_get_type (), &type_info); - } - - return type; -} - -static void -object_destroy(GtkObject *obj) -{ - struct _FilterDruidPrivate *p = _PRIVATE(obj); - - g_free(p->default_html); - - gtk_signal_disconnect_by_data((GtkObject *)p->list0, obj); - - /* FIXME: free lists? */ - - GTK_OBJECT_CLASS(filter_druid_parent)->destroy(obj); -} - -static void -filter_druid_class_init (FilterDruidClass *klass) -{ - GtkObjectClass *object_class = (GtkObjectClass *) klass; - - filter_druid_parent = gtk_type_class (gtk_notebook_get_type ()); - - object_class->destroy = object_destroy; - - signals[OPTION_SELECTED] = - gtk_signal_new ("option_selected", - GTK_RUN_FIRST, - object_class->type, - GTK_SIGNAL_OFFSET (FilterDruidClass, option_selected), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); -} - -static void -filter_druid_init (FilterDruid *obj) -{ - struct _FilterDruidPrivate *priv; - - obj->priv = g_malloc0(sizeof(*obj->priv)); - priv = _PRIVATE(obj); -} - -/** - * filter_druid_new: - * - * Create a new FilterDruid object. - * - * Return value: A new FilterDruid widget. - **/ -FilterDruid * -filter_druid_new (void) -{ - FilterDruid *new = FILTER_DRUID ( gtk_type_new (filter_druid_get_type ())); - - build_druid(new); - - return new; -} - - -extern int filter_find_arg(FilterArg *a, char *name); - -#include "check.xpm" -#include "blank.xpm" - - -struct filter_optionrule * -find_optionrule(struct filter_option *option, char *name) -{ - GList *optionrulel; - struct filter_optionrule *or; - - optionrulel = option->options; - while (optionrulel) { - or = optionrulel->data; - if (!strcmp(or->rule->name, name)) { - return or; - } - optionrulel = g_list_next(optionrulel); - } - return NULL; -} - -static int display_order[] = { - FILTER_XML_MATCH, - FILTER_XML_EXCEPT, - FILTER_XML_ACTION, -}; -static char *display_pretext[] = { - "<b>For messages matching:</b><ul>", - "<b>Unless:</b><ul>", - "<b>Perform these actions:</b><ul>", -}; -static char *display_posttext[] = { - "</ul>", - "</ul>", - "</ul>", -}; - -void -html_write_options(GtkHTML *html, struct filter_option *option, char *def) -{ - GtkHTMLStream *stream; - GList *optionrulel; - int i; - - stream = gtk_html_begin(html); - - gtk_html_write(html, stream, "<body bgcolor=white alink=blue>", strlen("<body bgcolor=white alink=blue>")); - if (option) { - char *t; - - if (option->type == FILTER_XML_SEND) { - t = "<p>When a message is <i>sent</i>.</p>"; - } else { - t = "<p>When a message is <i>received</i>.</p>"; - } - gtk_html_write(html, stream, t, strlen(t)); - - for (i=0;i<sizeof(display_order)/sizeof(display_order[0]);i++) { - int doneheader = FALSE; - int donefirst = FALSE; - optionrulel = option->options; - while (optionrulel) { - struct filter_optionrule *or = optionrulel->data; - - if (or->rule->type == display_order[i]) { - if (!doneheader) { - gtk_html_write(html, stream, display_pretext[i], strlen(display_pretext[i])); - doneheader = TRUE; - } - - if (donefirst) { - gtk_html_write(html, stream, " <i>and</i> ", strlen(" <i>and</i> ")); - } - filter_description_html_write(or->rule->description, or->args, html, stream); - donefirst = TRUE; - gtk_html_write(html, stream, "<br>", strlen("<br>")); - } - optionrulel = g_list_next(optionrulel); - } - if (doneheader) { - gtk_html_write(html, stream, display_posttext[i], strlen(display_posttext[i])); - } - } - } else { - if (def == NULL) - def = "Select options."; - gtk_html_write(html, stream, def, strlen(def)); - } - gtk_html_end(html, stream, GTK_HTML_STREAM_OK); -} - -GList * -fill_rules(GList *rules, struct filter_option *option, int type) -{ - GList *rulel; - GtkWidget *listitem, *hbox, *checkbox, *label; - GList *items = NULL; - - rulel = rules; - while (rulel) { - struct filter_rule *fr = rulel->data; - char *labeltext; - - if (fr->type == type) { - int state; - - state = find_optionrule(option, fr->name) != NULL; - - labeltext = filter_description_text(fr->description, NULL); - - hbox = gtk_hbox_new(FALSE, 3); - checkbox = gnome_pixmap_new_from_xpm_d(state?check_xpm:blank_xpm); - gtk_box_pack_start(GTK_BOX(hbox), checkbox, FALSE, FALSE, 0); - label = gtk_label_new(labeltext); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0); - listitem = gtk_list_item_new(); - gtk_container_add(GTK_CONTAINER(listitem), hbox); - gtk_widget_show_all(listitem); - - gtk_object_set_data(GTK_OBJECT(listitem), "checkbox", checkbox); - gtk_object_set_data(GTK_OBJECT(listitem), "checkstate", (void *)state); - gtk_object_set_data(GTK_OBJECT(listitem), "rule", fr); - - items = g_list_append(items, listitem); - } - rulel = g_list_next(rulel); - } - return items; -} - -GList * -fill_options(GList *options) -{ - GList *optionl; - GtkWidget *listitem; - GList *items = NULL; - - optionl = options; - while (optionl) { - struct filter_option *op = optionl->data; - char *labeltext; - - labeltext = filter_description_text(op->description, NULL); - listitem = gtk_list_item_new_with_label(labeltext); - g_free(labeltext); - gtk_widget_show_all(listitem); - - gtk_object_set_data(GTK_OBJECT(listitem), "option", op); - - items = g_list_append(items, listitem); - optionl = g_list_next(optionl); - } - return items; -} - -static void -select_rule_child(GtkList *list, GtkWidget *child, FilterDruid *f) -{ - GtkWidget *w; - struct filter_rule *fr = gtk_object_get_data(GTK_OBJECT(child), "rule"); - int state; - struct filter_optionrule *rule; - /*struct _FilterDruidPrivate *p = _PRIVATE(f);*/ - - w = gtk_object_get_data(GTK_OBJECT(child), "checkbox"); - state = !(int) gtk_object_get_data(GTK_OBJECT(child), "checkstate"); - - gnome_pixmap_load_xpm_d(GNOME_PIXMAP(w), state?check_xpm:blank_xpm); - gtk_object_set_data(GTK_OBJECT(child), "checkstate", (void *)state); - - if (state) { - rule = filter_optionrule_new_from_rule(fr); - f->option_current->options = g_list_append(f->option_current->options, rule); - } else { - rule = find_optionrule(f->option_current, fr->name); - if (rule) { - f->option_current->options = g_list_remove(f->option_current->options, rule); - filter_clone_optionrule_free(rule); - } - } - - update_display(f, 0); -} - - - -static void -select_option_child(GtkList *list, GtkWidget *child, FilterDruid *f) -{ - struct filter_option *op; - struct filter_option *new; - GList *optionsl; - struct _FilterDruidPrivate *p = _PRIVATE(f); - - switch (p->page) { - case 1: - case 2: - case 3: - select_rule_child(list, child, f); - default: - return; - case 0: - break; - } - - if (f->option_current) { - /* free option_current copy */ - optionsl = f->option_current->options; - while (optionsl) { - GList *op = optionsl; - optionsl = g_list_next(optionsl); - filter_clone_optionrule_free(op->data); - } - g_list_free(f->option_current->options); - g_free(f->option_current); - f->option_current = NULL; - } - - if (child) { - op = gtk_object_get_data(GTK_OBJECT(child), "option"); - - /* clone the option */ - new = g_malloc(sizeof(*new)); - new->type = op->type; - new->description = op->description; - new->options = NULL; - optionsl = op->options; - while (optionsl) { - struct filter_optionrule *ornew, - *or = optionsl->data; - ornew = filter_clone_optionrule(or); - new->options = g_list_append(new->options, ornew); - optionsl = g_list_next(optionsl); - } - f->option_current = new; - - gtk_signal_emit(GTK_OBJECT(f), signals[OPTION_SELECTED], op); - } - - update_display(f, 0); -} - -static void -unselect_option_child(GtkList *list, GtkWidget *child, FilterDruid *f) -{ - select_option_child(list, NULL, f); -} - -static void -arg_changed(FilterArg *arg, FilterDruid *f) -{ - FilterArg *orig; - - orig = gtk_object_get_data(GTK_OBJECT (arg), "origin"); - if (orig) { - filter_arg_copy(orig, arg); - update_display(f, 0); - } else { - /* FIXME: uh, what the fuck to do here? */ - update_display(f, 0); - } -} - -static void -arg_link_clicked(GtkHTML *html, const char *url, FilterDruid *f) -{ - if (!strncmp(url, "arg:", 4)) { - FilterArg *arg; - void *dummy; - - if ((sscanf(url+4, "%p %p", &dummy, &arg) == 2) && arg) { - gtk_signal_connect(GTK_OBJECT (arg), "changed", arg_changed, f); - filter_arg_edit_values(arg); - } - } -} - -static void -option_name_changed(GtkEntry *entry, FilterDruid *f) -{ - struct filter_desc *desc; - - if (f->option_current) { - /* FIXME: lots of memory leaks */ - desc = g_malloc0(sizeof(*desc)); - desc->data = g_strdup(gtk_entry_get_text(entry)); - desc->type = FILTER_XML_TEXT; - desc->vartype = -1; - desc->varname = NULL; -#warning "Zucchi: is this correct?" - filter_description_free (f->option_current->description); - f->option_current->description = g_list_append(NULL, desc); - } -} - -static void -dialogue_clicked(FilterDruid *d, int button, void *data) -{ - GString *s = g_string_new(""); - struct _FilterDruidPrivate *p = _PRIVATE(d); - int initial=0; - - g_string_free(s, TRUE); - - switch(button) { - case 1: - if (p->page<4) { - p->page++; - initial =1; - } - break; - case 0: - if (p->page>0) { - p->page--; - initial = 1; - } - break; - } - update_display(d, initial); -} - -static int filter_types[] = { FILTER_XML_MATCH, FILTER_XML_EXCEPT, FILTER_XML_ACTION }; -static char *filter_titles[] = { - "Select rule(s), where messages match", - "Select rule(s), where messages do not match", - "Select action(s) to apply to messages" - -}; -static void -update_display(FilterDruid *f, int initial) -{ - struct _FilterDruidPrivate *p = _PRIVATE(f); - - switch (p->page) { - case 0: - if (initial) { - gtk_signal_handler_block_by_data((GtkObject *)p->list0, f); - gtk_list_remove_items((GtkList *)p->list0, p->items0); - p->items0 = fill_options(f->options); - gtk_list_append_items((GtkList *)p->list0, p->items0); - gtk_signal_handler_unblock_by_data((GtkObject *)p->list0, f); - gtk_frame_set_label(p->listframe0, "Select rule type"); - } - - html_write_options((GtkHTML *)p->html0, f->option_current, p->default_html); - break; - case 1: - case 2: - case 3: - if (initial) { - gtk_signal_handler_block_by_data((GtkObject *)p->list0, f); - gtk_list_remove_items((GtkList *)p->list0, p->items0); - p->items0 = fill_rules(f->rules, f->option_current, filter_types[p->page-1]); - gtk_list_append_items((GtkList *)p->list0, p->items0); - gtk_signal_handler_unblock_by_data((GtkObject *)p->list0, f); - gtk_frame_set_label(p->listframe0, filter_titles[p->page-1]); - gtk_notebook_set_page(GTK_NOTEBOOK(p->notebook), 0); - } - - html_write_options((GtkHTML *)p->html0, f->option_current, p->default_html); - break; - case 4: - if (initial) { - char *text; - text = filter_description_text(f->option_current->description, NULL); - if (text == NULL) { - /* maybe this could fudge something out of the first - bits of the rule */ - if (f->option_current->type == FILTER_XML_SEND) { - text = "Filter messages sent"; - } else { - text = "Filter messages received"; - } - gtk_entry_set_text(GTK_ENTRY(p->name1), text); - } else { - gtk_entry_set_text(GTK_ENTRY(p->name1), text); - g_free(text); - } - gtk_notebook_set_page(GTK_NOTEBOOK(p->notebook), 1); - } - - html_write_options((GtkHTML *)p->html1, f->option_current, p->default_html); - break; - - } -} - -void -filter_druid_set_rules(FilterDruid *f, GList *options, GList *rules, struct filter_option *current) -{ - struct filter_option *new; - GList *optionsl; - - f->options = options; - f->rules = rules; - f->user = NULL; - - if (current) { - /* FIXME: free this list if it isn't empty ... */ - /* clone the 'current' option */ - new = g_malloc(sizeof(*new)); - new->type = current->type; - new->description = current->description; - new->options = NULL; - optionsl = current->options; - while (optionsl) { - struct filter_optionrule *ornew, - *or = optionsl->data; - ornew = filter_clone_optionrule(or); - new->options = g_list_append(new->options, ornew); - optionsl = g_list_next(optionsl); - } - f->option_current = new; - } else { - f->option_current = NULL; - } - - update_display(f, 1); -} - -static void -build_druid(FilterDruid *d) -{ - GtkWidget *vbox, *frame, *scrolled_window, *list, *html, *label; - GtkWidget *table; - struct _FilterDruidPrivate *p = _PRIVATE(d); - -#if 0 - gnome_dialog_append_buttons((GnomeDialog *)d, "Prev", "Next", "Finish", "Cancel", 0); - gnome_dialog_set_close((GnomeDialog *)d, FALSE); - gnome_dialog_set_sensitive((GnomeDialog *)d, 0, FALSE); - gnome_dialog_set_sensitive((GnomeDialog *)d, 1, FALSE); - gnome_dialog_set_sensitive((GnomeDialog *)d, 2, FALSE); - gnome_dialog_set_default((GnomeDialog *)d, 1); -#endif - - p->notebook = GTK_WIDGET (d); - gtk_notebook_set_show_tabs(GTK_NOTEBOOK(p->notebook), FALSE); - gtk_notebook_set_show_border(GTK_NOTEBOOK(p->notebook), FALSE); - - /* page0, initial setup page */ - vbox = gtk_vbox_new(FALSE, 3); - frame = gtk_frame_new("Filters"); - p->listframe0 = (GtkFrame *)frame; - - list = gtk_list_new(); - scrolled_window = gtk_scrolled_window_new(NULL, NULL); - gtk_widget_set_usize(scrolled_window, 400, 150); - gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), GNOME_PAD_SMALL); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), list); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_container_set_focus_vadjustment - (GTK_CONTAINER (list), - gtk_scrolled_window_get_vadjustment - (GTK_SCROLLED_WINDOW (scrolled_window))); - gtk_container_add(GTK_CONTAINER(frame), scrolled_window); - gtk_box_pack_start((GtkBox *)vbox, frame, TRUE, TRUE, 0); - - frame = gtk_frame_new("Filter Description (click on values to edit)"); - html = gtk_html_new(); - scrolled_window = e_scroll_frame_new (NULL, NULL); - gtk_widget_set_usize(scrolled_window, 400, 150); - gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), GNOME_PAD_SMALL); - e_scroll_frame_set_policy (E_SCROLL_FRAME (scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - e_scroll_frame_set_shadow_type (E_SCROLL_FRAME (scrolled_window), - GTK_SHADOW_IN); - /*gtk_container_add(GTK_CONTAINER(frame1), html);*/ - gtk_container_add(GTK_CONTAINER(scrolled_window), html);//frame1); - gtk_container_add(GTK_CONTAINER(frame), scrolled_window); - gtk_box_pack_start((GtkBox *)vbox, frame, TRUE, TRUE, 0); - - p->html0 = html; - p->list0 = list; - - gtk_signal_connect(GTK_OBJECT(list), "select_child", select_option_child, d); - gtk_signal_connect(GTK_OBJECT(list), "unselect_child", select_option_child, d); -/* gtk_signal_connect(GTK_OBJECT(list), "unselect_child", unselect_option_child, d); */ -/* gtk_signal_connect(GTK_OBJECT(d), "clicked", dialogue_clicked, d);*/ - - gtk_signal_connect(GTK_OBJECT(html), "link_clicked", arg_link_clicked, d); - - gtk_notebook_append_page(GTK_NOTEBOOK(p->notebook), vbox, NULL); - - - /* page1, used for the final page display */ - vbox = gtk_vbox_new(FALSE, 3); - - frame = gtk_frame_new("Rule options"); - gtk_box_pack_start((GtkBox *)vbox, frame, FALSE, FALSE, 0); - - table = gtk_table_new (2, 2, FALSE); - gtk_container_set_border_width (GTK_CONTAINER (table), GNOME_PAD_SMALL); - gtk_table_set_row_spacings (GTK_TABLE (table), GNOME_PAD_SMALL); - gtk_table_set_col_spacings (GTK_TABLE (table), GNOME_PAD_SMALL); - - gtk_container_add(GTK_CONTAINER(frame), table); - - label = gtk_label_new("Name of rule"); - p->name1 = gtk_entry_new(); - gtk_signal_connect(GTK_OBJECT(p->name1), "changed", option_name_changed, d); - - p->activate1 = gtk_check_button_new_with_label("Activate rule?"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->activate1), TRUE); - - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, 0, 0, 0, 0); - gtk_table_attach (GTK_TABLE (table), p->name1, 1, 2, 0, 1, - GTK_FILL | GTK_EXPAND, 0, 0, 0); - gtk_table_attach (GTK_TABLE (table), p->activate1, 0, 2, 1, 2, - GTK_FILL | GTK_EXPAND, 0, 0, 0); - - /* another copy of the filter thingy */ - frame = gtk_frame_new("Filter Description (click on values to edit)"); - html = gtk_html_new(); - p->html1 = (GtkHTML *)html; - scrolled_window = e_scroll_frame_new (NULL, NULL); - gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), GNOME_PAD_SMALL); - e_scroll_frame_set_shadow_type (E_SCROLL_FRAME (scrolled_window), - GTK_SHADOW_IN); - gtk_widget_set_usize(scrolled_window, 400, 150); - e_scroll_frame_set_policy (E_SCROLL_FRAME (scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_container_add(GTK_CONTAINER(scrolled_window), html); - gtk_container_add(GTK_CONTAINER(frame), scrolled_window); - gtk_box_pack_start((GtkBox *)vbox, frame, TRUE, TRUE, 0); - - /* finish off */ - gtk_notebook_append_page(GTK_NOTEBOOK(p->notebook), vbox, NULL); - - gtk_signal_connect(GTK_OBJECT(html), "link_clicked", arg_link_clicked, d); - - gtk_widget_show_all(p->notebook); -} - -void -filter_druid_set_page(FilterDruid *f, enum FilterDruidPage page) -{ - struct _FilterDruidPrivate *p = _PRIVATE(f); - int initial = p->page != page; - - p->page = page; - update_display(f, initial); -} - - -void -filter_druid_set_default_html(FilterDruid *f, const char *html) -{ - struct _FilterDruidPrivate *p = _PRIVATE(f); - - g_free(p->default_html); - p->default_html = g_strdup(html); -} - -enum FilterDruidPage -filter_druid_get_page(FilterDruid *f) -{ - struct _FilterDruidPrivate *p = _PRIVATE(f); - - return p->page; -} - diff --git a/filter/filter-druid.h b/filter/filter-druid.h deleted file mode 100644 index 7927dc70dd..0000000000 --- a/filter/filter-druid.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2000 Helix Code Inc. - * - * Authors: Michael Zucchi <notzed@helixcode.com> - * - * 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 _FILTER_DRUID_H -#define _FILTER_DRUID_H - -#include <gtk/gtk.h> - -#include "filter-xml.h" - -#define FILTER_DRUID(obj) GTK_CHECK_CAST (obj, filter_druid_get_type (), FilterDruid) -#define FILTER_DRUID_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_druid_get_type (), FilterDruidClass) -#define IS_FILTER_DRUID(obj) GTK_CHECK_TYPE (obj, filter_druid_get_type ()) - -typedef struct _FilterDruid FilterDruid; -typedef struct _FilterDruidClass FilterDruidClass; - -enum FilterDruidPage { - FILTER_DRUID_SELECT_RULE, - FILTER_DRUID_SELECT_MATCH, - FILTER_DRUID_SELECT_NOMATCH, - FILTER_DRUID_SELECT_ACTION, - FILTER_DRUID_SELECT_FINISH -}; - -struct _FilterDruid { - GtkNotebook parent; - - GList *options; /* all options */ - GList *rules; /* all rules */ - GList *user; /* current user options */ - - struct filter_option *option_current; - - struct _FilterDruidPrivate *priv; -}; - -struct _FilterDruidClass { - GtkNotebookClass parent_class; - - /* signals */ - void (*option_selected)(FilterDruid *f, struct filter_option *option); -}; - -guint filter_druid_get_type (void); -FilterDruid *filter_druid_new (void); - -/* Hmm, glists suck, no typesafety */ -void filter_druid_set_rules(FilterDruid *f, GList *options, GList *rules, struct filter_option *userrule); -void filter_druid_set_default_html(FilterDruid *f, const char *text); - -/* set the page of display */ -void filter_druid_set_page(FilterDruid *f, enum FilterDruidPage page); -enum FilterDruidPage filter_druid_get_page(FilterDruid *f); - -/* check if the druid is allowed to finish at this point */ -gboolean filter_druid_can_finish(FilterDruid *f); - -#endif /* ! _FILTER_DRUID_H */ diff --git a/filter/filter-editor.c b/filter/filter-editor.c index 3bd239befa..368a5fbcfc 100644 --- a/filter/filter-editor.c +++ b/filter/filter-editor.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2000 Helix Code Inc. * - * Authors: Michael Zucchi <notzed@helixcode.com> + * 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 @@ -18,30 +18,29 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <gnome-xml/parser.h> -#include "filter-druid.h" -#include "filter-editor.h" +#include <gtk/gtk.h> +#include <gnome.h> +#include <glade/glade.h> +#include "filter-editor.h" +#include "filter-context.h" +#include "filter-filter.h" -static void filter_editor_class_init (FilterEditorClass *klass); -static void filter_editor_init (FilterEditor *obj); +#define d(x) -static GnomeDialogClass *filter_editor_parent; +#if 0 +static void filter_editor_class_init (FilterEditorClass *class); +static void filter_editor_init (FilterEditor *gspaper); +static void filter_editor_finalise (GtkObject *obj); #define _PRIVATE(x) (((FilterEditor *)(x))->priv) struct _FilterEditorPrivate { - FilterDruid *druid; - - GtkWidget *edit, *add, *remove, *up, *down; - - /* for sub-druid */ - struct filter_option *druid_option; - GtkWidget *druid_dialogue; - FilterDruid *druid_druid; }; -enum SIGNALS { +static GnomeDialogClass *parent_class; + +enum { LAST_SIGNAL }; @@ -55,354 +54,296 @@ filter_editor_get_type (void) if (!type) { GtkTypeInfo type_info = { "FilterEditor", - sizeof (FilterEditor), - sizeof (FilterEditorClass), - (GtkClassInitFunc) filter_editor_class_init, - (GtkObjectInitFunc) filter_editor_init, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) NULL + sizeof(FilterEditor), + sizeof(FilterEditorClass), + (GtkClassInitFunc)filter_editor_class_init, + (GtkObjectInitFunc)filter_editor_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL }; - type = gtk_type_unique (gnome_dialog_get_type (), &type_info); + type = gtk_type_unique(gnome_dialog_get_type (), &type_info); } return type; } static void -object_destroy(GtkObject *obj) +filter_editor_class_init (FilterEditorClass *class) { - struct _FilterEditorPrivate *p = _PRIVATE(obj); - - if (p->druid_druid) - gtk_object_unref(GTK_OBJECT (p->druid_dialogue)); - - GTK_OBJECT_CLASS(filter_editor_parent)->destroy(GTK_OBJECT (obj)); -} - -static void -filter_editor_class_init (FilterEditorClass *klass) -{ - GtkObjectClass *object_class = (GtkObjectClass *) klass; + GtkObjectClass *object_class; - filter_editor_parent = gtk_type_class (gnome_dialog_get_type ()); - - object_class->destroy = object_destroy; - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); -} + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(gnome_dialog_get_type ()); -static void -filter_editor_init (FilterEditor *obj) -{ - obj->priv = g_malloc0(sizeof(*obj->priv)); -} + object_class->finalize = filter_editor_finalise; + /* override methods */ + /* signals */ -static void -sensitise(FilterEditor *e) -{ - struct _FilterEditorPrivate *p = _PRIVATE(e); - - gtk_widget_set_sensitive(p->add, TRUE); - gtk_widget_set_sensitive(p->edit, e->option_current != NULL); - gtk_widget_set_sensitive(p->remove, e->option_current != NULL); - gtk_widget_set_sensitive(p->up, g_list_index(e->useroptions, e->option_current)>0); - gtk_widget_set_sensitive(p->down, g_list_index(e->useroptions, e->option_current)!=g_list_length(e->useroptions)-1); + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); } static void -druid_option_selected(FilterDruid *f, struct filter_option *option, FilterEditor *e) +filter_editor_init (FilterEditor *o) { - e->option_current = option; - sensitise(e); + o->priv = g_malloc0(sizeof(*o->priv)); } static void -druid_dialogue_clicked(GnomeDialog *d, int button, FilterEditor *e) +filter_editor_finalise(GtkObject *obj) { - struct _FilterEditorPrivate *p = _PRIVATE(e); - int page = filter_druid_get_page(p->druid_druid); + FilterEditor *o = (FilterEditor *)obj; - switch(button) { - case 1: - if (page<4) { - page++; - } - break; - case 0: - if (page>0) { - page--; - } - break; - case 2: - if (p->druid_druid->option_current) { -#warning "what is going on here?" - /* FIXME: should this be struct filter_option?? */ - struct filter_option *or; - - printf("refcount = %d\n", ((GtkObject *)p->druid_druid)->ref_count); - - or = p->druid_druid->option_current; - if (p->druid_option) { - GList *node; - - node = g_list_find(e->useroptions, p->druid_option); - if (node) { - /* FIXME: free old one */ - /* we need to know what type or is supposed to be before - we can free old data */ - node->data = or; - } else { - g_warning("Cannot find node I edited, appending instead"); - e->useroptions = g_list_append(e->useroptions, or); - } - } else { - e->useroptions = g_list_append(e->useroptions, or); - } - filter_druid_set_rules(p->druid, e->useroptions, e->rules, or); - } - case 3: - p->druid_dialogue = NULL; - gnome_dialog_close(d); - return; - } - filter_druid_set_page(p->druid_druid, page); - - gnome_dialog_set_sensitive(GNOME_DIALOG (p->druid_dialogue), 0, page > 0); - gnome_dialog_set_sensitive(GNOME_DIALOG (p->druid_dialogue), 1, page < 4); - /* FIXME: make this depenedant on when the rules are actually done */ - gnome_dialog_set_sensitive(GNOME_DIALOG (p->druid_dialogue), 2, page == 4); + ((GtkObjectClass *)(parent_class))->finalize(obj); } -static void -druid_dialogue_option_selected(FilterDruid *f, struct filter_option *option, FilterEditor *e) +/** + * filter_editor_new: + * + * Create a new FilterEditor object. + * + * Return value: A new #FilterEditor object. + **/ +FilterEditor * +filter_editor_new(void) { - struct _FilterEditorPrivate *p = _PRIVATE(e); - - gnome_dialog_set_sensitive(GNOME_DIALOG (p->druid_dialogue), 1, TRUE); + FilterEditor *o = (FilterEditor *)gtk_type_new(filter_editor_get_type ()); + return o; } -static void -add_or_edit(FilterEditor *e, struct filter_option *option) -{ - GnomeDialog *dialogue; - FilterDruid *druid; - struct _FilterEditorPrivate *p = _PRIVATE(e); - - if (p->druid_dialogue) { - gdk_window_raise(GTK_WIDGET(p->druid_dialogue)->window); - return; - } - - dialogue = GNOME_DIALOG (gnome_dialog_new (option ? _("Edit Filter") : _("Create filter"), NULL)); - p->druid_dialogue = GTK_WIDGET (dialogue); - { - const char *pixmaps[] = { - GNOME_STOCK_BUTTON_PREV, - GNOME_STOCK_BUTTON_NEXT, - GNOME_STOCK_BUTTON_APPLY, - GNOME_STOCK_BUTTON_CANCEL, - NULL - }; - const char *names[] = { - N_("Back"), - N_("Next"), - N_("Finish"), - N_("Cancel"), - NULL - }; - if (option) - names[2] = N_("Apply"); - gnome_dialog_append_buttons_with_pixmaps(dialogue, names, pixmaps); - } - - gnome_dialog_set_close(dialogue, FALSE); - gnome_dialog_set_sensitive(dialogue, 0, FALSE); - gnome_dialog_set_sensitive(dialogue, 1, FALSE); - gnome_dialog_set_sensitive(dialogue, 2, FALSE); - gnome_dialog_set_default(dialogue, 1); - - gtk_signal_connect(GTK_OBJECT (dialogue), "clicked", druid_dialogue_clicked, e); - - druid = FILTER_DRUID (filter_druid_new()); - - p->druid_druid = druid; - - filter_druid_set_default_html(p->druid_druid, - _("<h2>Create Filtering Rule</h2>" - "<p>Select one of the base rules above, then continue " - "forwards to customise it.</p>")); - - filter_druid_set_rules(druid, e->systemoptions, e->rules, option); - gtk_box_pack_start(GTK_BOX (dialogue->vbox), GTK_WIDGET (druid), TRUE, TRUE, 0); - - if (option) { - druid_dialogue_clicked(dialogue, 1, e); - } - - p->druid_option = option; +#endif - gtk_signal_connect(GTK_OBJECT (druid), "option_selected", druid_dialogue_option_selected, e); - gtk_widget_show(GTK_WIDGET (druid)); - gtk_widget_show(GTK_WIDGET (dialogue)); -} +enum { + BUTTON_ADD, + BUTTON_EDIT, + BUTTON_DELETE, + BUTTON_UP, + BUTTON_DOWN, + BUTTON_LAST +}; -static void -add_clicked(GtkWidget *w, FilterEditor *e) -{ - add_or_edit(e, NULL); -} +struct _editor_data { + RuleContext *f; + FilterRule *current; + GtkList *list; + GtkButton *buttons[BUTTON_LAST]; +}; -static void -edit_clicked(GtkWidget *w, FilterEditor *e) -{ - add_or_edit(e, e->option_current); -} +static void set_sensitive(struct _editor_data *data); -static void -remove_clicked(GtkWidget *w, FilterEditor *e) +static void rule_add(GtkWidget *widget, struct _editor_data *data) { - printf("remove current ...\n"); + FilterFilter *rule; + int result; + GnomeDialog *gd; + GtkWidget *w; + FilterPart *part; + + d(printf("add rule\n")); + /* create a new rule with 1 match and 1 action */ + rule = filter_filter_new(); + + part = rule_context_next_part(data->f, NULL); + filter_rule_add_part((FilterRule *)rule, filter_part_clone(part)); + part = filter_context_next_action((FilterContext *)data->f, NULL); + filter_filter_add_action(rule, filter_part_clone(part)); + + w = filter_rule_get_widget((FilterRule *)rule, data->f); + gd = (GnomeDialog *)gnome_dialog_new("Add Rule", "Ok", "Cancel", NULL); + gtk_box_pack_start((GtkBox *)gd->vbox, w, FALSE, TRUE, 0); + gtk_widget_show((GtkWidget *)gd); + result = gnome_dialog_run_and_close(gd); + if (result == 0) { + GtkListItem *item = (GtkListItem *)gtk_list_item_new_with_label(((FilterRule *)rule)->name); + GList *l = NULL; + + gtk_object_set_data((GtkObject *)item, "rule", rule); + gtk_widget_show((GtkWidget *)item); + l = g_list_append(l, item); + gtk_list_append_items(data->list, l); + gtk_list_select_child(data->list, (GtkWidget *)item); + data->current = (FilterRule *)rule; + rule_context_add_rule(data->f, (FilterRule *)rule); + set_sensitive(data); + } else { + gtk_object_unref((GtkObject *)rule); + } } -static void -up_clicked(GtkWidget *w, FilterEditor *e) +static void rule_edit(GtkWidget *widget, struct _editor_data *data) { - printf("up ...\n"); + GtkWidget *w; + int result; + GnomeDialog *gd; + FilterRule *rule; + int pos; + + d(printf("edit rule\n")); + rule = data->current; + w = filter_rule_get_widget(rule, data->f); + gd = (GnomeDialog *)gnome_dialog_new("Edit Rule", "Ok", NULL); + gtk_box_pack_start((GtkBox *)gd->vbox, w, FALSE, TRUE, 0); + gtk_widget_show((GtkWidget *)gd); + result = gnome_dialog_run_and_close(gd); + + if (result == 0) { + pos = rule_context_get_rank_rule(data->f, data->current); + if (pos != -1) { + GtkListItem *item = g_list_nth_data(data->list->children, pos); + gtk_label_set_text((GtkLabel *)(((GtkBin *)item)->child), data->current->name); + } + } } -static void -down_clicked(GtkWidget *w, FilterEditor *e) +static void rule_delete(GtkWidget *widget, struct _editor_data *data) { - printf("down ...\n"); + int pos; + GList *l; + GtkListItem *item; + + d(printf("ddelete rule\n")); + pos = rule_context_get_rank_rule(data->f, data->current); + if (pos != -1) { + rule_context_remove_rule(data->f, data->current); + + item = g_list_nth_data(data->list->children, pos); + l = g_list_append(NULL, item); + gtk_list_remove_items(data->list, l); + g_list_free(l); + + gtk_object_unref((GtkObject *)data->current); + data->current = NULL; + } + set_sensitive(data); } -/* build the contents of the editor */ -static void -build_editor(FilterEditor *e) +static void rule_move(struct _editor_data *data, int from, int to) { - struct _FilterEditorPrivate *p = _PRIVATE(e); - GtkWidget *hbox; - GtkWidget *vbox; + GList *l; + GtkListItem *item; - hbox = gtk_hbox_new(FALSE, 3); - - p->druid = FILTER_DRUID (filter_druid_new()); - gtk_box_pack_start(GTK_BOX (hbox), GTK_WIDGET (p->druid), TRUE, TRUE, 0); - - vbox = gtk_vbox_new(FALSE, 0); + d(printf("moving %d to %d\n", from, to)); + rule_context_rank_rule(data->f, data->current, to); - p->edit = gtk_button_new_with_label ("Edit"); - p->add = gtk_button_new_with_label ("Add"); - p->remove = gtk_button_new_with_label ("Remove"); - p->up = gtk_button_new_with_label ("Up"); - p->down = gtk_button_new_with_label ("Down"); - - gtk_box_pack_start(GTK_BOX (vbox), p->edit, FALSE, TRUE, 0); - gtk_box_pack_start(GTK_BOX (vbox), p->add, FALSE, TRUE, 3); - gtk_box_pack_start(GTK_BOX (vbox), p->remove, FALSE, TRUE, 0); - gtk_box_pack_start(GTK_BOX (vbox), p->up, FALSE, TRUE, 3); - gtk_box_pack_start(GTK_BOX (vbox), p->down, FALSE, TRUE, 0); - - gtk_box_pack_start(GTK_BOX (hbox), vbox, FALSE, FALSE, 0); - - gtk_box_pack_start(GTK_BOX (e->parent.vbox), hbox, TRUE, TRUE, 0); - - gtk_signal_connect(GTK_OBJECT (p->druid), "option_selected", druid_option_selected, e); - - gtk_signal_connect(GTK_OBJECT (p->edit), "clicked", edit_clicked, e); - gtk_signal_connect(GTK_OBJECT (p->add), "clicked", add_clicked, e); - gtk_signal_connect(GTK_OBJECT (p->remove), "clicked", remove_clicked, e); - gtk_signal_connect(GTK_OBJECT (p->up), "clicked", up_clicked, e); - gtk_signal_connect(GTK_OBJECT (p->down), "clicked", down_clicked, e); - - filter_druid_set_default_html(p->druid, "<h2>Filtering Rules</h2>" - "<p>Select one of the rules above to <i>view</i>, and " - "<i>edit</i>. Or <i>Add</i> a new rule.</p>"); - - gtk_widget_show_all(hbox); - sensitise(e); + item = g_list_nth_data(data->list->children, from); + l = g_list_append(NULL, item); + gtk_list_remove_items_no_unref(data->list, l); + gtk_list_insert_items(data->list, l, to); + gtk_list_select_child(data->list, (GtkWidget *)item); + set_sensitive(data); } - -/** - * filter_editor_new: - * - * Create a new FilterEditor object. - * - * Return value: A new FilterEditor widget. - **/ -FilterEditor * -filter_editor_new (void) +static void rule_up(GtkWidget *widget, struct _editor_data *data) { - FilterEditor *new = FILTER_EDITOR ( gtk_type_new (filter_editor_get_type ())); - - build_editor(new); + int pos; - return new; + d(printf("up rule\n")); + pos = rule_context_get_rank_rule(data->f, data->current); + if (pos>0) { + rule_move(data, pos, pos-1); + } } -void -filter_editor_set_rules(FilterEditor *e, GList *rules, GList *systemoptions, GList *useroptions) +static void rule_down(GtkWidget *widget, struct _editor_data *data) { - struct _FilterEditorPrivate *p = _PRIVATE(e); + int pos; - e->rules= rules; - e->systemoptions = systemoptions; - e->useroptions = useroptions; - - filter_druid_set_rules(p->druid, useroptions, rules, NULL); + d(printf("down rule\n")); + pos = rule_context_get_rank_rule(data->f, data->current); + rule_move(data, pos, pos+1); } -void -filter_editor_set_rule_files(FilterEditor *e, const char *systemrules, const char *userrules) -{ - GList *rules, *options = NULL, *options2; - xmlDocPtr doc, out; - - doc = xmlParseFile(systemrules); - if( doc == NULL ) { - g_warning( "Couldn't load system rules file %s", systemrules ); - rules = NULL; - options2 = NULL; - } else { - rules = filter_load_ruleset(doc); - options2 = filter_load_optionset(doc, rules); - } +static struct { + char *name; + GtkSignalFunc func; +} edit_buttons[] = { + { "rule_add", rule_add }, + { "rule_edit", rule_edit }, + { "rule_delete", rule_delete }, + { "rule_up", rule_up }, + { "rule_down", rule_down }, +}; - out = xmlParseFile(userrules); - if (out) - options = filter_load_optionset(out, rules); +static void +set_sensitive(struct _editor_data *data) +{ + FilterRule *rule = NULL; + int index=-1, count=0; - filter_editor_set_rules(e, rules, options2, options); + while ((rule = rule_context_next_rule(data->f, rule))) { + if (rule == data->current) + index=count; + count++; + } + d(printf("index = %d count=%d\n", index, count)); + count--; + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_EDIT], index != -1); + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_DELETE], index != -1); + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_UP], index > 0); + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_DOWN], index >=0 && index<count); } -int -filter_editor_save_rules(FilterEditor *e, const char *userrules) +static void +select_rule(GtkWidget *w, GtkWidget *child, struct _editor_data *data) { - return filter_write_optionset_file(userrules, e->useroptions); + data->current = gtk_object_get_data((GtkObject *)child, "rule"); + if (data->current) + d(printf("seledct rule: %s\n", data->current->name)); + else + d(printf("bad data?\n")); + set_sensitive(data); } -#ifdef STANDALONE - -int main(int argc, char **argv) +GtkWidget *filter_editor_construct (struct _FilterContext *f) { - FilterEditor *fe; + GladeXML *gui; + GtkWidget *d, *w; + GList *l; + FilterRule *rule = NULL; + struct _editor_data *data; + int i; + + g_assert(IS_FILTER_CONTEXT(f)); + + data = g_malloc0(sizeof(*data)); + data->f = (RuleContext *)f; + + gui = glade_xml_new(FILTER_GLADEDIR "/filter.glade", "edit_filter"); + d = glade_xml_get_widget (gui, "edit_filter"); + gtk_object_set_data_full((GtkObject *)d, "data", data, g_free); + + gtk_window_set_title((GtkWindow *)d, "Edit Filters"); + 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); + } - gnome_init("Test", "0.0", argc, argv); - gdk_rgb_init (); - gtk_widget_set_default_colormap (gdk_rgb_get_cmap ()); - gtk_widget_set_default_visual (gdk_rgb_get_visual ()); + /* to be defined yet */ +#if 0 + w = glade_xml_get_widget (gui, "filter_source"); + l = GTK_MENU_SHELL(GTK_OPTION_MENU(w)->menu)->children; + while (l) { + b = l->data; + l = l->next; + } +#endif - fe = filter_editor_new(); - filter_editor_set_rule_files(fe, "/home/notzed/gnome/evolution/filter/filterdescription.xml", "/home/notzed/filters.xml"); - gtk_widget_show(fe); + w = glade_xml_get_widget (gui, "rule_list"); + data->list = (GtkList *)w; + l = NULL; + while ((rule = rule_context_next_rule((RuleContext *)f, rule))) { + GtkListItem *item = (GtkListItem *)gtk_list_item_new_with_label(rule->name); + gtk_object_set_data((GtkObject *)item, "rule", rule); + gtk_widget_show((GtkWidget *)item); + l = g_list_append(l, item); + } + gtk_list_append_items(data->list, l); + gtk_signal_connect((GtkObject *)w, "select_child", select_rule, data); - gtk_main(); + set_sensitive(data); + gtk_object_unref((GtkObject *)gui); - return 0; + return d; } - -#endif diff --git a/filter/filter-editor.h b/filter/filter-editor.h index 66f7a81e11..20369a9536 100644 --- a/filter/filter-editor.h +++ b/filter/filter-editor.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2000 Helix Code Inc. * - * Authors: Michael Zucchi <notzed@helixcode.com> + * 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 @@ -22,37 +22,40 @@ #define _FILTER_EDITOR_H #include <gtk/gtk.h> -#include <gnome.h> -#include "filter-xml.h" +#include <libgnomeui/gnome-dialog.h> -#define FILTER_EDITOR(obj) GTK_CHECK_CAST (obj, filter_editor_get_type (), FilterEditor) -#define FILTER_EDITOR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_editor_get_type (), FilterEditorClass) +#if 0 +/* NOTE: object stuff not used (yet?), this is just a holder file for a static factory */ + +#define FILTER_EDITOR(obj) GTK_CHECK_CAST (obj, filter_editor_get_type (), FilterEditor) +#define FILTER_EDITOR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_editor_get_type (), FilterEditorClass) #define IS_FILTER_EDITOR(obj) GTK_CHECK_TYPE (obj, filter_editor_get_type ()) -typedef struct _FilterEditor FilterEditor; -typedef struct _FilterEditorClass FilterEditorClass; +typedef struct _FilterEditor FilterEditor; +typedef struct _FilterEditorClass FilterEditorClass; struct _FilterEditor { GnomeDialog parent; - struct _FilterEditorPrivate *priv; - GList *rules; - GList *systemoptions; - GList *useroptions; - - struct filter_option *option_current; }; struct _FilterEditorClass { GnomeDialogClass parent_class; + + /* virtual methods */ + + /* signals */ }; guint filter_editor_get_type (void); -FilterEditor *filter_editor_new (void); +FilterEditor *filter_editor_new (void); +#endif + +struct _FilterContext; -void filter_editor_set_rules(FilterEditor *e, GList *rules, GList *systemoptions, GList *useroptions); -void filter_editor_set_rule_files(FilterEditor *e, const char *systemrules, const char *userrules); -int filter_editor_save_rules(FilterEditor *e, const char *userrules); +/* methods */ +GtkWidget *filter_editor_construct (struct _FilterContext *f); #endif /* ! _FILTER_EDITOR_H */ + diff --git a/filter/filter-element.c b/filter/filter-element.c new file mode 100644 index 0000000000..049b15727b --- /dev/null +++ b/filter/filter-element.c @@ -0,0 +1,264 @@ +/* + * 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 "filter-element.h" +#include "filter-input.h" +#include "filter-option.h" +#include "filter-code.h" +#include "filter-colour.h" +#include "filter-folder.h" + +static void xml_create(FilterElement *fe, xmlNodePtr node); +static FilterElement *clone(FilterElement *fe); + +static void filter_element_class_init (FilterElementClass *class); +static void filter_element_init (FilterElement *gspaper); +static void filter_element_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((FilterElement *)(x))->priv) +struct _FilterElementPrivate { +}; + +static GtkObjectClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +filter_element_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "FilterElement", + sizeof(FilterElement), + sizeof(FilterElementClass), + (GtkClassInitFunc)filter_element_class_init, + (GtkObjectInitFunc)filter_element_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(gtk_object_get_type (), &type_info); + } + + return type; +} + +static void +filter_element_class_init (FilterElementClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(gtk_object_get_type ()); + + object_class->finalize = filter_element_finalise; + + /* override methods */ + class->xml_create = xml_create; + class->clone = clone; + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +filter_element_init (FilterElement *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); +} + +static void +filter_element_finalise(GtkObject *obj) +{ + FilterElement *o = (FilterElement *)obj; + + o = o; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * filter_element_new: + * + * Create a new FilterElement object. + * + * Return value: A new #FilterElement object. + **/ +FilterElement * +filter_element_new(void) +{ + FilterElement *o = (FilterElement *)gtk_type_new(filter_element_get_type ()); + return o; +} + +/** + * filter_element_xml_create: + * @fe: + * @node: + * + * Create a new filter element based on an xml definition of + * that element. + **/ +void filter_element_xml_create (FilterElement *fe, xmlNodePtr node) +{ + return ((FilterElementClass *)((GtkObject *)fe)->klass)->xml_create(fe, node); +} + +/** + * filter_element_xml_encode: + * @fe: + * + * Encode the values of a filter element into xml format. + * + * Return value: + **/ +xmlNodePtr filter_element_xml_encode (FilterElement *fe) +{ + return ((FilterElementClass *)((GtkObject *)fe)->klass)->xml_encode(fe); +} + +/** + * filter_element_xml_decode: + * @fe: + * @node: + * + * Decode the values of a fitler element from xml format. + * + * Return value: + **/ +int filter_element_xml_decode (FilterElement *fe, xmlNodePtr node) +{ + return ((FilterElementClass *)((GtkObject *)fe)->klass)->xml_decode(fe, node); +} + +/** + * filter_element_clone: + * @fe: + * + * Clones the FilterElement @fe. + * + * Return value: + **/ +FilterElement *filter_element_clone (FilterElement *fe) +{ + return ((FilterElementClass *)((GtkObject *)fe)->klass)->clone(fe); +} + +/** + * filter_element_get_widget: + * @fe: + * @node: + * + * Create a widget to represent this element. + * + * Return value: + **/ +GtkWidget *filter_element_get_widget (FilterElement *fe) +{ + return ((FilterElementClass *)((GtkObject *)fe)->klass)->get_widget(fe); +} + +/** + * filter_element_build_code: + * @fe: + * @out: + * @ff: + * + * Add the code representing this element to the output string @out. + **/ +void filter_element_build_code (FilterElement *fe, GString *out, struct _FilterPart *ff) +{ + return ((FilterElementClass *)((GtkObject *)fe)->klass)->build_code(fe, out, ff); +} + +/** + * filter_element_format_sexp: + * @fe: + * @out: + * + * 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) +{ + return ((FilterElementClass *)((GtkObject *)fe)->klass)->format_sexp(fe, out); +} + +/** + * filter_element_new_type_name: + * @type: + * + * Create a new filter element based on its type name. + * + * Return value: + **/ +FilterElement *filter_element_new_type_name (const char *type) +{ + if (type == NULL) + return NULL; + + if (!strcmp(type, "string")) { + return (FilterElement *)filter_input_new(); + } else if (!strcmp(type, "folder")) { + return (FilterElement *)filter_folder_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(); + } else if (!strcmp(type, "colour")) { + return (FilterElement *)filter_colour_new(); + } else if (!strcmp(type, "optionlist")) { + return (FilterElement *)filter_option_new(); + } else { + g_warning("Unknown filter type '%s'", type); + return 0; + } +} + +/* default implementations */ +static void xml_create(FilterElement *fe, xmlNodePtr node) +{ + fe->name = xmlGetProp(node, "name"); +} + +static FilterElement *clone(FilterElement *fe) +{ + xmlNodePtr node; + FilterElement *new; + + new = (FilterElement *)gtk_type_new( ((GtkObject *)fe)->klass->type ); + node = filter_element_xml_encode(fe); + filter_element_xml_decode(new, node); + xmlFreeNodeList(node); + return new; +} + + diff --git a/filter/filter-element.h b/filter/filter-element.h new file mode 100644 index 0000000000..8fe82402ee --- /dev/null +++ b/filter/filter-element.h @@ -0,0 +1,77 @@ +/* + * 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 _FILTER_ELEMENT_H +#define _FILTER_ELEMENT_H + +#include <gtk/gtk.h> +#include <gnome-xml/parser.h> + +#define FILTER_ELEMENT(obj) GTK_CHECK_CAST (obj, filter_element_get_type (), FilterElement) +#define FILTER_ELEMENT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_element_get_type (), FilterElementClass) +#define IS_FILTER_ELEMENT(obj) GTK_CHECK_TYPE (obj, filter_element_get_type ()) + +typedef struct _FilterElement FilterElement; +typedef struct _FilterElementClass FilterElementClass; + +struct _FilterElement { + GtkObject parent; + struct _FilterElementPrivate *priv; + + char *name; +}; + +struct _FilterPart; + +struct _FilterElementClass { + GtkObjectClass parent_class; + + /* virtual methods */ + void (*xml_create)(FilterElement *, xmlNodePtr); + xmlNodePtr (*xml_encode)(FilterElement *); + int (*xml_decode)(FilterElement *, xmlNodePtr); + + FilterElement *(*clone)(FilterElement *fe); + + GtkWidget *(*get_widget)(FilterElement *); + void (*build_code)(FilterElement *, GString *, struct _FilterPart *ff); + void (*format_sexp)(FilterElement *, GString *); + + /* signals */ +}; + +guint filter_element_get_type (void); +FilterElement *filter_element_new (void); + +FilterElement *filter_element_new_type_name (const char *type); + +/* methods */ +void filter_element_xml_create (FilterElement *fe, xmlNodePtr node); + +xmlNodePtr filter_element_xml_encode (FilterElement *fe); +int filter_element_xml_decode (FilterElement *fe, xmlNodePtr node); +FilterElement *filter_element_clone (FilterElement *fe); + +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-filter.c b/filter/filter-filter.c new file mode 100644 index 0000000000..9e902dbbd8 --- /dev/null +++ b/filter/filter-filter.c @@ -0,0 +1,411 @@ +/* + * 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 <gnome-xml/xmlmemory.h> + +#include "filter-filter.h" +#include "filter-context.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); + +static void filter_filter_class_init (FilterFilterClass *class); +static void filter_filter_init (FilterFilter *gspaper); +static void filter_filter_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((FilterFilter *)(x))->priv) + +struct _FilterFilterPrivate { +}; + +static FilterRuleClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +filter_filter_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "FilterFilter", + sizeof(FilterFilter), + sizeof(FilterFilterClass), + (GtkClassInitFunc)filter_filter_class_init, + (GtkObjectInitFunc)filter_filter_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(filter_rule_get_type (), &type_info); + } + + return type; +} + +static void +filter_filter_class_init (FilterFilterClass *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 = filter_filter_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; + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +filter_filter_init (FilterFilter *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); +} + +static void +unref_list(GList *l) +{ + while (l) { + gtk_object_unref((GtkObject *)l->data); + l = g_list_next(l); + } +} + +static void +filter_filter_finalise(GtkObject *obj) +{ + FilterFilter *o = (FilterFilter *)obj; + + unref_list(o->actions); + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * filter_filter_new: + * + * Create a new FilterFilter object. + * + * Return value: A new #FilterFilter object. + **/ +FilterFilter * +filter_filter_new(void) +{ + FilterFilter *o = (FilterFilter *)gtk_type_new(filter_filter_get_type ()); + return o; +} + +void filter_filter_add_action (FilterFilter *fr, FilterPart *fp) +{ + fr->actions = g_list_append(fr->actions, fp); +} + +void filter_filter_remove_action (FilterFilter *fr, FilterPart *fp) +{ + fr->actions = g_list_remove(fr->actions, fp); +} + +void filter_filter_replace_action(FilterFilter *fr, FilterPart *fp, FilterPart *new) +{ + GList *l; + + l = g_list_find(fr->actions, fp); + if (l) { + l->data = new; + } else { + fr->actions = g_list_append(fr->actions, new); + } +} + +void filter_filter_build_action (FilterFilter *fr, GString *out) +{ + g_string_append(out, "(begin\n"); + filter_part_build_code_list(fr->actions, out); + g_string_append(out, ")\n"); +} + +static xmlNodePtr xml_encode(FilterRule *fr) +{ + xmlNodePtr node, set, work; + GList *l; + FilterFilter *ff = (FilterFilter *)fr; + + node = ((FilterRuleClass *)(parent_class))->xml_encode(fr); + g_assert(node != NULL); + set = xmlNewNode(NULL, "actionset"); + xmlAddChild(node, set); + l = ff->actions; + while (l) { + work = filter_part_xml_encode((FilterPart *)l->data); + xmlAddChild(set, work); + l = g_list_next(l); + } + return node; + +} + +static void load_set(xmlNodePtr node, FilterFilter *ff, RuleContext *f) +{ + xmlNodePtr work; + char *rulename; + FilterPart *part; + + work = node->childs; + while (work) { + if (!strcmp(work->name, "part")) { + rulename = xmlGetProp(work, "name"); + part = filter_context_find_action((FilterContext *)f, rulename); + if (part) { + part = filter_part_clone(part); + filter_part_xml_decode(part, work); + filter_filter_add_action(ff, part); + } else { + g_warning("cannot find rule part '%s'\n", rulename); + } + xmlFree(rulename); + } else { + g_warning("Unknwon xml node in part: %s", work->name); + } + work = work->next; + } +} + +static int xml_decode(FilterRule *fr, xmlNodePtr node, struct _RuleContext *f) +{ + xmlNodePtr work; + FilterFilter *ff = (FilterFilter *)fr; + int result; + + result = ((FilterRuleClass *)(parent_class))->xml_decode(fr, node, f); + if (result != 0) + return result; + + work = node->childs; + while (work) { + if (!strcmp(work->name, "actionset")) { + load_set(work, ff, f); + } + work = work->next; + } + return 0; +} + +/*static void build_code(FilterRule *fr, GString *out) +{ + return ((FilterRuleClass *)(parent_class))->build_code(fr, out); +}*/ + +struct _part_data { + FilterRule *fr; + FilterContext *f; + FilterPart *part; + GtkWidget *partwidget, *container; +}; + +static void option_activate(GtkMenuItem *item, struct _part_data *data) +{ + FilterPart *part = gtk_object_get_data((GtkObject *)item, "part"); + FilterPart *newpart; + + /* 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((GtkContainer *)data->container, data->partwidget); + newpart = filter_part_clone(part); + filter_filter_replace_action((FilterFilter *)data->fr, data->part, newpart); + gtk_object_unref((GtkObject *)data->part); + data->part = newpart; + data->partwidget = filter_part_get_widget(newpart); + if (data->partwidget) + gtk_box_pack_start((GtkBox *)data->container, data->partwidget, FALSE, FALSE, 0); +} + +static GtkWidget * +get_rule_part_widget(FilterContext *f, FilterPart *newpart, FilterRule *fr) +{ + FilterPart *part = NULL; + GtkMenu *menu; + GtkMenuItem *item; + GtkOptionMenu *omenu; + GtkHBox *hbox; + GtkWidget *p; + int index=0, current=0; + struct _part_data *data; + + data = g_malloc0(sizeof(*data)); + data->fr = fr; + data->f = f; + data->part = newpart; + + hbox = (GtkHBox *)gtk_hbox_new(FALSE, 0); + p = filter_part_get_widget(newpart); + + data->partwidget = p; + data->container = (GtkWidget *)hbox; + + menu = (GtkMenu *)gtk_menu_new(); + while ((part=filter_context_next_action(f, part))) { + item = (GtkMenuItem *)gtk_menu_item_new_with_label(part->title); + gtk_object_set_data((GtkObject *)item, "part", part); + gtk_signal_connect((GtkObject *)item, "activate", option_activate, data); + gtk_menu_append(menu, (GtkWidget *)item); + gtk_widget_show((GtkWidget *)item); + if (!strcmp(newpart->title, part->title)) { + current = index; + } + index++; + } + + omenu = (GtkOptionMenu *)gtk_option_menu_new(); + gtk_option_menu_set_menu(omenu, (GtkWidget *)menu); + gtk_option_menu_set_history(omenu, current); + gtk_widget_show((GtkWidget *)omenu); + + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)omenu, FALSE, FALSE, 0); + if (p) { + gtk_box_pack_start((GtkBox *)hbox, p, FALSE, FALSE, 0); + } + gtk_widget_show_all((GtkWidget *)hbox); + + return (GtkWidget *)hbox; +} + +struct _rule_data { + FilterRule *fr; + FilterContext *f; + GtkWidget *parts; +}; + +static void +less_parts(GtkWidget *button, struct _rule_data *data) +{ + GList *l; + FilterPart *part; + GtkWidget *w; + + l = ((FilterFilter *)data->fr)->actions; + if (g_list_length(l) < 2) + return; + + /* remove the last one from the list */ + l = g_list_last(l); + part = l->data; + filter_filter_remove_action((FilterFilter *)data->fr, part); + gtk_object_unref((GtkObject *)part); + + /* and from the display */ + l = g_list_last(GTK_BOX(data->parts)->children); + w = ((GtkBoxChild *)l->data)->widget; + gtk_container_remove((GtkContainer *)data->parts, w); +} + +static void +more_parts(GtkWidget *button, struct _rule_data *data) +{ + FilterPart *new; + GtkWidget *w; + + /* create a new rule entry, use the first type of rule */ + new = filter_context_next_action((FilterContext *)data->f, NULL); + if (new) { + new = filter_part_clone(new); + filter_filter_add_action((FilterFilter *)data->fr, new); + w = get_rule_part_widget(data->f, new, data->fr); + gtk_box_pack_start((GtkBox *)data->parts, w, FALSE, FALSE, 0); + } +} + +static GtkWidget *get_widget(FilterRule *fr, struct _RuleContext *f) +{ + GtkWidget *widget; + GtkVBox *parts, *inframe; + GtkHBox *hbox; + GtkWidget *w; + GtkFrame *frame; + GList *l; + FilterPart *part; + struct _rule_data *data; + FilterFilter *ff = (FilterFilter *)fr; + + d(printf("filter filter.get widget\n")); + + widget = ((FilterRuleClass *)(parent_class))->get_widget(fr, f); + + /* and now for the action area */ + frame = (GtkFrame *)gtk_frame_new("Perform actions"); + inframe = (GtkVBox *)gtk_vbox_new(FALSE, 3); + gtk_container_add((GtkContainer *)frame, (GtkWidget *)inframe); + + parts = (GtkVBox *)gtk_vbox_new(FALSE, 3); + data = g_malloc0(sizeof(*data)); + data->f = (FilterContext *)f; + data->fr = fr; + data->parts = (GtkWidget *)parts; + + l = ff->actions; + while (l) { + part = l->data; + d(printf("adding action %s\n", part->title)); + w = get_rule_part_widget((FilterContext *)f, part, fr); + gtk_box_pack_start((GtkBox *)parts, (GtkWidget *)w, FALSE, FALSE, 3); + l = g_list_next(l); + } + gtk_box_pack_start((GtkBox *)inframe, (GtkWidget *)parts, FALSE, FALSE, 3); + + hbox = (GtkHBox *)gtk_hbox_new(FALSE, 3); + w = gtk_button_new_with_label("Less"); + gtk_signal_connect((GtkObject *)w, "clicked", less_parts, data); + gtk_box_pack_end((GtkBox *)hbox, (GtkWidget *)w, FALSE, FALSE, 0); + w = gtk_button_new_with_label("More"); + gtk_signal_connect((GtkObject *)w, "clicked", more_parts, data); + gtk_box_pack_end((GtkBox *)hbox, (GtkWidget *)w, FALSE, FALSE, 0); + gtk_box_pack_start((GtkBox *)inframe, (GtkWidget *)hbox, FALSE, FALSE, 3); + + gtk_widget_show_all((GtkWidget *)frame); + + gtk_box_pack_start((GtkBox *)widget, (GtkWidget *)frame, FALSE, FALSE, 3); + + return widget; +} + diff --git a/filter/filter-filter.h b/filter/filter-filter.h new file mode 100644 index 0000000000..944aba42ae --- /dev/null +++ b/filter/filter-filter.h @@ -0,0 +1,60 @@ +/* + * 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 _FILTER_FILTER_H +#define _FILTER_FILTER_H + +#include <gtk/gtk.h> +#include "filter-rule.h" + +#define FILTER_FILTER(obj) GTK_CHECK_CAST (obj, filter_filter_get_type (), FilterFilter) +#define FILTER_FILTER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_filter_get_type (), FilterFilterClass) +#define IS_FILTER_FILTER(obj) GTK_CHECK_TYPE (obj, filter_filter_get_type ()) + +typedef struct _FilterFilter FilterFilter; +typedef struct _FilterFilterClass FilterFilterClass; + +struct _FilterFilter { + FilterRule parent; + struct _FilterFilterPrivate *priv; + + GList *actions; +}; + +struct _FilterFilterClass { + FilterRuleClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint filter_filter_get_type (void); +FilterFilter *filter_filter_new (void); + +/* methods */ +void filter_filter_add_action (FilterFilter *fr, FilterPart *fp); +void filter_filter_remove_action (FilterFilter *fr, FilterPart *fp); +void filter_filter_replace_action (FilterFilter *fr, FilterPart *fp, FilterPart *new); + +void filter_filter_build_action (FilterFilter *fr, GString *out); + +#endif /* ! _FILTER_FILTER_H */ + diff --git a/filter/filter-folder.c b/filter/filter-folder.c new file mode 100644 index 0000000000..fa3fe913ae --- /dev/null +++ b/filter/filter-folder.c @@ -0,0 +1,269 @@ +/* + * 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> + +#define SHELL + +#include "filter-folder.h" +#ifdef SHELL +#include "shell/evolution-shell-client.h" +#endif +#include "e-util/e-sexp.h" + +#define d(x) + +static void xml_create(FilterElement *fe, xmlNodePtr node); +static xmlNodePtr xml_encode(FilterElement *fe); +static int xml_decode(FilterElement *fe, xmlNodePtr node); +static GtkWidget *get_widget(FilterElement *fe); +static void build_code(FilterElement *fe, GString *out, struct _FilterPart *ff); +static void format_sexp(FilterElement *, GString *); + +#ifdef SHELL +extern EvolutionShellClient *global_shell_client; +#endif + +static void filter_folder_class_init (FilterFolderClass *class); +static void filter_folder_init (FilterFolder *gspaper); +static void filter_folder_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((FilterFolder *)(x))->priv) + +struct _FilterFolderPrivate { +}; + +static FilterElementClass *parent_class; + +guint +filter_folder_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "FilterFolder", + sizeof(FilterFolder), + sizeof(FilterFolderClass), + (GtkClassInitFunc)filter_folder_class_init, + (GtkObjectInitFunc)filter_folder_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(filter_element_get_type (), &type_info); + } + + return type; +} + +static void +filter_folder_class_init (FilterFolderClass *class) +{ + GtkObjectClass *object_class; + FilterElementClass *filter_element = (FilterElementClass *)class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(filter_element_get_type ()); + + object_class->finalize = filter_folder_finalise; + + /* override methods */ + filter_element->xml_create = xml_create; + filter_element->xml_encode = xml_encode; + filter_element->xml_decode = xml_decode; + filter_element->get_widget = get_widget; + filter_element->build_code = build_code; + filter_element->format_sexp = format_sexp; +} + +static void +filter_folder_init (FilterFolder *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); +} + +static void +filter_folder_finalise(GtkObject *obj) +{ + FilterFolder *o = (FilterFolder *)obj; + + g_free(o->uri); + g_free(o->name); + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * filter_folder_new: + * + * Create a new FilterFolder object. + * + * Return value: A new #FilterFolder object. + **/ +FilterFolder * +filter_folder_new(void) +{ + FilterFolder *o = (FilterFolder *)gtk_type_new(filter_folder_get_type ()); + return o; +} + +static void xml_create(FilterElement *fe, xmlNodePtr node) +{ + /* parent implementation */ + ((FilterElementClass *)(parent_class))->xml_create(fe, node); +} + +static xmlNodePtr xml_encode(FilterElement *fe) +{ + xmlNodePtr value, work; + FilterFolder *ff = (FilterFolder *)fe; + + d(printf("Encoding folder as xml\n")); + + value = xmlNewNode(NULL, "value"); + xmlSetProp(value, "name", fe->name); + xmlSetProp(value, "type", "folder"); + + work = xmlNewChild(value, NULL, "folder", NULL); + xmlSetProp(work, "name", ff->name); + xmlSetProp(work, "uri", ff->uri); + + return value; +} + +static int xml_decode(FilterElement *fe, xmlNodePtr node) +{ + FilterFolder *ff = (FilterFolder *)fe; + xmlNodePtr n; + + d(printf("Decoding folder from xml %p\n", fe)); + + fe->name = xmlGetProp(node, "name"); + + n = node->childs; + while (n) { + if (!strcmp(n->name, "folder")) { + ff->name = xmlGetProp(n, "name"); + ff->uri = xmlGetProp(n, "uri"); + break; + } + n = n->next; + } + return 0; +} + +static void button_clicked(GtkButton *button, FilterFolder *ff) +{ +#ifdef SHELL + const char *allowed_types[] = { "mail", NULL }; + char *def, *uri, *str; + + def = ff->uri?ff->uri:""; + evolution_shell_client_user_select_folder (global_shell_client, + _("Select Folder"), + def, allowed_types, NULL, &uri); + + if (uri != NULL && uri[0] != '\0') { + g_free(ff->uri); + g_free(ff->name); + ff->uri = uri; + + str = strstr(uri, "//"); + if (str) + str = strchr(str+2, '/'); + if (str) + str++; + else + str = uri; + + ff->name = g_strdup(str); + gtk_label_set_text(GTK_BIN(button)->child, ff->name); + } else { + g_free(uri); + } +#else + GnomeDialog *gd; + GtkEntry *entry; + char *uri, *str; + + gd = (GnomeDialog *)gnome_dialog_new("Enter folder URI", "Ok", "Cancel", 0); + entry = (GtkEntry *)gtk_entry_new(); + if (ff->uri) { + gtk_entry_set_text(entry, ff->uri); + } + gtk_box_pack_start((GtkBox *)gd->vbox, (GtkWidget *)entry, TRUE, TRUE, 3); + gtk_widget_show((GtkWidget *)entry); + switch (gnome_dialog_run(gd)) { + case 0: + g_free(ff->uri); + g_free(ff->name); + uri = gtk_entry_get_text(entry); + ff->uri = g_strdup(uri); + str = strstr(uri, "//"); + if (str) + str = strchr(str+2, '/'); + if (str) + str++; + else + str = uri; + ff->name = g_strdup(str); + gtk_label_set_text((GtkLabel *)GTK_BIN(button)->child, ff->name); + case 1: + gnome_dialog_close(gd); + case -1: + /* nothing */ + } + +#endif +} + +static GtkWidget *get_widget(FilterElement *fe) +{ + FilterFolder *ff = (FilterFolder *)fe; + GtkButton *button; + GtkLabel *label; + char *name; + + if (ff->name && ff->name[0]) + name = ff->name; + else + name = "<click to select folder>"; + label = (GtkLabel *)gtk_label_new(name); + button = (GtkButton *)gtk_button_new(); + gtk_container_add((GtkContainer *)button, (GtkWidget *)label); + gtk_widget_show((GtkWidget *)button); + gtk_widget_show((GtkWidget *)label); + gtk_signal_connect((GtkObject *)button, "clicked", button_clicked, ff); + return (GtkWidget *)button; +} + +static void build_code(FilterElement *fe, GString *out, struct _FilterPart *ff) +{ + return; +} + +static void format_sexp(FilterElement *fe, GString *out) +{ + FilterFolder *ff = (FilterFolder *)fe; + + e_sexp_encode_string(out, ff->uri); +} diff --git a/filter/filter-folder.h b/filter/filter-folder.h new file mode 100644 index 0000000000..ee52d7037b --- /dev/null +++ b/filter/filter-folder.h @@ -0,0 +1,56 @@ +/* + * 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 _FILTER_FOLDER_H +#define _FILTER_FOLDER_H + +#include <gtk/gtk.h> +#include "filter-element.h" + +#define FILTER_FOLDER(obj) GTK_CHECK_CAST (obj, filter_folder_get_type (), FilterFolder) +#define FILTER_FOLDER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_folder_get_type (), FilterFolderClass) +#define IS_FILTER_FOLDER(obj) GTK_CHECK_TYPE (obj, filter_folder_get_type ()) + +typedef struct _FilterFolder FilterFolder; +typedef struct _FilterFolderClass FilterFolderClass; + +struct _FilterFolder { + FilterElement parent; + struct _FilterFolderPrivate *priv; + + char *uri; + char *name; /* name of folder for display? */ +}; + +struct _FilterFolderClass { + FilterElementClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint filter_folder_get_type (void); +FilterFolder *filter_folder_new (void); + +/* methods */ + +#endif /* ! _FILTER_FOLDER_H */ + diff --git a/filter/filter-format.c b/filter/filter-format.c deleted file mode 100644 index 7f8f388ef5..0000000000 --- a/filter/filter-format.c +++ /dev/null @@ -1,196 +0,0 @@ -/* -*- Mode: C; c-file-style: "linux"; indent-tabs-mode: t; c-basic-offset: 8; -*- */ - -#include <glib.h> -#include <gtk/gtk.h> -#include <gnome.h> -#include <gtkhtml/gtkhtml.h> - -#include <gnome-xml/tree.h> -#include <gnome-xml/parser.h> - -#include "filter-arg-types.h" -#include "filter-xml.h" - -#define d(x) - -struct description_decode_lambda { - GString *str; - GList *args; - GtkHTML *html; - GtkHTMLStream *stream; -}; - -static char * -arg_text(FilterArg *arg) -{ - char *out = NULL; - GList *value; - GString *str; - - value = arg->values; - - d(printf("getting text from arg %s\n", arg->name)); - - if (value == NULL) - return NULL; - - str = g_string_new(""); - filter_arg_write_text(arg, str); - out = str->str; - g_string_free(str, FALSE); - return out; -} - -static void -description_decode_text(struct filter_desc *d, struct description_decode_lambda *l) -{ - GList *list; - char *txt; - - switch (d->type) { - case FILTER_XML_TEXT: - case FILTER_XML_DESC: - dotext: - d(printf("appending '%s'\n", d->data)); - /* printf("vartype = %s\n", detokenise(d->vartype)); */ - d(printf("varname = %s\n", d->varname)); - if (d->vartype !=-1 && d->varname - && (list = g_list_find_custom(l->args, d->varname, (GCompareFunc) filter_find_arg)) - && (txt = arg_text(list->data))) { - } else { - txt = d->data; - } - g_string_append(l->str, txt); - break; - default: - printf("WARN: unknown desc text type '%d' = %s\n", d->type, d->data); - goto dotext; - } -} - -char * -filter_description_text(GList *description, GList *args) -{ - char *txt; - struct description_decode_lambda l; - - d(printf("\ndecoding ...\n")); - - l.str = g_string_new(""); - l.args = args; - g_list_foreach(description, (GFunc) description_decode_text, &l); - - d(printf("string is '%s'\n", l.str->str)); - - txt = l.str->str; - g_string_free(l.str, FALSE); - - return txt; -} - -static void -html_write(GtkHTML *html, GtkHTMLStream *stream, char *s) -{ - d(printf("appending html '%s'\n", s)); - gtk_html_write(html, stream, s, strlen(s)); -} - - -static void -description_decode_html(struct filter_desc *d, struct description_decode_lambda *l) -{ - GList *list; - char *txt, *end; - int free; - - switch (d->type) { - case FILTER_XML_TEXT: - case FILTER_XML_DESC: - dotext: - d(printf("appending '%s'\n", d->data)); - /*printf("vartype = %s\n", detokenise(d->vartype));*/ - d(printf("varname = %s\n", d->varname)); - free = FALSE; - if (d->vartype !=-1 && d->varname) { - char *link; - list = g_list_find_custom(l->args, d->varname, (GCompareFunc) filter_find_arg); - end = "</a>"; - if (list) { - txt = arg_text(list->data); - if (txt == NULL) - txt = d->data; - else - free = TRUE; - link = g_strdup_printf("<a href=\"arg:%p %p\">", d, list->data); - } else { - printf("cannot find arg '%s'\n", d->varname); - link = g_strdup_printf("<a href=\"arg:%p %p\">", d, NULL); - txt = d->data; - } - html_write(l->html, l->stream, link); - g_free(link); - } else { - txt = d->data; - end = NULL; - } - html_write(l->html, l->stream, txt); - if (end) { - html_write(l->html, l->stream, end); - } - if (free) - g_free(txt); - break; - default: - /*printf("WARN: unknown desc text type '%s' = %s\n", detokenise(d->type), d->data);*/ - goto dotext; - } -} - -void -filter_description_html_write(GList *description, GList *args, GtkHTML *html, GtkHTMLStream *stream) -{ - struct description_decode_lambda l; - - d(printf("\ndecoding ...\n")); - - l.str = NULL; - l.args = args; - l.html = html; - l.stream = stream; - g_list_foreach(description, (GFunc) description_decode_html, &l); -} - -#ifdef TESTER -int main(int argc, char **argv) -{ - GList *rules, *options; - xmlDocPtr doc, out, optionset, filteroptions; - - gnome_init("Test", "0.0", argc, argv); - - doc = xmlParseFile("filterdescription.xml"); - - rules = load_ruleset(doc); - options = load_optionset(doc, rules); - - out = xmlParseFile("saveoptions.xml"); - options = load_optionset(doc, rules); - - while (options) { - printf("applying a rule ...\n"); - filterme(options->data); - options = g_list_next(options); - } - -#if 0 - out = xmlNewDoc("1.0"); - optionset = save_optionset(out, options); - filteroptions = xmlNewDocNode(out, NULL, "filteroptions", NULL); - xmlAddChild(filteroptions, optionset); - xmlDocSetRootElement(out, filteroptions); - xmlSaveFile("saveoptions.xml", out); -#endif - return 0; -} -#endif - diff --git a/filter/filter-format.h b/filter/filter-format.h deleted file mode 100644 index 82c5d9fb13..0000000000 --- a/filter/filter-format.h +++ /dev/null @@ -1,11 +0,0 @@ - -#ifndef _FILTER_FORMAT_H -#define _FILTER_FORMAT_H - -#include <glib.h> - -char *filter_description_text(GList *description, GList *args); -void filter_description_html_write(GList *description, GList *args, - GtkHTML *html, GtkHTMLStream *stream); - -#endif /* _FILTER_FORMAT_H */ diff --git a/filter/filter-input.c b/filter/filter-input.c new file mode 100644 index 0000000000..eca5afd2ff --- /dev/null +++ b/filter/filter-input.c @@ -0,0 +1,246 @@ +/* + * 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 "filter-input.h" +#include "e-util/e-sexp.h" + +#define d(x) + +static void xml_create(FilterElement *fe, xmlNodePtr node); +static xmlNodePtr xml_encode(FilterElement *fe); +static int xml_decode(FilterElement *fe, xmlNodePtr node); +static GtkWidget *get_widget(FilterElement *fe); +static void build_code(FilterElement *fe, GString *out, struct _FilterPart *ff); +static void format_sexp(FilterElement *, GString *); + +static void filter_input_class_init (FilterInputClass *class); +static void filter_input_init (FilterInput *gspaper); +static void filter_input_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((FilterInput *)(x))->priv) + +struct _FilterInputPrivate { +}; + +static FilterElementClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +filter_input_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "FilterInput", + sizeof(FilterInput), + sizeof(FilterInputClass), + (GtkClassInitFunc)filter_input_class_init, + (GtkObjectInitFunc)filter_input_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(filter_element_get_type (), &type_info); + } + + return type; +} + +static void +filter_input_class_init (FilterInputClass *class) +{ + GtkObjectClass *object_class; + FilterElementClass *filter_element = (FilterElementClass *)class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(filter_element_get_type ()); + + object_class->finalize = filter_input_finalise; + + /* override methods */ + filter_element->xml_create = xml_create; + filter_element->xml_encode = xml_encode; + filter_element->xml_decode = xml_decode; + filter_element->get_widget = get_widget; + filter_element->build_code = build_code; + filter_element->format_sexp = format_sexp; + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +filter_input_init (FilterInput *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); +} + +static void +filter_input_finalise(GtkObject *obj) +{ + FilterInput *o = (FilterInput *)obj; + + o = o; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * filter_input_new: + * + * Create a new FilterInput object. + * + * Return value: A new #FilterInput object. + **/ +FilterInput * +filter_input_new(void) +{ + FilterInput *o = (FilterInput *)gtk_type_new(filter_input_get_type ()); + return o; +} + +FilterInput *filter_input_new_type_name (const char *type) +{ + FilterInput *o = filter_input_new(); + o->type = g_strdup(type); + + d(printf("new type %s = %p\n", type, o)); + return o; +} + +static void xml_create(FilterElement *fe, xmlNodePtr node) +{ + /* parent implementation */ + ((FilterElementClass *)(parent_class))->xml_create(fe, node); + +} + +static xmlNodePtr xml_encode(FilterElement *fe) +{ + xmlNodePtr value; + GList *l; + FilterInput *fi = (FilterInput *)fe; + char *type; + + type = fi->type?fi->type:"string"; + + d(printf("Encoding %s as xml\n", type)); + + value = xmlNewNode(NULL, "value"); + xmlSetProp(value, "name", fe->name); + xmlSetProp(value, "type", type); + l = fi->values; + while (l) { + xmlNodePtr cur; + char *str = l->data; + + cur = xmlNewChild(value, NULL, type, NULL); + xmlNodeSetContent(cur, str); + l = g_list_next(l); + } + return value; +} + +static int xml_decode(FilterElement *fe, xmlNodePtr node) +{ + FilterInput *fi = (FilterInput *)fe; + char *name, *str, *type; + xmlNodePtr n; + + type = fi->type?fi->type:"string"; + + d(printf("Decoding %s from xml %p\n", type, fe)); + + name = xmlGetProp(node, "name"); + d(printf("Name = %s\n", name)); + fe->name = name; + fi->type = xmlGetProp(node, "type"); + n = node->childs; + while (n) { + if (!strcmp(n->name, type)) { + str = xmlNodeGetContent(n); + d(printf(" '%s'\n", str)); + fi->values = g_list_append(fi->values, str); + } else { + 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) +{ + char *new; + FilterInput *fi = (FilterInput *)fe; + GList *l; + + new = gtk_entry_get_text(entry); + + /* NOTE: entry only supports a single 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(new)); +} + +static GtkWidget *get_widget(FilterElement *fe) +{ + GtkEntry *entry; + FilterInput *fi = (FilterInput *)fe; + + entry = (GtkEntry *)gtk_entry_new(); + if (fi->values && fi->values->data) { + gtk_entry_set_text(entry, fi->values->data); + } + gtk_signal_connect((GtkObject *)entry, "changed", entry_changed, fe); + return (GtkWidget *)entry; +} + +static void build_code(FilterElement *fe, GString *out, struct _FilterPart *ff) +{ + return; +} + +static void format_sexp(FilterElement *fe, GString *out) +{ + GList *l; + FilterInput *fi = (FilterInput *)fe; + + l = fi->values; + while (l) { + e_sexp_encode_string(out, l->data); + l = g_list_next(l); + } +} diff --git a/filter/filter-input.h b/filter/filter-input.h new file mode 100644 index 0000000000..0ce43d980d --- /dev/null +++ b/filter/filter-input.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 _FILTER_INPUT_H +#define _FILTER_INPUT_H + +#include <gtk/gtk.h> +#include "filter-element.h" + +#define FILTER_INPUT(obj) GTK_CHECK_CAST (obj, filter_input_get_type (), FilterInput) +#define FILTER_INPUT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_input_get_type (), FilterInputClass) +#define IS_FILTER_INPUT(obj) GTK_CHECK_TYPE (obj, filter_input_get_type ()) + +typedef struct _FilterInput FilterInput; +typedef struct _FilterInputClass FilterInputClass; + +struct _FilterInput { + FilterElement parent; + struct _FilterInputPrivate *priv; + + char *type; /* name of type */ + GList *values; /* strings */ +}; + +struct _FilterInputClass { + FilterElementClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint filter_input_get_type (void); +FilterInput *filter_input_new (void); + +FilterInput *filter_input_new_type_name (const char *type); + +/* methods */ +void filter_input_set_value(FilterInput *fi, const char *value); + +#endif /* ! _FILTER_INPUT_H */ + diff --git a/filter/filter-option.c b/filter/filter-option.c new file mode 100644 index 0000000000..31be216f25 --- /dev/null +++ b/filter/filter-option.c @@ -0,0 +1,304 @@ +/* + * 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 <gnome-xml/xmlmemory.h> + +#include "filter-option.h" +#include "filter-part.h" +#include "e-util/e-sexp.h" + +#define d(x) + +static void xml_create(FilterElement *fe, xmlNodePtr node); +static xmlNodePtr xml_encode(FilterElement *fe); +static int 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 void filter_option_class_init (FilterOptionClass *class); +static void filter_option_init (FilterOption *gspaper); +static void filter_option_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((FilterOption *)(x))->priv) + +struct _FilterOptionPrivate { +}; + +static FilterElementClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +filter_option_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "FilterOption", + sizeof(FilterOption), + sizeof(FilterOptionClass), + (GtkClassInitFunc)filter_option_class_init, + (GtkObjectInitFunc)filter_option_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(filter_element_get_type (), &type_info); + } + + return type; +} + +static void +filter_option_class_init (FilterOptionClass *class) +{ + GtkObjectClass *object_class; + FilterElementClass *filter_element = (FilterElementClass *)class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(filter_element_get_type ()); + + object_class->finalize = filter_option_finalise; + + /* override methods */ + filter_element->xml_create = xml_create; + filter_element->xml_encode = xml_encode; + filter_element->xml_decode = xml_decode; + filter_element->clone = clone; + filter_element->get_widget = get_widget; + filter_element->build_code = build_code; + filter_element->format_sexp = format_sexp; + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +filter_option_init (FilterOption *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); +} + +static void +filter_option_finalise(GtkObject *obj) +{ + FilterOption *o = (FilterOption *)obj; + + o = o; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * filter_option_new: + * + * Create a new FilterOption object. + * + * Return value: A new #FilterOption object. + **/ +FilterOption * +filter_option_new(void) +{ + FilterOption *o = (FilterOption *)gtk_type_new(filter_option_get_type ()); + return o; +} + +static struct _filter_option * +find_option(FilterOption *fo, const char *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; +} + +static void xml_create(FilterElement *fe, xmlNodePtr node) +{ + FilterOption *fo = (FilterOption *)fe; + xmlNodePtr n, work; + struct _filter_option *op; + + /* parent implementation */ + ((FilterElementClass *)(parent_class))->xml_create(fe, node); + + n = node->childs; + while (n) { + if (!strcmp(n->name, "option")) { + op = g_malloc0(sizeof(*op)); + op->value = xmlGetProp(n, "value"); + work = n->childs; + while (work) { + if (!strcmp(work->name, "title")) { + if (!op->title) { + op->title = xmlNodeGetContent(work); + } + } else if (!strcmp(work->name, "code")) { + if (!op->code) { + op->code = xmlNodeGetContent(work); + } + } + work = work->next; + } + d(printf("creating new option:\n title %s\n value %s\n code %s\n", op->title, op->value, op->code)); + fo->options = g_list_append(fo->options, op); + if (fo->current == NULL) + fo->current = op; + } else { + 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, "value"); + xmlSetProp(value, "name", fe->name); + xmlSetProp(value, "type", "option"); + if (fo->current) { + xmlSetProp(value, "value", fo->current->value); + } + return value; +} + +static int xml_decode(FilterElement *fe, xmlNodePtr node) +{ + FilterOption *fo = (FilterOption *)fe; + char *value; + + d(printf("Decoding option from xml\n")); + fe->name = xmlGetProp(node, "name"); + value = xmlGetProp(node, "value"); + if (value) { + fo->current = find_option(fo, value); + xmlFree(value); + } else { + fo->current = NULL; + } + return 0; +} + +static void option_activate(GtkMenuItem *item, FilterOption *fo) +{ + fo->current = gtk_object_get_data((GtkObject *)item, "option"); + d(printf("option changed to %s\n", fo->current->title)); +} + +static GtkWidget *get_widget(FilterElement *fe) +{ + FilterOption *fo = (FilterOption *)fe; + GtkMenu *menu; + GtkOptionMenu *omenu; + GtkMenuItem *item; + GList *l = fo->options; + struct _filter_option *op; + int index = 0, current=0; + + menu = (GtkMenu *)gtk_menu_new(); + while (l) { + op = l->data; + item = (GtkMenuItem *)gtk_menu_item_new_with_label(op->title); + gtk_object_set_data((GtkObject *)item, "option", op); + gtk_signal_connect((GtkObject *)item, "activate", option_activate, fo); + gtk_menu_append(menu, (GtkWidget *)item); + gtk_widget_show((GtkWidget *)item); + if (op == fo->current) { + current = index; + } + l = g_list_next(l); + index++; + } + + omenu = (GtkOptionMenu *)gtk_option_menu_new(); + gtk_option_menu_set_menu(omenu, (GtkWidget *)menu); + gtk_option_menu_set_history(omenu, current); + + return (GtkWidget *)omenu; +} + +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) { + 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 *fn, *op; + + d(printf("cloning option\n")); + + new = FILTER_OPTION(((FilterElementClass *)(parent_class))->clone(fe)); + l = fo->options; + while (l) { + op = l->data; + fn = g_malloc(sizeof(*fn)); + d(printf(" option %s\n", op->title)); + fn->title = g_strdup(op->title); + fn->value = g_strdup(op->value); + fn->code = g_strdup(op->code); + new->options = g_list_append(new->options, fn); + l = g_list_next(l); + + if (new->current == NULL) + new->current = fn; + } + + 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 new file mode 100644 index 0000000000..1645b333a1 --- /dev/null +++ b/filter/filter-option.h @@ -0,0 +1,63 @@ +/* + * 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 _FILTER_OPTION_H +#define _FILTER_OPTION_H + +#include <gtk/gtk.h> + +#include "filter-element.h" + +#define FILTER_OPTION(obj) GTK_CHECK_CAST (obj, filter_option_get_type (), FilterOption) +#define FILTER_OPTION_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_option_get_type (), FilterOptionClass) +#define IS_FILTER_OPTION(obj) GTK_CHECK_TYPE (obj, filter_option_get_type ()) + +typedef struct _FilterOption FilterOption; +typedef struct _FilterOptionClass FilterOptionClass; + +struct _filter_option { + char *title; /* button title */ + char *value; /* value, if it has one */ + char *code; /* used to string code segments together */ +}; + +struct _FilterOption { + FilterElement parent; + struct _FilterOptionPrivate *priv; + + GList *options; + struct _filter_option *current; +}; + +struct _FilterOptionClass { + FilterElementClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint filter_option_get_type (void); +FilterOption *filter_option_new (void); + +/* methods */ + +#endif /* ! _FILTER_OPTION_H */ + diff --git a/filter/filter-part.c b/filter/filter-part.c new file mode 100644 index 0000000000..b38cc8e20f --- /dev/null +++ b/filter/filter-part.c @@ -0,0 +1,432 @@ +/* + * 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 <gnome-xml/xmlmemory.h> + +#include "filter-part.h" +#include "filter-element.h" + +#define d(x) + +static void filter_part_class_init (FilterPartClass *class); +static void filter_part_init (FilterPart *gspaper); +static void filter_part_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((FilterPart *)(x))->priv) + +struct _FilterPartPrivate { +}; + +static GtkObjectClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +filter_part_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "FilterPart", + sizeof(FilterPart), + sizeof(FilterPartClass), + (GtkClassInitFunc)filter_part_class_init, + (GtkObjectInitFunc)filter_part_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(gtk_object_get_type (), &type_info); + } + + return type; +} + +static void +filter_part_class_init (FilterPartClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(gtk_object_get_type ()); + + object_class->finalize = filter_part_finalise; + /* override methods */ + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +filter_part_init (FilterPart *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); +} + +static void +filter_part_finalise(GtkObject *obj) +{ + FilterPart *o = (FilterPart *)obj; + + o = o; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * filter_part_new: + * + * Create a new FilterPart object. + * + * Return value: A new #FilterPart object. + **/ +FilterPart * +filter_part_new(void) +{ + FilterPart *o = (FilterPart *)gtk_type_new(filter_part_get_type ()); + return o; +} + + + +int filter_part_xml_create (FilterPart *ff, xmlNodePtr node) +{ + xmlNodePtr n; + char *type; + FilterElement *el; + + ff->name = xmlGetProp(node, "name"); + n = node->childs; + while (n) { + if (!strcmp(n->name, "input")) { + type = xmlGetProp(n, "type"); + d(printf("creating new element type input '%s'\n", type)); + if (type != NULL + && (el = filter_element_new_type_name(type)) != NULL) { + filter_element_xml_create(el, n); + xmlFree(type); + d(printf("adding element part %p %s\n", el, el->name)); + ff->elements = g_list_append(ff->elements, el); + } else { + g_warning("Invalid xml format, missing/unknown input type"); + } + } else if (!strcmp(n->name, "title")) { + if (!ff->title) + ff->title = xmlNodeGetContent(n); + } else if (!strcmp(n->name, "code")) { + if (!ff->code) + ff->code = xmlNodeGetContent(n); + } else { + g_warning("Unknwon 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, "part"); + xmlSetProp(part, "name", 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; +} + +int filter_part_xml_decode (FilterPart *fp, xmlNodePtr node) +{ + FilterElement *fe; + xmlNodePtr n; + char *name; + + g_return_val_if_fail(fp != NULL, -1); + g_return_val_if_fail(node != NULL, -1); + + n = node->childs; + while (n) { + if (!strcmp(n->name, "value")) { + name = xmlGetProp(n, "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 *)gtk_type_new( ((GtkObject *)fp)->klass->type ); + 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; +} + +FilterElement *filter_part_find_element(FilterPart *ff, const char *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) +{ + GtkHBox *hbox; + GList *l = ff->elements; + FilterElement *fe; + GtkWidget *w; + + hbox = (GtkHBox *)gtk_hbox_new(FALSE, 3); + + while (l) { + fe = l->data; + w = filter_element_get_widget(fe); + if (w) { + gtk_box_pack_start((GtkBox *)hbox, w, FALSE, FALSE, 3); + } + l = g_list_next(l); + } + gtk_widget_show_all((GtkWidget *)hbox); + return (GtkWidget *)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 = g_list_next(l); + } +} + +/** + * 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 = g_list_next(l); + } +} + +/** + * filter_part_find_list: + * @l: + * @name: + * + * Find a filter part stored in a list. + * + * Return value: + **/ +FilterPart *filter_part_find_list (GList *l, const char *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 = g_list_next(l); + } + 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 = g_list_next(node); + } + 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 char *source, GString *out) +{ + const char *newstart, *start, *end; + char *name=alloca(32); + int len, namelen=32; + FilterElement *fe; + + start = source; + while ( (newstart = strstr(start, "${")) + && (end = strstr(newstart+2, "}")) ) { + len = end-newstart-2; + if (len+1>namelen) { + namelen = (len+1)*2; + name = 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", name, fe)); + if (fe) { + g_string_sprintfa(out, "%.*s", newstart-start, start); + filter_element_format_sexp(fe, out); +#if 0 + } else if ( (val = g_hash_table_lookup(ff->globals, name)) ) { + g_string_sprintfa(out, "%.*s", newstart-start, start); + e_sexp_encode_string(out, val); +#endif + } else { + g_string_sprintfa(out, "%.*s", end-start+1, start); + } + start = end+1; + } + g_string_append(out, start); +} + +#if 0 +int main(int argc, char **argv) +{ + xmlDocPtr system; + FilterPart *ff; + GtkWidget *w; + GnomeDialog *gd; + xmlNodePtr node; + 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); + + gd = (GnomeDialog *)gnome_dialog_new("Test", "Ok", NULL); + gtk_box_pack_start((GtkBox *)gd->vbox, w, FALSE, TRUE, 0); + gtk_widget_show((GtkWidget *)gd); + + gnome_dialog_run_and_close(gd); + + 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 new file mode 100644 index 0000000000..2995046b20 --- /dev/null +++ b/filter/filter-part.h @@ -0,0 +1,75 @@ +/* + * 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 _FILTER_PART_H +#define _FILTER_PART_H + +#include <gtk/gtk.h> +#include "filter-input.h" + +#define FILTER_PART(obj) GTK_CHECK_CAST (obj, filter_part_get_type (), FilterPart) +#define FILTER_PART_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_part_get_type (), FilterPartClass) +#define IS_FILTER_PART(obj) GTK_CHECK_TYPE (obj, filter_part_get_type ()) + +typedef struct _FilterPart FilterPart; +typedef struct _FilterPartClass FilterPartClass; + +struct _FilterPart { + GtkObject parent; + struct _FilterPartPrivate *priv; + + char *name; + char *title; + char *code; + GList *elements; +}; + +struct _FilterPartClass { + GtkObjectClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint filter_part_get_type (void); +FilterPart *filter_part_new (void); + +/* methods */ +int filter_part_xml_create (FilterPart *ff, xmlNodePtr node); + +xmlNodePtr filter_part_xml_encode (FilterPart *fe); +int filter_part_xml_decode (FilterPart *fe, xmlNodePtr node); + +FilterPart *filter_part_clone (FilterPart *fp); + +FilterElement *filter_part_find_element(FilterPart *ff, const char *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 char *str, GString *out); + +/* static functions */ +void filter_part_build_code_list (GList *l, GString *out); +FilterPart *filter_part_find_list (GList *l, const char *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 new file mode 100644 index 0000000000..9e1da43164 --- /dev/null +++ b/filter/filter-rule.c @@ -0,0 +1,525 @@ +/* + * 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 <gnome-xml/xmlmemory.h> + +#include "filter-rule.h" +#include "filter-context.h" + +#define d(x) + +static xmlNodePtr xml_encode(FilterRule *); +static int xml_decode(FilterRule *, xmlNodePtr, RuleContext *); +static void build_code(FilterRule *, GString *out); +static GtkWidget *get_widget(FilterRule *fr, struct _RuleContext *f); + +static void filter_rule_class_init (FilterRuleClass *class); +static void filter_rule_init (FilterRule *gspaper); +static void filter_rule_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((FilterRule *)(x))->priv) + +struct _FilterRulePrivate { + GtkWidget *parts; /* where the parts are stored */ +}; + +static GtkObjectClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +filter_rule_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "FilterRule", + sizeof(FilterRule), + sizeof(FilterRuleClass), + (GtkClassInitFunc)filter_rule_class_init, + (GtkObjectInitFunc)filter_rule_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(gtk_object_get_type (), &type_info); + } + + return type; +} + +static void +filter_rule_class_init (FilterRuleClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(gtk_object_get_type ()); + + object_class->finalize = filter_rule_finalise; + + /* override methods */ + class->xml_encode = xml_encode; + class->xml_decode = xml_decode; + class->build_code = build_code; + class->get_widget = get_widget; + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +filter_rule_init (FilterRule *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); +} + +static void +unref_list(GList *l) +{ + while (l) { + gtk_object_unref((GtkObject *)l->data); + l = g_list_next(l); + } +} + +static void +filter_rule_finalise(GtkObject *obj) +{ + FilterRule *o = (FilterRule *)obj; + + g_free(o->name); + unref_list(o->parts); + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * filter_rule_new: + * + * Create a new FilterRule object. + * + * Return value: A new #FilterRule object. + **/ +FilterRule * +filter_rule_new(void) +{ + FilterRule *o = (FilterRule *)gtk_type_new(filter_rule_get_type ()); + return o; +} + +xmlNodePtr filter_rule_xml_encode (FilterRule *fr) +{ + return ((FilterRuleClass *)((GtkObject *)fr)->klass)->xml_encode(fr); +} + +static xmlNodePtr xml_encode(FilterRule *fr) +{ + xmlNodePtr node, set, work; + GList *l; + + node = xmlNewNode(NULL, "rule"); + switch (fr->grouping) { + case FILTER_GROUP_ALL: + xmlSetProp(node, "grouping", "all"); + break; + case FILTER_GROUP_ANY: + xmlSetProp(node, "grouping", "any"); + break; + } + if (fr->name) { + work = xmlNewNode(NULL, "title"); + xmlNodeSetContent(work, fr->name); + xmlAddChild(node, work); + } + set = xmlNewNode(NULL, "partset"); + xmlAddChild(node, set); + l = fr->parts; + while (l) { + work = filter_part_xml_encode((FilterPart *)l->data); + xmlAddChild(set, work); + l = g_list_next(l); + } + return node; +} + +static void load_set(xmlNodePtr node, FilterRule *fr, RuleContext *f) +{ + xmlNodePtr work; + char *rulename; + FilterPart *part; + + work = node->childs; + while (work) { + if (!strcmp(work->name, "part")) { + rulename = xmlGetProp(work, "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 { + g_warning("Unknwon xml node in part: %s", work->name); + } + work = work->next; + } +} + +int filter_rule_xml_decode (FilterRule *fr, xmlNodePtr node, RuleContext *f) +{ + return ((FilterRuleClass *)((GtkObject *)fr)->klass)->xml_decode(fr, node, f); +} + +static int xml_decode(FilterRule *fr, xmlNodePtr node, RuleContext *f) +{ + xmlNodePtr work; + char *grouping; + + if (fr->name) { + g_free(fr->name); + fr->name = NULL; + } + grouping = xmlGetProp(node, "grouping"); + if (!strcmp(grouping, "any")) + fr->grouping = FILTER_GROUP_ANY; + else + fr->grouping = FILTER_GROUP_ALL; + work = node->childs; + while (work) { + if (!strcmp(work->name, "partset")) { + load_set(work, fr, f); + } else if (!strcmp(work->name, "title")) { + if (!fr->name) + fr->name = xmlNodeGetContent(work); + } + work = work->next; + } + return 0; +} + +void filter_rule_add_part (FilterRule *fr, FilterPart *fp) +{ + fr->parts = g_list_append(fr->parts, fp); +} + +void filter_rule_remove_part (FilterRule *fr, FilterPart *fp) +{ + fr->parts = g_list_remove(fr->parts, fp); +} + +void filter_rule_replace_part(FilterRule *fr, FilterPart *fp, FilterPart *new) +{ + GList *l; + + l = g_list_find(fr->parts, fp); + if (l) { + l->data = new; + } else { + fr->parts = g_list_append(fr->parts, new); + } +} + +void filter_rule_build_code (FilterRule *fr, GString *out) +{ + return ((FilterRuleClass *)((GtkObject *)fr)->klass)->build_code(fr, out); +} + +static void build_code(FilterRule *fr, GString *out) +{ + 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"); +} + + +static void +match_all(GtkRadioButton *w, FilterRule *fr) +{ + if (gtk_toggle_button_get_active((GtkToggleButton *)w)) + fr->grouping = FILTER_GROUP_ALL; +} + +static void +match_any(GtkRadioButton *w, FilterRule *fr) +{ + if (gtk_toggle_button_get_active((GtkToggleButton *)w)) + fr->grouping = FILTER_GROUP_ANY; +} + +struct _part_data { + FilterRule *fr; + RuleContext *f; + FilterPart *part; + GtkWidget *partwidget, *container; +}; + +static void option_activate(GtkMenuItem *item, struct _part_data *data) +{ + FilterPart *part = gtk_object_get_data((GtkObject *)item, "part"); + FilterPart *newpart; + + /* 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((GtkContainer *)data->container, data->partwidget); + newpart = filter_part_clone(part); + filter_rule_replace_part(data->fr, data->part, newpart); + gtk_object_unref((GtkObject *)data->part); + data->part = newpart; + data->partwidget = filter_part_get_widget(newpart); + if (data->partwidget) + gtk_box_pack_start((GtkBox *)data->container, data->partwidget, FALSE, FALSE, 0); +} + +static GtkWidget * +get_rule_part_widget(RuleContext *f, FilterPart *newpart, FilterRule *fr) +{ + FilterPart *part = NULL; + GtkMenu *menu; + GtkMenuItem *item; + GtkOptionMenu *omenu; + GtkHBox *hbox; + GtkWidget *p; + int index=0, current=0; + struct _part_data *data; + + data = g_malloc0(sizeof(*data)); + data->fr = fr; + data->f = f; + data->part = newpart; + + hbox = (GtkHBox *)gtk_hbox_new(FALSE, 0); + /* only set to automatically clean up the memory */ + gtk_object_set_data_full((GtkObject *)hbox, "data", data, g_free); + + p = filter_part_get_widget(newpart); + + data->partwidget = p; + data->container = (GtkWidget *)hbox; + + menu = (GtkMenu *)gtk_menu_new(); + /* sigh, this is a little ugly */ + while ((part=rule_context_next_part(f, part))) { + item = (GtkMenuItem *)gtk_menu_item_new_with_label(part->title); + gtk_object_set_data((GtkObject *)item, "part", part); + gtk_signal_connect((GtkObject *)item, "activate", option_activate, data); + gtk_menu_append(menu, (GtkWidget *)item); + gtk_widget_show((GtkWidget *)item); + if (!strcmp(newpart->title, part->title)) { + current = index; + } + index++; + } + + omenu = (GtkOptionMenu *)gtk_option_menu_new(); + gtk_option_menu_set_menu(omenu, (GtkWidget *)menu); + gtk_option_menu_set_history(omenu, current); + gtk_widget_show((GtkWidget *)omenu); + + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)omenu, FALSE, FALSE, 0); + if (p) { + gtk_box_pack_start((GtkBox *)hbox, p, FALSE, FALSE, 0); + } + gtk_widget_show_all((GtkWidget *)hbox); + + return (GtkWidget *)hbox; +} + +struct _rule_data { + FilterRule *fr; + RuleContext *f; + GtkWidget *parts; +}; + +static void +less_parts(GtkWidget *button, struct _rule_data *data) +{ + GList *l; + FilterPart *part; + GtkWidget *w; + + l = data->fr->parts; + if (g_list_length(l) < 2) + return; + + /* remove the last one from the list */ + l = g_list_last(l); + part = l->data; + filter_rule_remove_part(data->fr, part); + gtk_object_unref((GtkObject *)part); + + /* and from the display */ + l = g_list_last(GTK_BOX(data->parts)->children); + w = ((GtkBoxChild *)l->data)->widget; + gtk_container_remove((GtkContainer *)data->parts, w); +} + +static void +more_parts(GtkWidget *button, struct _rule_data *data) +{ + FilterPart *new; + GtkWidget *w; + + /* create a new rule entry, use the first type of rule */ + new = rule_context_next_part(data->f, NULL); + if (new) { + new = filter_part_clone(new); + filter_rule_add_part(data->fr, new); + w = get_rule_part_widget(data->f, new, data->fr); + gtk_box_pack_start((GtkBox *)data->parts, w, FALSE, FALSE, 0); + } +} + +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, struct _RuleContext *f) +{ + return ((FilterRuleClass *)((GtkObject *)fr)->klass)->get_widget(fr, f); +} + +static GtkWidget *get_widget(FilterRule *fr, struct _RuleContext *f) +{ + GtkVBox *vbox, *parts, *inframe; + GtkHBox *hbox; + GtkWidget *w; + GtkRadioButton *g0, *g1; + GtkFrame *frame; + GtkEntry *name; + GtkLabel *label; + GList *l; + FilterPart *part; + struct _rule_data *data; + + /* this stuff should probably be a table, but the + rule parts need to be a vbox */ + vbox = (GtkVBox *)gtk_vbox_new(FALSE, 3); + + label = (GtkLabel *)gtk_label_new("Name"); + name = (GtkEntry *)gtk_entry_new(); + if (fr->name) + gtk_entry_set_text(name, fr->name); + hbox = (GtkHBox *)gtk_hbox_new(FALSE, 3); + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)label, FALSE, FALSE, 0); + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)name, TRUE, TRUE, 0); + gtk_box_pack_start((GtkBox *)vbox, (GtkWidget *)hbox, FALSE, FALSE, 3); + gtk_signal_connect((GtkObject *)name, "changed", name_changed, fr); + + frame = (GtkFrame *)gtk_frame_new("Messages matching"); + inframe = (GtkVBox *)gtk_vbox_new(FALSE, 3); + gtk_container_add((GtkContainer *)frame, (GtkWidget *)inframe); + + hbox = (GtkHBox *)gtk_hbox_new(FALSE, 3); + g0 = (GtkRadioButton *)gtk_radio_button_new_with_label(NULL, "Match all parts"); + g1 = (GtkRadioButton *)gtk_radio_button_new_with_label(g0->group, "Match any part"); + if (fr->grouping == FILTER_GROUP_ALL) { + gtk_toggle_button_set_active((GtkToggleButton *)g0, TRUE); + } else { + gtk_toggle_button_set_active((GtkToggleButton *)g1, TRUE); + } + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)g0, FALSE, FALSE, 0); + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)g1, FALSE, FALSE, 0); + gtk_box_pack_start((GtkBox *)inframe, (GtkWidget *)hbox, FALSE, FALSE, 3); + + gtk_signal_connect((GtkObject *)g0, "toggled", match_all, fr); + gtk_signal_connect((GtkObject *)g1, "toggled", match_any, fr); + + /* this is the parts list, it should probably be inside a scrolling list */ + parts = (GtkVBox *)gtk_vbox_new(FALSE, 3); + + /* data for the parts part of the display */ + data = g_malloc0(sizeof(*data)); + data->f = f; + data->fr = fr; + data->parts = (GtkWidget *)parts; + + /* only set to automatically clean up the memory */ + gtk_object_set_data_full((GtkObject *)vbox, "data", data, g_free); + + l = fr->parts; + while (l) { + part = l->data; + w = get_rule_part_widget(f, part, fr); + gtk_box_pack_start((GtkBox *)parts, (GtkWidget *)w, FALSE, FALSE, 3); + l = g_list_next(l); + } + + gtk_box_pack_start((GtkBox *)inframe, (GtkWidget *)parts, FALSE, FALSE, 3); + + hbox = (GtkHBox *)gtk_hbox_new(FALSE, 3); + w = gtk_button_new_with_label("Less"); + gtk_signal_connect((GtkObject *)w, "clicked", less_parts, data); + gtk_box_pack_end((GtkBox *)hbox, (GtkWidget *)w, FALSE, FALSE, 3); + w = gtk_button_new_with_label("More"); + gtk_signal_connect((GtkObject *)w, "clicked", more_parts, data); + gtk_box_pack_end((GtkBox *)hbox, (GtkWidget *)w, FALSE, FALSE, 3); + gtk_box_pack_start((GtkBox *)inframe, (GtkWidget *)hbox, FALSE, FALSE, 3); + + gtk_box_pack_start((GtkBox *)vbox, (GtkWidget *)frame, FALSE, FALSE, 3); + + gtk_widget_show_all((GtkWidget *)vbox); + return (GtkWidget *)vbox; +} + +FilterRule *filter_rule_next_list (GList *l, FilterRule *last) +{ + GList *node = l; + + if (last != NULL) { + node = g_list_find(node, last); + if (node == NULL) + node = l; + else + node = g_list_next(node); + } + if (node) + return node->data; + return NULL; +} diff --git a/filter/filter-rule.h b/filter/filter-rule.h new file mode 100644 index 0000000000..ca5b1ddfb7 --- /dev/null +++ b/filter/filter-rule.h @@ -0,0 +1,88 @@ +/* + * 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 _FILTER_RULE_H +#define _FILTER_RULE_H + +#include <gtk/gtk.h> + +#include "filter-part.h" + +#define FILTER_RULE(obj) GTK_CHECK_CAST (obj, filter_rule_get_type (), FilterRule) +#define FILTER_RULE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_rule_get_type (), FilterRuleClass) +#define IS_FILTER_RULE(obj) GTK_CHECK_TYPE (obj, filter_rule_get_type ()) + +typedef struct _FilterRule FilterRule; +typedef struct _FilterRuleClass FilterRuleClass; + +struct _RuleContext; + +enum _filter_grouping_t { + FILTER_GROUP_ALL, /* all rules must match */ + FILTER_GROUP_ANY /* any rule must match */ +}; + +struct _FilterRule { + GtkObject parent; + struct _FilterRulePrivate *priv; + + char *name; + + enum _filter_grouping_t grouping; + GList *parts; +}; + +struct _FilterRuleClass { + GtkObjectClass parent_class; + + /* virtual methods */ + xmlNodePtr (*xml_encode)(FilterRule *); + int (*xml_decode)(FilterRule *, xmlNodePtr, struct _RuleContext *); + + void (*build_code)(FilterRule *, GString *out); + + GtkWidget *(*get_widget)(FilterRule *fr, struct _RuleContext *f); + + /* signals */ +}; + +guint filter_rule_get_type (void); +FilterRule *filter_rule_new (void); + +/* methods */ +xmlNodePtr filter_rule_xml_encode (FilterRule *fr); +int filter_rule_xml_decode (FilterRule *fr, xmlNodePtr node, struct _RuleContext *f); + +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); +*/ + +/* static functions */ +FilterRule *filter_rule_next_list (GList *l, FilterRule *last); + +#endif /* ! _FILTER_RULE_H */ + diff --git a/filter/filter-xml.c b/filter/filter-xml.c deleted file mode 100644 index 61788286bf..0000000000 --- a/filter/filter-xml.c +++ /dev/null @@ -1,591 +0,0 @@ -/* -*- Mode: C; c-file-style: "linux"; indent-tabs-mode: t; c-basic-offset: 8; -*- */ - -/* Load save filter descriptions/options from an xml file */ - -#include <glib.h> -#include <gtk/gtk.h> -#include <gnome.h> -#include <gtkhtml/gtkhtml.h> - -#include <gnome-xml/tree.h> -#include <gnome-xml/parser.h> - -#include "filter-arg-types.h" -#include "filter-xml.h" - -#define d(x) - -struct token_tab { - char *name; - enum filter_xml_token token; -}; - -struct token_tab token_table[] = { - { "action", FILTER_XML_ACTION }, - { "address", FILTER_XML_ADDRESS }, - { "code", FILTER_XML_CODE }, - { "description", FILTER_XML_DESC }, - { "except", FILTER_XML_EXCEPT }, - { "folder", FILTER_XML_FOLDER }, - { "match", FILTER_XML_MATCH }, - { "name", FILTER_XML_NAME }, - { "option", FILTER_XML_OPTION }, - { "optionrule", FILTER_XML_OPTIONRULE }, - { "optionset", FILTER_XML_OPTIONSET }, - { "optionvalue", FILTER_XML_OPTIONVALUE }, - { "receive", FILTER_XML_RECEIVE }, - { "rule", FILTER_XML_RULE }, - { "ruleset", FILTER_XML_RULESET }, - { "send", FILTER_XML_SEND }, - { "source", FILTER_XML_SOURCE }, - { "string", FILTER_XML_STRING }, - { "text", FILTER_XML_TEXT }, -}; - -/* convert a name to a token value */ -static int -tokenise(const char *name) -{ - int i; - int len = sizeof(token_table)/sizeof(token_table[0]); - - if (name) { - for (i=0;i<len;i++) { - if (strcmp(name, token_table[i].name) == 0) - return token_table[i].token; - } - } - return -1; -} - -static int -tokenise_xmlfreeprop(char *name) -{ - int ret = -1; - ret = tokenise(name); - free(name); - return ret; -} - -static char * -detokenise(int token) -{ - int i; - int len = sizeof(token_table)/sizeof(token_table[0]); - - if (token>=0) { - for (i=0;i<len;i++) { - if (token_table[i].token == token) - return token_table[i].name; - } - } - return "<unknown>"; -} - - -static xmlNodePtr -find_node(xmlNodePtr start, char *name) -{ - d(printf("trying to find node '%s'\n", name)); - while (start && strcmp(start->name, name)) - start = start->next; - d(printf("node = %p\n", start)); - return start; -} - -static xmlNodePtr -find_node_attr(xmlNodePtr start, char *name, char *attrname, char *attrvalue) -{ - char *s; - - d(printf("looking for node named %s with attribute %s=%s\n", name, attrname, attrvalue)); - - while ( start && (start = find_node(start, name)) ) { - s = xmlGetProp(start, attrname); - d(printf(" comparing '%s' to '%s'\n", s, attrvalue)); - if (s && !strcmp(s, attrvalue)) { - free(s); - break; - } - free(s); - start = start->next; - } - return start; -} - -static GList * -load_desc(xmlNodePtr node, int type, int vartype, char *varname) -{ - struct filter_desc *desc; - xmlNodePtr n; - int newtype; - int newvartype; - char *newvarname; - GList *list = NULL; - - while (node) { - if (node->content) { - desc = g_malloc0(sizeof(*desc)); - desc->data = g_strdup (node->content); - desc->type = type; - desc->vartype = vartype; - desc->varname = g_strdup(varname); - d(printf(" **** node name = %s var name = %s var type = %s\n", node->name, varname, detokenise(vartype))); - list = g_list_append(list, desc); - d(printf("appending '%s'\n", node->content)); - newtype = type; - newvartype = -1; - newvarname = NULL; - } else { - newtype = tokenise(node->name); - newvartype = tokenise_xmlfreeprop(xmlGetProp(node, "type")); - newvarname = xmlGetProp(node, "name"); - } - n = node->childs; - while (n) { - d(printf("adding child '%s'\n", n->name)); - list = g_list_concat(list, load_desc(n, newtype, newvartype, newvarname)); - n = n->next; - } - if (newvarname) - free(newvarname); - node = node->next; - } - return list; -} - -GList * -filter_load_ruleset(xmlDocPtr doc) -{ - xmlNodePtr ruleset, rule, n; - struct filter_rule *r; - int type; - int ruletype; - GList *rules = NULL; - - g_return_val_if_fail(doc!=NULL, NULL); - - ruleset = find_node(doc->root->childs, "ruleset"); - - while (ruleset) { - - rule = ruleset->childs; - - ruletype = tokenise_xmlfreeprop(xmlGetProp(ruleset, "type")); - - d(printf("ruleset, name = %s\n", ruleset->name)); - - while (rule) { - - n = rule->childs; - r = g_malloc0(sizeof(*r)); - r->type = ruletype; - r->name = xmlGetProp(rule, "name"); - - d(printf(" rule, name = %s\n", r->name)); - - while (n) { - type = tokenise(n->name); - d(printf(" n, name = %s\n", n->name)); - d(printf(" ncontent = %s\n", n->content)); - d(printf(" childs = %p\n", n->childs)); - if (n->childs) { - d(printf(" childs content = %s\n", n->childs->content)); - } - switch(type) { - case FILTER_XML_CODE: - r->code = xmlNodeGetContent(n); - break; - case FILTER_XML_DESC: - d(printf(" ** loading description\n")); - r->description = load_desc(n->childs, type, -1, NULL); - d(printf(" ** done loading description\n")); - break; - default: - printf("warning, unknown token encountered\n"); - break; - } - n = n->next; - } - if (r) - rules = g_list_append(rules, r); - rule = rule->next; - } - ruleset = find_node(ruleset->next, "ruleset"); - } - return rules; -} - -int -filter_find_rule(struct filter_rule *a, char *name) -{ - d(printf("finding, is %s = %s?\n", a->name, name)); - return strcmp(a->name, name); -} - -int -filter_find_arg(FilterArg *a, char *name) -{ - d(printf("finding, is %s = %s?\n", a->name, name)); - return strcmp(a->name, name); -} - -static FilterArg * -load_optionvalue(struct filter_desc *desc, xmlNodePtr node) -{ - FilterArg *arg = NULL; - - d(printf("creating arg entry for '%s'\n", desc->varname)); - - switch(desc->vartype) { - case FILTER_XML_ADDRESS: - arg = filter_arg_address_new(desc->varname); - break; - case FILTER_XML_FOLDER: - arg = filter_arg_folder_new(desc->varname); - break; - case FILTER_XML_STRING: - arg = filter_arg_string_new(desc->varname); - break; - default: - d(printf("ok, maybe we're not\n")); - /* unknown arg type, drop it */ - return NULL; - } - - if (node == NULL) - return arg; - - filter_arg_values_add_xml(arg, node); - - return arg; -} - -GList * -filter_load_optionset(xmlDocPtr doc, GList *rules) -{ - xmlNodePtr optionset, option, o, or; - struct filter_option *op; - struct filter_optionrule *optionrule; - struct filter_rule *fr; - struct filter_desc *desc; - int type; - GList *l = NULL; - GList *lrule; - GList *ldesc; - - g_return_val_if_fail(doc!=NULL, NULL); - - optionset = find_node(doc->root->childs, "optionset"); - if (optionset == NULL) { - printf("optionset not found\n"); - return NULL; - } - option = find_node(optionset->childs, "option"); - while (option) { - o = option->childs; - op = g_malloc0(sizeof(*op)); - d(printf("option = %s\n", o->name)); - d(printf("option, type=%s\n", xmlGetProp(option, "type"))); - op->type = tokenise_xmlfreeprop(xmlGetProp(option, "type")); - while (o) { - char *rulestr; - - type = tokenise(o->name); - switch (type) { - case FILTER_XML_OPTIONRULE: - rulestr = xmlGetProp(o, "rule"); - lrule = g_list_find_custom(rules, rulestr, (GCompareFunc) filter_find_rule); - if (lrule) { - fr = lrule->data; - d(printf("found rule : %s\n", fr->name)); - optionrule = g_malloc0(sizeof(*optionrule)); - optionrule->rule = fr; - op->options = g_list_append(op->options, optionrule); - - /* scan through all variables required, setup blank variables if they do not exist */ - ldesc = fr->description; - while (ldesc) { - desc = ldesc->data; - if (desc->varname && desc->vartype!=-1) { - FilterArg *arg; - /* try and see if there is a setting for this value */ - or = find_node_attr(o->childs, "optionvalue", "name", desc->varname); - arg = load_optionvalue(desc, or); - if (arg) { - optionrule->args = g_list_append(optionrule->args, arg); - d(printf("Adding arg %s\n", arg->name)); - } - } - ldesc = g_list_next(ldesc); - } - } else { - /* FIXME: memleak */ - printf("Cannot find rule: %s\n", rulestr); - } - free(rulestr); - break; - case FILTER_XML_DESC: - d(printf("loading option descriptiong\n")); - op->description = load_desc(option->childs, type, -1, NULL); - break; - } - o = o->next; - } - l = g_list_append(l, op); - option = find_node(option->next, "option"); - } - return l; -} - -static xmlNodePtr -write_description(xmlDocPtr doc, GList *descl) -{ - xmlNodePtr d; - struct filter_desc *desc; - - desc = descl->data; - d = xmlNewDocNode(doc, NULL, "description", NULL); - xmlNodeSetContent(d, desc->data); - return d; -} - -xmlNodePtr -filter_write_optionset(xmlDocPtr doc, GList *optionl) -{ - xmlNodePtr root, option, optionrule, optionvalue; - GList *optionrulel, *argl; - struct filter_optionrule *or; - - root = xmlNewDocNode(doc, NULL, "optionset", NULL); - - /* for all options */ - while (optionl) { - struct filter_option *op = optionl->data; - - option = xmlNewDocNode(doc, NULL, "option", NULL); - xmlSetProp(option, "type", detokenise(op->type)); - - if (op->description) { - xmlNodePtr desc; - - desc = write_description(doc, op->description); - xmlAddChild(option, desc); - } - - optionrulel = op->options; - while (optionrulel) { - or = optionrulel->data; - - optionrule = xmlNewDocNode(doc, NULL, "optionrule", NULL); - xmlSetProp(optionrule, "type", detokenise(or->rule->type)); - xmlSetProp(optionrule, "rule", or->rule->name); - - argl = or->args; - while (argl) { - FilterArg *arg = argl->data; - - optionvalue = filter_arg_values_get_xml(arg); - if (optionvalue) - xmlAddChild(optionrule, optionvalue); - - argl = g_list_next(argl); - } - - xmlAddChild(option, optionrule); - - optionrulel = g_list_next(optionrulel); - } - - xmlAddChild(root, option); - optionl = g_list_next(optionl); - } - - return root; -} - -/* utility functions */ -struct filter_optionrule * -filter_clone_optionrule(struct filter_optionrule *or) -{ - GList *arg; - struct filter_optionrule *rule; - - rule = g_malloc0(sizeof(*rule)); - - rule->rule = or->rule; - arg = or->args; - while (arg) { - FilterArg *new = filter_arg_clone(FILTER_ARG(arg->data)); - gtk_object_set_data((GtkObject *)new, "origin", arg->data); - rule->args = g_list_append(rule->args, new); - arg = g_list_next(arg); - } - return rule; -} - -void -filter_clone_optionrule_free(struct filter_optionrule *or) -{ - GList *argl; - - d(printf("---- free optionrule\n")); - - argl = or->args; - while (argl) { - gtk_object_unref(GTK_OBJECT(argl->data)); - argl = g_list_next(argl); - } - g_list_free(or->args); - g_free(or); -} - -struct filter_optionrule * -filter_optionrule_new_from_rule(struct filter_rule *rule) -{ - struct filter_optionrule *or; - GList *descl; - - or = g_malloc0(sizeof(*or)); - - or->rule = rule; - - descl = rule->description; - while (descl) { - struct filter_desc *desc = descl->data; - if (desc->varname && desc->vartype != -1) { - FilterArg *arg = NULL; - switch (desc->vartype) { - case FILTER_XML_ADDRESS: - arg = filter_arg_address_new(desc->varname); - break; - case FILTER_XML_FOLDER: - arg = filter_arg_folder_new(desc->varname); - break; - case FILTER_XML_STRING: - arg = filter_arg_string_new(desc->varname); - break; - } - if (arg) { - or->args = g_list_append(or->args, arg); - } - } - descl = g_list_next(descl); - } - return or; -} - -void -filter_description_free(GList *descl) -{ - GList *node; - - node = descl; - while (node) { - GList *next = g_list_next(node); - struct filter_desc *d = node->data; - - g_free(d->data); - g_free(d->varname); - g_free(d); - - node = next; - } - g_list_free(descl); -} - -void -filter_load_ruleset_free(GList *nodel) -{ - GList *node = nodel; - - while (node) { - GList *next = g_list_next(node); - struct filter_rule *r = node->data; - - filter_description_free(r->description); - - /* g_free(r->name); */ - /* g_free(r->code); */ - - g_free(r); - node = next; - } - g_list_free(nodel); -} - -void -filter_load_optionset_free(GList *optionl) -{ - GList *option = optionl; - while (option) { - GList *next = g_list_next(option); - struct filter_option *fo = option->data; - GList *optionrule = fo->options; - - while (optionrule) { - GList *next = g_list_next(optionrule); - struct filter_optionrule *or = optionrule->data; - GList *arg = or->args; - - while (arg) { - gtk_object_unref(arg->data); - arg = g_list_next(arg); - } - - g_list_free(or->args); - g_free(or); - optionrule = next; - } - filter_description_free(fo->description); - g_list_free(fo->options); - g_free(fo); - option = next; - } -} - -GList *filter_load_ruleset_file(const char *name) -{ - xmlDocPtr doc; - GList *rules; - - doc = xmlParseFile(name); - rules = filter_load_ruleset(doc); - xmlFreeDoc(doc); - - return rules; -} - -GList *filter_load_optionset_file(const char *name, GList *rules) -{ - xmlDocPtr doc; - GList *options; - - doc = xmlParseFile(name); - if( doc == NULL ) { - g_warning( "Couldn't load option file %s!", name ); - return NULL; - } - options = filter_load_optionset(doc, rules); - xmlFreeDoc(doc); - - return options; -} - -int filter_write_optionset_file(const char *name, GList *optionl) -{ - xmlDocPtr out; - xmlNodePtr optionset; - xmlNodePtr filteroptions; - int ret; - - out = xmlNewDoc("1.0"); - optionset = filter_write_optionset(out, optionl); - filteroptions = xmlNewDocNode(out, NULL, "filteroptions", NULL); - xmlAddChild(filteroptions, optionset); - xmlDocSetRootElement(out, filteroptions); - ret = xmlSaveFile(name, out); - xmlFreeDoc(out); - - return ret; -} diff --git a/filter/filter-xml.h b/filter/filter-xml.h deleted file mode 100644 index 00b4758feb..0000000000 --- a/filter/filter-xml.h +++ /dev/null @@ -1,78 +0,0 @@ - -#ifndef _FILTER_XML_H -#define _FILTER_XML_H - -#include <glib.h> -#include <gnome-xml/tree.h> - -#include "filter-arg.h" - -enum filter_xml_token { - FILTER_XML_TEXT=0, - FILTER_XML_RULE, - FILTER_XML_CODE, - FILTER_XML_DESC, - FILTER_XML_RULESET, - FILTER_XML_OPTION, - FILTER_XML_OPTIONRULE, - FILTER_XML_OPTIONSET, - FILTER_XML_OPTIONVALUE, - FILTER_XML_SOURCE, - FILTER_XML_SEND, - FILTER_XML_RECEIVE, - FILTER_XML_ADDRESS, - FILTER_XML_FOLDER, - FILTER_XML_STRING, - FILTER_XML_NAME, - FILTER_XML_MATCH, - FILTER_XML_ACTION, - FILTER_XML_EXCEPT -}; - -struct filter_desc { - int type; - char *data; - char *varname; /* for named types */ - int vartype; -}; - -struct filter_rule { - int type; - char *name; - char *code; - GList *description; -}; - -struct filter_optionrule { - struct filter_rule *rule; - GList *args; /* FilterArg objects */ -}; - -struct filter_option { - int type; /* 'send' 'receive'? */ - GList *description; /* filter_desc */ - GList *options; /* option_rule */ -}; - -GList *filter_load_ruleset(xmlDocPtr doc); -GList *filter_load_optionset(xmlDocPtr doc, GList *rules); -xmlNodePtr filter_write_optionset(xmlDocPtr doc, GList *optionl); - -void filter_description_free(GList *descl); -void filter_load_ruleset_free(GList *nodel); -void filter_load_optionset_free(GList *optionl); - -GList *filter_load_ruleset_file(const char *name); -GList *filter_load_optionset_file(const char *name, GList *rules); -int filter_write_optionset_file(const char *name, GList *optionl); - -/* callbacks for searching GLists of various types */ -int filter_find_rule(struct filter_rule *a, char *name); -int filter_find_arg(FilterArg *a, char *name); - -/* utility functions */ -struct filter_optionrule *filter_clone_optionrule(struct filter_optionrule *or); -void filter_clone_optionrule_free(struct filter_optionrule *or); -struct filter_optionrule *filter_optionrule_new_from_rule(struct filter_rule *rule); - -#endif /* ! _FILTER_XML_H */ diff --git a/filter/filter.glade b/filter/filter.glade new file mode 100644 index 0000000000..7592bc30fd --- /dev/null +++ b/filter/filter.glade @@ -0,0 +1,383 @@ +<?xml version="1.0"?> +<GTK-Interface> + +<project> + <name>Filter</name> + <program_name>filter</program_name> + <directory></directory> + <source_directory>src</source_directory> + <pixmaps_directory>pixmaps</pixmaps_directory> + <language>C</language> + <gnome_support>True</gnome_support> + <gettext_support>True</gettext_support> +</project> + +<widget> + <class>GnomeDialog</class> + <name>edit_filter</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-vbox1</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_area1</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>button1</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>button3</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button> + </widget> + </widget> + + <widget> + <class>GtkOptionMenu</class> + <name>filter_source</name> + <sensitive>False</sensitive> + <can_focus>True</can_focus> + <items>Incoming +Outgoing +</items> + <initial_choice>0</initial_choice> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkFrame</class> + <name>frame1</name> + <label>Filter Rules</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>hbox1</name> + <homogeneous>False</homogeneous> + <spacing>0</spacing> + + <widget> + <class>GtkScrolledWindow</class> + <name>scrolledwindow1</name> + <width>256</width> + <hscrollbar_policy>GTK_POLICY_ALWAYS</hscrollbar_policy> + <vscrollbar_policy>GTK_POLICY_ALWAYS</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>viewport1</name> + <shadow_type>GTK_SHADOW_IN</shadow_type> + + <widget> + <class>GtkList</class> + <name>rule_list</name> + <selection_mode>GTK_SELECTION_SINGLE</selection_mode> + </widget> + </widget> + </widget> + + <widget> + <class>GtkVBox</class> + <name>vbox1</name> + <homogeneous>False</homogeneous> + <spacing>0</spacing> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + + <widget> + <class>GtkVButtonBox</class> + <name>vbuttonbox1</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>rule_add</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <label>Add</label> + </widget> + + <widget> + <class>GtkButton</class> + <name>rule_edit</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <label>Edit</label> + </widget> + + <widget> + <class>GtkButton</class> + <name>rule_delete</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <label>Delete</label> + </widget> + + <widget> + <class>GtkButton</class> + <name>rule_up</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <stock_button>GNOME_STOCK_BUTTON_UP</stock_button> + </widget> + + <widget> + <class>GtkButton</class> + <name>rule_down</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <stock_button>GNOME_STOCK_BUTTON_DOWN</stock_button> + </widget> + </widget> + </widget> + </widget> + </widget> + </widget> +</widget> + +<widget> + <class>GnomeDialog</class> + <name>edit_vfolder</name> + <title>Edit VFolders</title> + <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-vbox2</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_area2</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>button13</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>button15</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>frame2</name> + <label>Virtual Folders</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>hbox2</name> + <homogeneous>False</homogeneous> + <spacing>0</spacing> + + <widget> + <class>GtkScrolledWindow</class> + <name>scrolledwindow2</name> + <width>256</width> + <height>167</height> + <hscrollbar_policy>GTK_POLICY_ALWAYS</hscrollbar_policy> + <vscrollbar_policy>GTK_POLICY_ALWAYS</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>viewport2</name> + <shadow_type>GTK_SHADOW_IN</shadow_type> + + <widget> + <class>GtkList</class> + <name>rule_list</name> + <selection_mode>GTK_SELECTION_SINGLE</selection_mode> + </widget> + </widget> + </widget> + + <widget> + <class>GtkVBox</class> + <name>vbox2</name> + <homogeneous>False</homogeneous> + <spacing>0</spacing> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + + <widget> + <class>GtkVButtonBox</class> + <name>vbuttonbox2</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>rule_add</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <label>Add</label> + </widget> + + <widget> + <class>GtkButton</class> + <name>rule_edit</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <label>Edit</label> + </widget> + + <widget> + <class>GtkButton</class> + <name>rule_delete</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <label>Delete</label> + </widget> + + <widget> + <class>GtkButton</class> + <name>rule_up</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <stock_button>GNOME_STOCK_BUTTON_UP</stock_button> + </widget> + + <widget> + <class>GtkButton</class> + <name>rule_down</name> + <can_default>True</can_default> + <can_focus>True</can_focus> + <stock_button>GNOME_STOCK_BUTTON_DOWN</stock_button> + </widget> + </widget> + </widget> + </widget> + </widget> + </widget> +</widget> + +</GTK-Interface> diff --git a/filter/filtertypes.xml b/filter/filtertypes.xml index 2a94de574f..db5ceaa3ac 100644 --- a/filter/filtertypes.xml +++ b/filter/filtertypes.xml @@ -1,110 +1,105 @@ <?xml version="1.0"?> <filterdescription> -<ruleset type="match"> -<rule name="from-address"> - <code> - (match-all (header-contains "From" ${sender})) - </code> - <description lang="en">The From address matches <source type="address" name="sender">sender(s)</source>.</description> -</rule> - -<rule name="to-address"> - <code> - (match-all (or (header-contains "To" ${recipient}) - (header-contains "Cc" ${recipient}))) - </code> - <description lang="en">The To or Cc address matches <source type="address" name="recipient">recipients</source>.</description> -</rule> - -<rule name="subject-contains"> - <code> - (match-all (header-contains "Subject" ${words})) - </code> - <description lang="en">The Subject contains <source type="string" name="words">words</source>.</description> -</rule> - -<rule name="body-contains"> - <code> - (match-all (body-contains ${words})) - </code> - <description lang="en">The body contains <source type="string" name="words">words</source>.</description> -</rule> - -<rule name="cc-address"> - <code> - (match-all (header-contains "CC" ${self-email})) - </code> - <description lang="en">I am in the cc list.</description> -</rule> - -<rule name="msg-size"> - <code> - (& (> message-size (size-lower size-range)) - (< message-size (size-uppwer size-range))) - </code> - <description lang="en">The message is a <source type="size-range" name="size">certain size</source>.</description> -</rule> -</ruleset> - -<ruleset type="action"> -<rule name="copy-me"> - <code> - (copy-to ${folder}) - </code> - <description language="en">Send a copy to <source type="folder" name="folder">folder</source>.</description> -</rule> -<rule name="forward"> - <code> - (forward-to ${address}) - </code> - <description language="en">Forward the message to <source type="address" name="address">people</source>.</description> -</rule> -<rule name="delete"> - <code> - (delete) - </code> - <description language="en">Delete message.</description> -</rule> -<rule name="stop"> - <code> - (stop) - </code> - <description language="en">Stop processing further rules for this message.</description> -</rule> -</ruleset> - -<ruleset type="except"> -<rule name="except-me"> - <code> - (match-all (not (header-contains "To" ${self-email}))) - </code> - <description language="en">When I am the recipient.</description> -</rule> - -<rule name="not-body-contains"> - <code> - (match-all (not (body-contains ${words}))) - </code> - <description lang="en">The body does not contain <source type="string" name="words">words</source>.</description> -</rule> - -</ruleset> - -<optionset> - <option type="receive"> - <description language="en">When a message arrives.</description> - </option> - <option type="send"> - <description language="en">When a message is sent.</description> - </option> - <option type="receive"> - <description language="en">Copy incoming messages from a certain address to specific folder.</description> - <optionrule type="match" rule="from-address"/> - <optionrule type="action" rule="copy-me"/> - </option> - <option type="send"> - <description language="en">Copy sent messages to a specific folder.</description> - <optionrule type="action" rule="copy-me"/> - </option> -</optionset> +<partset> + <part name="sender"> + <title>Sender</title> + <input type="optionlist" name="sender-type"> + <option value="contains"> + <title>contains</title> + <code>(match-all (header-contains "From" ${sender}))</code> + </option> + <option value="not contains"> + <title>does not contain</title> + <code>(match-all (not (header-contains "From" ${sender})))</code> + </option> + </input> + <input type="string" name="sender"/> + </part> + <part name="to"> + <title>Recipients</title> + <input type="optionlist" name="recipient-type"> + <option value="contains"> + <title>contains</title> + <code> + (match-all (or (header-contains "To" ${recipient}) + (header-contains "Cc" ${recipient}))) + </code> + </option> + <option value="not contains"> + <title>does not contain</title> + <code> + (match-all (not (or + (header-contains "To" ${recipient}) + (header-contains "Cc" ${recipient})))) + </code> + </option> + </input> + <input type="address" name="recipient"/> + </part> + <part name="subject"> + <title>Subject</title> + <input type="optionlist" name="subject-type"> + <option value="contains"> + <title>contains</title> + <code> + (match-all (header-contains "Subject" ${subject})) + </code> + </option> + <option value="not contains"> + <title>does not contain</title> + <code> + (match-all (not (header-contains "Subject" ${subject}))) + </code> + </option> + </input> + <input type="string" name="subject"/> + </part> + <part name="body"> + <title>Message Body</title> + <input type="optionlist" name="body-type"> + <option value="contains"> + <title>contains</title> + <code> + (body-contains ${word}) + </code> + </option> + <option value="not contains"> + <title>does not contain</title> + <code> + (not (body-contains "Subject" ${word})) + </code> + </option> + </input> + <input type="string" name="word"/> + </part> + <part name="sexp"> + <title>Expression</title> + <input type="code" name="code"/> + </part> +</partset> +<actionset> + <part name="copy-to-folder"> + <title>Copy to Folder</title> + <code>(copy-to ${folder})</code> + <input type="folder" name="folder"/> + </part> + <part name="forward-to"> + <title>Forward to address</title> + <code>(forward-to ${address})</code> + <input type="address" name="address"/> + </part> + <part name="delete"> + <title>Delete</title> + <code>(delete)</code> + </part> + <part name="stop"> + <title>Stop processing</title> + <code>(stop)</code> + </part> + <part name="colour"> + <title>Assign Colour</title> + <code>(set-colour ${colour})</code> + <input type="colour" name="colour"/> + </part> +</actionset> </filterdescription> diff --git a/filter/rule-context.c b/filter/rule-context.c new file mode 100644 index 0000000000..e6a18d078a --- /dev/null +++ b/filter/rule-context.c @@ -0,0 +1,349 @@ +/* + * 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 <errno.h> +#include <gtk/gtk.h> +#include <gnome.h> + +#include "rule-context.h" + +#define d(x) x + +static int load(RuleContext *f, const char *system, const char *user); +static int save(RuleContext *f, const char *user); + +static void rule_context_class_init (RuleContextClass *class); +static void rule_context_init (RuleContext *gspaper); +static void rule_context_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((RuleContext *)(x))->priv) + +struct _RuleContextPrivate { +}; + +static GtkObjectClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +rule_context_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "RuleContext", + sizeof(RuleContext), + sizeof(RuleContextClass), + (GtkClassInitFunc)rule_context_class_init, + (GtkObjectInitFunc)rule_context_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(gtk_object_get_type (), &type_info); + } + + return type; +} + +static void +rule_context_class_init (RuleContextClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(gtk_object_get_type ()); + + object_class->finalize = rule_context_finalise; + + /* override methods */ + class->load = load; + class->save = save; + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +rule_context_init (RuleContext *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); + + o->part_set_map = g_hash_table_new(g_str_hash, g_str_equal); + o->rule_set_map = g_hash_table_new(g_str_hash, g_str_equal); +} + +static void +rule_context_finalise(GtkObject *obj) +{ + RuleContext *o = (RuleContext *)obj; + + o = o; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * rule_context_new: + * + * Create a new RuleContext object. + * + * Return value: A new #RuleContext object. + **/ +RuleContext * +rule_context_new(void) +{ + RuleContext *o = (RuleContext *)gtk_type_new(rule_context_get_type ()); + return o; +} + +void rule_context_add_part_set(RuleContext *f, const char *setname, int part_type, RCPartFunc append, RCNextPartFunc next) +{ + struct _part_set_map *map; + + map = g_malloc0(sizeof(*map)); + map->type = part_type; + map->append = append; + map->next = next; + map->name = g_strdup(setname); + g_hash_table_insert(f->part_set_map, map->name, map); + f->part_set_list = g_list_append(f->part_set_list, map); + d(printf("adding part set '%s'\n", setname)); +} + +void rule_context_add_rule_set(RuleContext *f, const char *setname, int rule_type, RCRuleFunc append, RCNextRuleFunc next) +{ + struct _rule_set_map *map; + + map = g_malloc0(sizeof(*map)); + map->type = rule_type; + map->append = append; + map->next = next; + map->name = g_strdup(setname); + g_hash_table_insert(f->rule_set_map, map->name, map); + f->rule_set_list = g_list_append(f->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. + **/ +void +rule_context_set_error(RuleContext *f, char *error) +{ + g_free(f->error); + f->error = error; +} + +/** + * rule_context_load: + * @f: + * @system: + * @user: + * + * Load a rule context from a system and user description file. + * + * Return value: + **/ +int rule_context_load(RuleContext *f, const char *system, const char *user) +{ + printf("rule_context: loading %s %s\n", system, user); + + return ((RuleContextClass *)((GtkObject *)f)->klass)->load(f, system, user); +} + +static int load(RuleContext *f, const char *system, const char *user) +{ + xmlNodePtr set, rule; + struct _part_set_map *part_map; + struct _rule_set_map *rule_map; + + rule_context_set_error(f, NULL); + + d(printf("loading rules %s %s\n", system, user)); + + f->system = xmlParseFile(system); + if (f->system == NULL) { + rule_context_set_error(f, g_strdup_printf("Unable to load system rules '%s': %s", + system, strerror(errno))); + return -1; + } + if (strcmp(f->system->root->name, "filterdescription")) { + rule_context_set_error(f, g_strdup_printf("Unable to load system rules '%s': Invalid format", + system)); + xmlFreeDoc(f->system); + f->system = NULL; + return -1; + } + f->user = xmlParseFile(user); + if (f->user == NULL) { + rule_context_set_error(f, g_strdup_printf("Unable to load user rules '%s': %s", + system, strerror(errno))); + xmlFreeDoc(f->system); + f->system = NULL; + return -1; + } + + /* now parse structure */ + /* get rule parts */ + set = f->system->root->childs; + while (set) { + d(printf("set name = %s\n", set->name)); + part_map = g_hash_table_lookup(f->part_set_map, set->name); + if (part_map) { + d(printf("loading parts ...\n")); + rule = set->childs; + while (rule) { + if (!strcmp(rule->name, "part")) { + FilterPart *part = FILTER_PART(gtk_type_new(part_map->type)); + if (filter_part_xml_create(part, rule) == 0) { + part_map->append(f, part); + } else { + gtk_object_unref((GtkObject *)part); + g_warning("Cannot load filter part"); + } + } + rule = rule->next; + } + } + set = set->next; + } + + /* now load actual rules */ + set = f->user->root->childs; + while (set) { + d(printf("set name = %s\n", set->name)); + rule_map = g_hash_table_lookup(f->rule_set_map, set->name); + if (rule_map) { + d(printf("loading rules ...\n")); + rule = set->childs; + while (rule) { + printf("checking node: %s\n", rule->name); + if (!strcmp(rule->name, "rule")) { + FilterRule *part = FILTER_RULE(gtk_type_new(rule_map->type)); + if (filter_rule_xml_decode(part, rule, f) == 0) { + rule_map->append(f, part); + } else { + gtk_object_unref((GtkObject *)part); + g_warning("Cannot load filter part"); + } + } + rule = rule->next; + } + } + set = set->next; + } + return 0; +} + +/** + * rule_context_save: + * @f: + * @user: + * + * Save a rule context to disk. + * + * Return value: + **/ +int rule_context_save(RuleContext *f, const char *user) +{ + return ((RuleContextClass *)((GtkObject *)f)->klass)->save(f, user); +} + +static int save(RuleContext *f, const char *user) +{ + xmlDocPtr doc; + xmlNodePtr root, rules, work; + GList *l; + FilterRule *rule; + struct _rule_set_map *map; + + doc = xmlNewDoc("1.0"); + root = xmlNewDocNode(doc, NULL, "filteroptions", NULL); + xmlDocSetRootElement(doc, root); + l = f->rule_set_list; + while (l) { + map = l->data; + rules = xmlNewDocNode(doc, NULL, map->name, NULL); + xmlAddChild(root, rules); + rule = NULL; + while ( (rule = map->next(f, rule)) ) { + d(printf("processing rule %s\n", rule->name)); + work = filter_rule_xml_encode(rule); + xmlAddChild(rules, work); + } + l = g_list_next(l); + } + xmlSaveFile(user, doc); + xmlFreeDoc(doc); + return 0; +} + +FilterPart *rule_context_find_part(RuleContext *f, char *name) +{ + d(printf("find part : ")); + return filter_part_find_list(f->parts, name); +} + +FilterPart *rule_context_next_part(RuleContext *f, FilterPart *last) +{ + return filter_part_next_list(f->parts, last); +} + +FilterRule *rule_context_next_rule(RuleContext *f, FilterRule *last) +{ + return filter_rule_next_list(f->rules, last); +} + +void rule_context_add_part(RuleContext *f, FilterPart *part) +{ + f->parts = g_list_append(f->parts, part); +} + +void rule_context_add_rule(RuleContext *f, FilterRule *new) +{ + f->rules = g_list_append(f->rules, new); +} + +void rule_context_remove_rule(RuleContext *f, FilterRule *rule) +{ + f->rules = g_list_remove(f->rules, rule); +} + +void rule_context_rank_rule(RuleContext *f, FilterRule *rule, int rank) +{ + f->rules = g_list_remove(f->rules, rule); + f->rules = g_list_insert(f->rules, rule, rank); +} + +int rule_context_get_rank_rule(RuleContext *f, FilterRule *rule) +{ + return g_list_index(f->rules, rule); +} diff --git a/filter/rule-context.h b/filter/rule-context.h new file mode 100644 index 0000000000..f2b59cd3c0 --- /dev/null +++ b/filter/rule-context.h @@ -0,0 +1,111 @@ +/* + * 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 _RULE_CONTEXT_H +#define _RULE_CONTEXT_H + +#include <gtk/gtk.h> +#include <gnome-xml/parser.h> + +#include "filter-part.h" +#include "filter-rule.h" + +#define RULE_CONTEXT(obj) GTK_CHECK_CAST (obj, rule_context_get_type (), RuleContext) +#define RULE_CONTEXT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, rule_context_get_type (), RuleContextClass) +#define IS_RULE_CONTEXT(obj) GTK_CHECK_TYPE (obj, rule_context_get_type ()) + +typedef struct _RuleContext RuleContext; +typedef struct _RuleContextClass RuleContextClass; + +struct _RuleContext { + GtkObject parent; + struct _RuleContextPrivate *priv; + + char *error; /* string version of error */ + + xmlDocPtr system; /* system rules source */ + xmlDocPtr user; /* user defined rules source */ + + 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 _RuleContextClass { + GtkObjectClass parent_class; + + /* virtual methods */ + int (*load)(RuleContext *f, const char *system, const char *user); + int (*save)(RuleContext *f, const char *user); + + /* signals */ +}; + +typedef void (*RCPartFunc)(RuleContext *f, FilterPart *part); +typedef void (*RCRuleFunc)(RuleContext *f, FilterRule *part); +typedef FilterPart * (*RCNextPartFunc)(RuleContext *f, FilterPart *part); +typedef FilterRule * (*RCNextRuleFunc)(RuleContext *f, FilterRule *rule); + +struct _part_set_map { + char *name; + int type; + RCPartFunc append; + RCNextPartFunc next; +}; + +struct _rule_set_map { + char *name; + int type; + RCRuleFunc append; + RCNextRuleFunc next; +}; + +guint rule_context_get_type (void); +RuleContext *rule_context_new (void); + +/* methods */ +int rule_context_load(RuleContext *f, const char *system, const char *user); +int rule_context_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_next_part(RuleContext *f, FilterPart *last); + +FilterRule *rule_context_next_rule(RuleContext *f, FilterRule *last); +void rule_context_add_rule(RuleContext *f, FilterRule *new); +void rule_context_remove_rule(RuleContext *f, FilterRule *rule); + +/* get/set the rank (position) of a rule */ +void rule_context_rank_rule(RuleContext *f, FilterRule *rule, int rank); +int rule_context_get_rank_rule(RuleContext *f, FilterRule *rule); + +void rule_context_delete_rule(RuleContext *f, FilterRule *rule); + +/* setup type for set parts */ +void rule_context_add_part_set(RuleContext *f, const char *setname, int part_type, RCPartFunc append, RCNextPartFunc next); +void rule_context_add_rule_set(RuleContext *f, const char *setname, int rule_type, RCRuleFunc append, RCNextRuleFunc next); + +#endif /* ! _RULE_CONTEXT_H */ + diff --git a/filter/score-context.c b/filter/score-context.c new file mode 100644 index 0000000000..a171bd1240 --- /dev/null +++ b/filter/score-context.c @@ -0,0 +1,100 @@ +/* + * 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 "score-context.h" +#include "score-rule.h" + +static void score_context_class_init (ScoreContextClass *class); +static void score_context_init (ScoreContext *gspaper); +static void score_context_finalise (GtkObject *obj); + +static RuleContextClass *parent_class; + +guint +score_context_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "ScoreContext", + sizeof(ScoreContext), + sizeof(ScoreContextClass), + (GtkClassInitFunc)score_context_class_init, + (GtkObjectInitFunc)score_context_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(rule_context_get_type (), &type_info); + } + + return type; +} + +static void +score_context_class_init (ScoreContextClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(rule_context_get_type ()); + + object_class->finalize = score_context_finalise; + /* override methods */ + +} + +static void +score_context_init (ScoreContext *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", score_rule_get_type(), + rule_context_add_rule, rule_context_next_rule); +} + +static void +score_context_finalise(GtkObject *obj) +{ + ScoreContext *o = (ScoreContext *)obj; + + o = o; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * score_context_new: + * + * Create a new ScoreContext object. + * + * Return value: A new #ScoreContext object. + **/ +ScoreContext * +score_context_new(void) +{ + ScoreContext *o = (ScoreContext *)gtk_type_new(score_context_get_type ()); + return o; +} diff --git a/filter/score-context.h b/filter/score-context.h new file mode 100644 index 0000000000..b89f70c1f8 --- /dev/null +++ b/filter/score-context.h @@ -0,0 +1,53 @@ +/* + * 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 _SCORE_CONTEXT_H +#define _SCORE_CONTEXT_H + +#include <gtk/gtk.h> + +#include "rule-context.h" + +#define SCORE_CONTEXT(obj) GTK_CHECK_CAST (obj, score_context_get_type (), ScoreContext) +#define SCORE_CONTEXT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, score_context_get_type (), ScoreContextClass) +#define IS_SCORE_CONTEXT(obj) GTK_CHECK_TYPE (obj, score_context_get_type ()) + +typedef struct _ScoreContext ScoreContext; +typedef struct _ScoreContextClass ScoreContextClass; + +struct _ScoreContext { + RuleContext parent; +}; + +struct _ScoreContextClass { + RuleContextClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint score_context_get_type (void); +ScoreContext *score_context_new (void); + +/* methods */ + +#endif /* ! _SCORE_CONTEXT_H */ + diff --git a/filter/score-editor.c b/filter/score-editor.c new file mode 100644 index 0000000000..20c5ba78de --- /dev/null +++ b/filter/score-editor.c @@ -0,0 +1,311 @@ +/* + * 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 "score-editor.h" +#include "score-context.h" +#include "score-rule.h" + +#define d(x) + +#if 0 +static void score_editor_class_init (ScoreEditorClass *class); +static void score_editor_init (ScoreEditor *gspaper); + +static GnomeDialogClass *parent_class; + +guint +score_editor_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "ScoreEditor", + sizeof(ScoreEditor), + sizeof(ScoreEditorClass), + (GtkClassInitFunc)score_editor_class_init, + (GtkObjectInitFunc)score_editor_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(gnome_dialog_get_type (), &type_info); + } + + return type; +} + +static void +score_editor_class_init (ScoreEditorClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(gnome_dialog_get_type ()); + + /* override methods */ + +} + +static void +score_editor_init (ScoreEditor *o) +{ +} + +/** + * score_editor_new: + * + * Create a new ScoreEditor object. + * + * Return value: A new #ScoreEditor object. + **/ +ScoreEditor * +score_editor_new(void) +{ + ScoreEditor *o = (ScoreEditor *)gtk_type_new(score_editor_get_type ()); + return o; +} +#endif + + +enum { + BUTTON_ADD, + BUTTON_EDIT, + BUTTON_DELETE, + BUTTON_UP, + BUTTON_DOWN, + BUTTON_LAST +}; + +struct _editor_data { + RuleContext *f; + FilterRule *current; + GtkList *list; + GtkButton *buttons[BUTTON_LAST]; +}; + +static void set_sensitive(struct _editor_data *data); + +static void rule_add(GtkWidget *widget, struct _editor_data *data) +{ + ScoreRule *rule; + int result; + GnomeDialog *gd; + GtkWidget *w; + FilterPart *part; + + d(printf("add rule\n")); + /* create a new rule with 1 match and 1 action */ + rule = score_rule_new(); + + part = rule_context_next_part(data->f, NULL); + filter_rule_add_part((FilterRule *)rule, filter_part_clone(part)); + + w = filter_rule_get_widget((FilterRule *)rule, data->f); + gd = (GnomeDialog *)gnome_dialog_new("Add Rule", "Ok", "Cancel", NULL); + gtk_box_pack_start((GtkBox *)gd->vbox, w, FALSE, TRUE, 0); + gtk_widget_show((GtkWidget *)gd); + result = gnome_dialog_run_and_close(gd); + if (result == 0) { + GtkListItem *item = (GtkListItem *)gtk_list_item_new_with_label(((FilterRule *)rule)->name); + GList *l = NULL; + + gtk_object_set_data((GtkObject *)item, "rule", rule); + gtk_widget_show((GtkWidget *)item); + l = g_list_append(l, item); + gtk_list_append_items(data->list, l); + gtk_list_select_child(data->list, (GtkWidget *)item); + data->current = (FilterRule *)rule; + rule_context_add_rule(data->f, (FilterRule *)rule); + set_sensitive(data); + } else { + gtk_object_unref((GtkObject *)rule); + } +} + +static void rule_edit(GtkWidget *widget, struct _editor_data *data) +{ + GtkWidget *w; + int result; + GnomeDialog *gd; + FilterRule *rule; + int pos; + + d(printf("edit rule\n")); + rule = data->current; + w = filter_rule_get_widget(rule, data->f); + gd = (GnomeDialog *)gnome_dialog_new("Edit Score Rule", "Ok", NULL); + gtk_box_pack_start((GtkBox *)gd->vbox, w, FALSE, TRUE, 0); + gtk_widget_show((GtkWidget *)gd); + result = gnome_dialog_run_and_close(gd); + + if (result == 0) { + pos = rule_context_get_rank_rule(data->f, data->current); + if (pos != -1) { + GtkListItem *item = g_list_nth_data(data->list->children, pos); + gtk_label_set_text((GtkLabel *)(((GtkBin *)item)->child), data->current->name); + } + } +} + +static void rule_delete(GtkWidget *widget, struct _editor_data *data) +{ + int pos; + GList *l; + GtkListItem *item; + + d(printf("ddelete rule\n")); + pos = rule_context_get_rank_rule(data->f, data->current); + if (pos != -1) { + rule_context_remove_rule(data->f, data->current); + + item = g_list_nth_data(data->list->children, pos); + l = g_list_append(NULL, item); + gtk_list_remove_items(data->list, l); + g_list_free(l); + + gtk_object_unref((GtkObject *)data->current); + data->current = NULL; + } + set_sensitive(data); +} + +static void rule_move(struct _editor_data *data, int from, int to) +{ + GList *l; + GtkListItem *item; + + d(printf("moving %d to %d\n", from, to)); + rule_context_rank_rule(data->f, data->current, to); + + item = g_list_nth_data(data->list->children, from); + l = g_list_append(NULL, item); + gtk_list_remove_items_no_unref(data->list, l); + gtk_list_insert_items(data->list, l, to); + gtk_list_select_child(data->list, (GtkWidget *)item); + set_sensitive(data); +} + +static void rule_up(GtkWidget *widget, struct _editor_data *data) +{ + int pos; + + d(printf("up rule\n")); + pos = rule_context_get_rank_rule(data->f, data->current); + if (pos>0) { + rule_move(data, pos, pos-1); + } +} + +static void rule_down(GtkWidget *widget, struct _editor_data *data) +{ + int pos; + + d(printf("down rule\n")); + pos = rule_context_get_rank_rule(data->f, data->current); + rule_move(data, pos, pos+1); +} + +static struct { + char *name; + GtkSignalFunc func; +} edit_buttons[] = { + { "rule_add", rule_add }, + { "rule_edit", rule_edit }, + { "rule_delete", rule_delete }, + { "rule_up", rule_up }, + { "rule_down", rule_down }, +}; + +static void +set_sensitive(struct _editor_data *data) +{ + FilterRule *rule = NULL; + int index=-1, count=0; + + while ((rule = rule_context_next_rule(data->f, rule))) { + if (rule == data->current) + index=count; + count++; + } + d(printf("index = %d count=%d\n", index, count)); + count--; + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_EDIT], index != -1); + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_DELETE], index != -1); + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_UP], index > 0); + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_DOWN], index >=0 && index<count); +} + +static void +select_rule(GtkWidget *w, GtkWidget *child, struct _editor_data *data) +{ + data->current = gtk_object_get_data((GtkObject *)child, "rule"); + if (data->current) + d(printf("seledct rule: %s\n", data->current->name)); + else + d(printf("bad data?\n")); + set_sensitive(data); +} + +GtkWidget *score_editor_construct (struct _ScoreContext *f) +{ + GladeXML *gui; + GtkWidget *d, *w; + GList *l; + FilterRule *rule = NULL; + struct _editor_data *data; + int i; + + g_assert(IS_SCORE_CONTEXT(f)); + + data = g_malloc0(sizeof(*data)); + data->f = (RuleContext *)f; + + gui = glade_xml_new(FILTER_GLADEDIR "/filter.glade", "edit_vfolder"); + d = glade_xml_get_widget (gui, "edit_vfolder"); + gtk_object_set_data_full((GtkObject *)d, "data", data, g_free); + + gtk_window_set_title((GtkWindow *)d, "Edit Score List"); + 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, "rule_list"); + data->list = (GtkList *)w; + l = NULL; + while ((rule = rule_context_next_rule((RuleContext *)f, rule))) { + GtkListItem *item = (GtkListItem *)gtk_list_item_new_with_label(rule->name); + gtk_object_set_data((GtkObject *)item, "rule", rule); + gtk_widget_show((GtkWidget *)item); + l = g_list_append(l, item); + } + gtk_list_append_items(data->list, l); + gtk_signal_connect((GtkObject *)w, "select_child", select_rule, data); + + set_sensitive(data); + gtk_object_unref((GtkObject *)gui); + + return d; +} diff --git a/filter/score-editor.h b/filter/score-editor.h new file mode 100644 index 0000000000..cb78d465f0 --- /dev/null +++ b/filter/score-editor.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 _SCORE_EDITOR_H +#define _SCORE_EDITOR_H + +#include <gtk/gtk.h> +#include <libgnomeui/gnome-dialog.h> + +#if 0 +/* NOTE: object stuff not used (yet?), this is just a holder file for a static factory */ + +#define SCORE_EDITOR(obj) GTK_CHECK_CAST (obj, score_editor_get_type (), ScoreEditor) +#define SCORE_EDITOR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, score_editor_get_type (), ScoreEditorClass) +#define IS_SCORE_EDITOR(obj) GTK_CHECK_TYPE (obj, score_editor_get_type ()) + +typedef struct _ScoreEditor ScoreEditor; +typedef struct _ScoreEditorClass ScoreEditorClass; + +struct _ScoreEditor { + GnomeDialog parent; +}; + +struct _ScoreEditorClass { + GnomeDialogClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint score_editor_get_type (void); +ScoreEditor *score_editor_new (void); +#endif + +struct _ScoreContext; + +/* methods */ +GtkWidget *score_editor_construct (struct _ScoreContext *f); + +#endif /* ! _SCORE_EDITOR_H */ + diff --git a/filter/score-rule.c b/filter/score-rule.c new file mode 100644 index 0000000000..8eb51b6821 --- /dev/null +++ b/filter/score-rule.c @@ -0,0 +1,190 @@ +/* + * 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 "score-rule.h" + +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); + +static void score_rule_class_init (ScoreRuleClass *class); +static void score_rule_init (ScoreRule *gspaper); +static void score_rule_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((ScoreRule *)(x))->priv) + +struct _ScoreRulePrivate { +}; + +static FilterRuleClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +score_rule_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "ScoreRule", + sizeof(ScoreRule), + sizeof(ScoreRuleClass), + (GtkClassInitFunc)score_rule_class_init, + (GtkObjectInitFunc)score_rule_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(filter_rule_get_type (), &type_info); + } + + return type; +} + +static void +score_rule_class_init (ScoreRuleClass *class) +{ + GtkObjectClass *object_class; + FilterRuleClass *rule_class = (FilterRuleClass *)class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(filter_rule_get_type ()); + + object_class->finalize = score_rule_finalise; + + /* override methods */ + rule_class->xml_encode = xml_encode; + rule_class->xml_decode = xml_decode; +/* rule_class->build_code = build_code;*/ + rule_class->get_widget = get_widget; + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +score_rule_init (ScoreRule *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); +} + +static void +score_rule_finalise(GtkObject *obj) +{ + ScoreRule *o = (ScoreRule *)obj; + + o = o; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * score_rule_new: + * + * Create a new ScoreRule object. + * + * Return value: A new #ScoreRule object. + **/ +ScoreRule * +score_rule_new(void) +{ + ScoreRule *o = (ScoreRule *)gtk_type_new(score_rule_get_type ()); + return o; +} + +static xmlNodePtr xml_encode(FilterRule *fr) +{ + ScoreRule *sr = (ScoreRule *)fr; + xmlNodePtr node, value; + char number[16]; + + node = ((FilterRuleClass *)(parent_class))->xml_encode(fr); + sprintf(number, "%d", sr->score); + value = xmlNewNode(NULL, "score"); + xmlSetProp(value, "value", number); + xmlAddChild(node, value); + return node; +} + +static int xml_decode(FilterRule *fr, xmlNodePtr node, struct _RuleContext *f) +{ + ScoreRule *sr = (ScoreRule *)fr; + xmlNodePtr value; + int result; + char *str; + + result = ((FilterRuleClass *)(parent_class))->xml_decode(fr, node, f); + if (result != 0) + return result; + value = node->childs; + while (value) { + if (!strcmp(value->name, "score")) { + str = xmlGetProp(value, "value"); + sscanf(str, "%d", &sr->score); + } + value = value->next; + } + return 0; +} + +/*static void build_code(FilterRule *fr, GString *out) +{ +}*/ + +static void spin_changed(GtkAdjustment *adj, ScoreRule *sr) +{ + sr->score = adj->value; +} + +static GtkWidget *get_widget(FilterRule *fr, struct _RuleContext *f) +{ + GtkWidget *widget; + GtkFrame *frame; + GtkLabel *label; + GtkHBox *hbox; + GtkAdjustment *adj; + ScoreRule *sr = (ScoreRule *)fr; + GtkSpinButton *spin; + + widget = ((FilterRuleClass *)(parent_class))->get_widget(fr, f); + frame = (GtkFrame *)gtk_frame_new("Score"); + hbox = (GtkHBox *)gtk_hbox_new(FALSE, 3); + label = (GtkLabel *)gtk_label_new("Score"); + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)label, FALSE, FALSE, 3); + adj = (GtkAdjustment *)gtk_adjustment_new((float)sr->score, -100, 100, 1, 10, 10); + gtk_signal_connect((GtkObject *)adj, "value_changed", spin_changed, sr); + spin = (GtkSpinButton *)gtk_spin_button_new(adj, 1.0, 0); + gtk_box_pack_start((GtkBox *)hbox, (GtkWidget *)spin, FALSE, FALSE, 3); + gtk_container_add((GtkContainer *)frame, (GtkWidget *)hbox); + gtk_widget_show_all((GtkWidget *)frame); + + gtk_box_pack_start((GtkBox *)widget, (GtkWidget *)frame, FALSE, FALSE, 3); + return widget; +} diff --git a/filter/score-rule.h b/filter/score-rule.h new file mode 100644 index 0000000000..25607fd7c4 --- /dev/null +++ b/filter/score-rule.h @@ -0,0 +1,56 @@ +/* + * 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 _SCORE_RULE_H +#define _SCORE_RULE_H + +#include <gtk/gtk.h> + +#include "filter-rule.h" + +#define SCORE_RULE(obj) GTK_CHECK_CAST (obj, score_rule_get_type (), ScoreRule) +#define SCORE_RULE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, score_rule_get_type (), ScoreRuleClass) +#define IS_SCORE_RULE(obj) GTK_CHECK_TYPE (obj, score_rule_get_type ()) + +typedef struct _ScoreRule ScoreRule; +typedef struct _ScoreRuleClass ScoreRuleClass; + +struct _ScoreRule { + FilterRule parent; + struct _ScoreRulePrivate *priv; + + int score; +}; + +struct _ScoreRuleClass { + FilterRuleClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint score_rule_get_type (void); +ScoreRule *score_rule_new (void); + +/* methods */ + +#endif /* ! _SCORE_RULE_H */ + diff --git a/filter/vfolder-context.c b/filter/vfolder-context.c new file mode 100644 index 0000000000..0202c71847 --- /dev/null +++ b/filter/vfolder-context.c @@ -0,0 +1,115 @@ +/* + * 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 "vfolder-context.h" + +static void vfolder_context_class_init (VfolderContextClass *class); +static void vfolder_context_init (VfolderContext *gspaper); +static void vfolder_context_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((VfolderContext *)(x))->priv) + +struct _VfolderContextPrivate { +}; + +static RuleContextClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +vfolder_context_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "VfolderContext", + sizeof(VfolderContext), + sizeof(VfolderContextClass), + (GtkClassInitFunc)vfolder_context_class_init, + (GtkObjectInitFunc)vfolder_context_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(rule_context_get_type (), &type_info); + } + + return type; +} + +static void +vfolder_context_class_init (VfolderContextClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(rule_context_get_type ()); + + object_class->finalize = vfolder_context_finalise; + /* override methods */ + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +vfolder_context_init (VfolderContext *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); + + 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, rule_context_next_rule); +} + +static void +vfolder_context_finalise(GtkObject *obj) +{ + VfolderContext *o = (VfolderContext *)obj; + + o = o; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * vfolder_context_new: + * + * Create a new VfolderContext object. + * + * Return value: A new #VfolderContext object. + **/ +VfolderContext * +vfolder_context_new(void) +{ + VfolderContext *o = (VfolderContext *)gtk_type_new(vfolder_context_get_type ()); + return o; +} diff --git a/filter/vfolder-context.h b/filter/vfolder-context.h new file mode 100644 index 0000000000..0bf1b5aaf2 --- /dev/null +++ b/filter/vfolder-context.h @@ -0,0 +1,55 @@ +/* + * 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_CONTEXT_H +#define _VFOLDER_CONTEXT_H + +#include <gtk/gtk.h> + +#include "rule-context.h" + +#define VFOLDER_CONTEXT(obj) GTK_CHECK_CAST (obj, vfolder_context_get_type (), VfolderContext) +#define VFOLDER_CONTEXT_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, vfolder_context_get_type (), VfolderContextClass) +#define IS_VFOLDER_CONTEXT(obj) GTK_CHECK_TYPE (obj, vfolder_context_get_type ()) + +typedef struct _VfolderContext VfolderContext; +typedef struct _VfolderContextClass VfolderContextClass; + +struct _VfolderContext { + RuleContext parent; + struct _VfolderContextPrivate *priv; + +}; + +struct _VfolderContextClass { + RuleContextClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint vfolder_context_get_type (void); +VfolderContext *vfolder_context_new (void); + +/* methods */ + +#endif /* ! _VFOLDER_CONTEXT_H */ + diff --git a/filter/vfolder-editor.c b/filter/vfolder-editor.c new file mode 100644 index 0000000000..90da3c5221 --- /dev/null +++ b/filter/vfolder-editor.c @@ -0,0 +1,336 @@ +/* + * 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-editor.h" +#include "vfolder-context.h" + +#define d(x) + +#if 0 +static void vfolder_editor_class_init (VfolderEditorClass *class); +static void vfolder_editor_init (VfolderEditor *gspaper); +static void vfolder_editor_finalise (GtkObject *obj); + +#define _PRIVATE(x) (((VfolderEditor *)(x))->priv) + +struct _VfolderEditorPrivate { +}; + +static GnomeDialogClass *parent_class; + +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +guint +vfolder_editor_get_type (void) +{ + static guint type = 0; + + if (!type) { + GtkTypeInfo type_info = { + "VfolderEditor", + sizeof(VfolderEditor), + sizeof(VfolderEditorClass), + (GtkClassInitFunc)vfolder_editor_class_init, + (GtkObjectInitFunc)vfolder_editor_init, + (GtkArgSetFunc)NULL, + (GtkArgGetFunc)NULL + }; + + type = gtk_type_unique(gnome_dialog_get_type (), &type_info); + } + + return type; +} + +static void +vfolder_editor_class_init (VfolderEditorClass *class) +{ + GtkObjectClass *object_class; + + object_class = (GtkObjectClass *)class; + parent_class = gtk_type_class(gnome_dialog_get_type ()); + + object_class->finalize = vfolder_editor_finalise; + /* override methods */ + + /* signals */ + + gtk_object_class_add_signals(object_class, signals, LAST_SIGNAL); +} + +static void +vfolder_editor_init (VfolderEditor *o) +{ + o->priv = g_malloc0(sizeof(*o->priv)); +} + +static void +vfolder_editor_finalise(GtkObject *obj) +{ + VfolderEditor *o = (VfolderEditor *)obj; + + ((GtkObjectClass *)(parent_class))->finalize(obj); +} + +/** + * vfolder_editor_new: + * + * Create a new VfolderEditor object. + * + * Return value: A new #VfolderEditor object. + **/ +VfolderEditor * +vfolder_editor_new(void) +{ + VfolderEditor *o = (VfolderEditor *)gtk_type_new(vfolder_editor_get_type ()); + return o; +} +#endif + + + +enum { + BUTTON_ADD, + BUTTON_EDIT, + BUTTON_DELETE, + BUTTON_UP, + BUTTON_DOWN, + BUTTON_LAST +}; + +struct _editor_data { + RuleContext *f; + FilterRule *current; + GtkList *list; + GtkButton *buttons[BUTTON_LAST]; +}; + +static void set_sensitive(struct _editor_data *data); + +static void rule_add(GtkWidget *widget, struct _editor_data *data) +{ + FilterRule *rule; + int result; + GnomeDialog *gd; + GtkWidget *w; + FilterPart *part; + + d(printf("add rule\n")); + /* create a new rule with 1 match and 1 action */ + rule = filter_rule_new(); + + part = rule_context_next_part(data->f, NULL); + filter_rule_add_part(rule, filter_part_clone(part)); + + w = filter_rule_get_widget(rule, data->f); + gd = (GnomeDialog *)gnome_dialog_new("Add Rule", "Ok", "Cancel", NULL); + gtk_box_pack_start((GtkBox *)gd->vbox, w, FALSE, TRUE, 0); + gtk_widget_show((GtkWidget *)gd); + result = gnome_dialog_run_and_close(gd); + if (result == 0) { + GtkListItem *item = (GtkListItem *)gtk_list_item_new_with_label(rule->name); + GList *l = NULL; + + gtk_object_set_data((GtkObject *)item, "rule", rule); + gtk_widget_show((GtkWidget *)item); + l = g_list_append(l, item); + gtk_list_append_items(data->list, l); + gtk_list_select_child(data->list, (GtkWidget *)item); + data->current = rule; + rule_context_add_rule(data->f, rule); + set_sensitive(data); + } else { + gtk_object_unref((GtkObject *)rule); + } +} + +static void rule_edit(GtkWidget *widget, struct _editor_data *data) +{ + GtkWidget *w; + int result; + GnomeDialog *gd; + FilterRule *rule; + int pos; + + d(printf("edit rule\n")); + rule = data->current; + w = filter_rule_get_widget(rule, data->f); + gd = (GnomeDialog *)gnome_dialog_new("Edit VFolder Rule", "Ok", NULL); + gtk_box_pack_start((GtkBox *)gd->vbox, w, FALSE, TRUE, 0); + gtk_widget_show((GtkWidget *)gd); + result = gnome_dialog_run_and_close(gd); + + if (result == 0) { + pos = rule_context_get_rank_rule(data->f, data->current); + if (pos != -1) { + GtkListItem *item = g_list_nth_data(data->list->children, pos); + gtk_label_set_text((GtkLabel *)(((GtkBin *)item)->child), data->current->name); + } + } +} + +static void rule_delete(GtkWidget *widget, struct _editor_data *data) +{ + int pos; + GList *l; + GtkListItem *item; + + d(printf("ddelete rule\n")); + pos = rule_context_get_rank_rule(data->f, data->current); + if (pos != -1) { + rule_context_remove_rule(data->f, data->current); + + item = g_list_nth_data(data->list->children, pos); + l = g_list_append(NULL, item); + gtk_list_remove_items(data->list, l); + g_list_free(l); + + gtk_object_unref((GtkObject *)data->current); + data->current = NULL; + } + set_sensitive(data); +} + +static void rule_move(struct _editor_data *data, int from, int to) +{ + GList *l; + GtkListItem *item; + + d(printf("moving %d to %d\n", from, to)); + rule_context_rank_rule(data->f, data->current, to); + + item = g_list_nth_data(data->list->children, from); + l = g_list_append(NULL, item); + gtk_list_remove_items_no_unref(data->list, l); + gtk_list_insert_items(data->list, l, to); + gtk_list_select_child(data->list, (GtkWidget *)item); + set_sensitive(data); +} + +static void rule_up(GtkWidget *widget, struct _editor_data *data) +{ + int pos; + + d(printf("up rule\n")); + pos = rule_context_get_rank_rule(data->f, data->current); + if (pos>0) { + rule_move(data, pos, pos-1); + } +} + +static void rule_down(GtkWidget *widget, struct _editor_data *data) +{ + int pos; + + d(printf("down rule\n")); + pos = rule_context_get_rank_rule(data->f, data->current); + rule_move(data, pos, pos+1); +} + +static struct { + char *name; + GtkSignalFunc func; +} edit_buttons[] = { + { "rule_add", rule_add }, + { "rule_edit", rule_edit }, + { "rule_delete", rule_delete }, + { "rule_up", rule_up }, + { "rule_down", rule_down }, +}; + +static void +set_sensitive(struct _editor_data *data) +{ + FilterRule *rule = NULL; + int index=-1, count=0; + + while ((rule = rule_context_next_rule(data->f, rule))) { + if (rule == data->current) + index=count; + count++; + } + d(printf("index = %d count=%d\n", index, count)); + count--; + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_EDIT], index != -1); + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_DELETE], index != -1); + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_UP], index > 0); + gtk_widget_set_sensitive((GtkWidget *)data->buttons[BUTTON_DOWN], index >=0 && index<count); +} + +static void +select_rule(GtkWidget *w, GtkWidget *child, struct _editor_data *data) +{ + data->current = gtk_object_get_data((GtkObject *)child, "rule"); + if (data->current) + d(printf("seledct rule: %s\n", data->current->name)); + else + d(printf("bad data?\n")); + set_sensitive(data); +} + +GtkWidget *vfolder_editor_construct (struct _VfolderContext *f) +{ + GladeXML *gui; + GtkWidget *d, *w; + GList *l; + FilterRule *rule = NULL; + struct _editor_data *data; + int i; + + g_assert(IS_VFOLDER_CONTEXT(f)); + + data = g_malloc0(sizeof(*data)); + data->f = (RuleContext *)f; + + gui = glade_xml_new(FILTER_GLADEDIR "/filter.glade", "edit_vfolder"); + d = glade_xml_get_widget (gui, "edit_vfolder"); + gtk_object_set_data_full((GtkObject *)d, "data", data, g_free); + + gtk_window_set_title((GtkWindow *)d, "Edit VFolders"); + 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, "rule_list"); + data->list = (GtkList *)w; + l = NULL; + while ((rule = rule_context_next_rule((RuleContext *)f, rule))) { + GtkListItem *item = (GtkListItem *)gtk_list_item_new_with_label(rule->name); + gtk_object_set_data((GtkObject *)item, "rule", rule); + gtk_widget_show((GtkWidget *)item); + l = g_list_append(l, item); + } + gtk_list_append_items(data->list, l); + gtk_signal_connect((GtkObject *)w, "select_child", select_rule, data); + + set_sensitive(data); + gtk_object_unref((GtkObject *)gui); + + return d; +} diff --git a/filter/vfolder-editor.h b/filter/vfolder-editor.h new file mode 100644 index 0000000000..2ff2b261dc --- /dev/null +++ b/filter/vfolder-editor.h @@ -0,0 +1,61 @@ +/* + * 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_EDITOR_H +#define _VFOLDER_EDITOR_H + +#include <gtk/gtk.h> +#include <libgnomeui/gnome-dialog.h> + +#if 0 +/* NOTE: object stuff not used (yet?), this is just a holder file for a static factory */ + +#define VFOLDER_EDITOR(obj) GTK_CHECK_CAST (obj, vfolder_editor_get_type (), VfolderEditor) +#define VFOLDER_EDITOR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, vfolder_editor_get_type (), VfolderEditorClass) +#define IS_VFOLDER_EDITOR(obj) GTK_CHECK_TYPE (obj, vfolder_editor_get_type ()) + +typedef struct _VfolderEditor VfolderEditor; +typedef struct _VfolderEditorClass VfolderEditorClass; + +struct _VfolderEditor { + GnomeDialog parent; + struct _VfolderEditorPrivate *priv; + +}; + +struct _VfolderEditorClass { + GnomeDialogClass parent_class; + + /* virtual methods */ + + /* signals */ +}; + +guint vfolder_editor_get_type (void); +VfolderEditor *vfolder_editor_new (void); +#endif + +struct _VfolderContext; + +/* methods */ +GtkWidget *vfolder_editor_construct (struct _VfolderContext *f); + +#endif /* ! _VFOLDER_EDITOR_H */ + diff --git a/filter/vfoldertypes.xml b/filter/vfoldertypes.xml index 5363d6bfc4..af763aed2f 100644 --- a/filter/vfoldertypes.xml +++ b/filter/vfoldertypes.xml @@ -1,74 +1,80 @@ <?xml version="1.0"?> <filterdescription> -<ruleset type="match"> -<rule name="from-address"> - <code> - (match-all (header-contains "From" ${sender})) - </code> - <description lang="en">The From address matches <source type="address" name="sender">sender(s)</source>.</description> -</rule> - -<rule name="to-address"> - <code> - (match-all (or (header-contains "To" ${recipient}) - (header-contains "Cc" ${recipient}))) - </code> - <description lang="en">The To or Cc address matches <source type="address" name="recipient">recipients</source>.</description> -</rule> - -<rule name="subject-contains"> - <code> - (match-all (header-contains "Subject" ${words})) - </code> - <description lang="en">The Subject contains <source type="string" name="words">words</source>.</description> -</rule> - -<rule name="body-contains"> - <code> - (match-all (body-contains ${words})) - </code> - <description lang="en">The body contains <source type="string" name="words">words</source>.</description> -</rule> - -<rule name="cc-address"> - <code> - (match-all (header-contains "CC" ${self-email})) - </code> - <description lang="en">I am in the cc list.</description> -</rule> - -</ruleset> - -<ruleset type="except"> -<rule name="except-me"> - <code> - (match-all (not (header-contains "To" ${self-email}))) - </code> - <description language="en">I am the recipient.</description> -</rule> -<rule name="not-body-contains"> - <code> - (match-all (not (body-contains ${words}))) - </code> - <description lang="en">The body does not contain <source type="string" name="words">words</source>.</description> -</rule> -</ruleset> - -<optionset> - <option type="match"> - <description language="en">For matching messages.</description> - </option> - <option type="match"> - <description language="en">Messages from a certain person.</description> - <optionrule type="match" rule="from-address"/> - </option> - <option type="match"> - <description language="en">Messages to a certain address.</description> - <optionrule type="match" rule="to-address"/> - </option> - <option type="match"> - <description language="en">Messages with a given subject.</description> - <optionrule type="match" rule="subject-contains"/> - </option> -</optionset> +<partset> + <part name="sender"> + <title>Sender</title> + <input type="optionlist" name="sender-type"> + <option value="contains"> + <title>contains</title> + <code>(match-all (header-contains "From" ${sender}))</code> + </option> + <option value="not contains"> + <title>does not contain</title> + <code>(match-all (not (header-contains "From" ${sender})))</code> + </option> + </input> + <input type="string" name="sender"/> + </part> + <part name="to"> + <title>Recipients</title> + <input type="optionlist" name="recipient-type"> + <option value="contains"> + <title>contains</title> + <code> + (match-all (or (header-contains "To" ${recipient}) + (header-contains "Cc" ${recipient}))) + </code> + </option> + <option value="not contains"> + <title>does not contain</title> + <code> + (match-all (not (or + (header-contains "To" ${recipient}) + (header-contains "Cc" ${recipient})))) + </code> + </option> + </input> + <input type="address" name="recipient"/> + </part> + <part name="subject"> + <title>Subject</title> + <input type="optionlist" name="subject-type"> + <option value="contains"> + <title>contains</title> + <code> + (match-all (header-contains "Subject" ${subject})) + </code> + </option> + <option value="not contains"> + <title>does not contain</title> + <code> + (match-all (not (header-contains "Subject" ${subject}))) + </code> + </option> + </input> + <input type="string" name="subject"/> + </part> + <part name="body"> + <title>Message Body</title> + <input type="optionlist" name="body-type"> + <option value="contains"> + <title>contains</title> + <code> + (body-contains ${word}) + </code> + </option> + <option value="not contains"> + <title>does not contain</title> + <code> + (not (body-contains "Subject" ${word})) + </code> + </option> + </input> + <input type="string" name="word"/> + </part> + <part name="sexp"> + <title>Expression</title> + <input type="code" name="code"/> + </part> +</partset> </filterdescription> |