aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
Diffstat (limited to 'mail')
-rw-r--r--mail/ChangeLog53
-rw-r--r--mail/folder-browser-factory.c61
-rw-r--r--mail/folder-browser.c19
-rw-r--r--mail/folder-browser.h15
-rw-r--r--mail/mail-autofilter.c2
-rw-r--r--mail/mail-callbacks.c19
-rw-r--r--mail/mail-tools.c10
-rw-r--r--mail/mail-tools.h6
-rw-r--r--mail/mail-vfolder.c2
-rw-r--r--mail/mail.h2
-rw-r--r--mail/message-list.c20
11 files changed, 197 insertions, 12 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 0bb4298961..1cbdce64c8 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,56 @@
+2000-08-17 Peter Williams <peterw@helixcode.com>
+
+ Implement filtering on demand.
+
+ * folder-browser-factory.c (register_ondemand): New function. Callback
+ to put the filter-on-demand filters into the bonobo UIH;
+ (create_ondemand_hooks): New function. Read in our on-demand filters
+ and hook them into the UI.
+ (remove_ondemand_hooks): New function. Remove the hooks when done with
+ them.
+ (control_activate): Call create_ondemand_hooks()
+ (control_deactivate): Call remove_ondemand_hooks();
+
+ * mail-callbacks.c (run_filter_ondemand): New function. Callback
+ for running a filter on demand.
+ (filter_edit): Pass NULLs as the new arguments to rule_context_load.
+
+ * mail.h: Prototype run_filter_ondemand();
+
+ * folder-browser.c (oc_destroy): New function. Iterator to destroy
+ an fb_ondemand_closure.
+ (folder_browser_destroy): Free the data associated with the ondemand
+ menu items.
+ (my_folder_browser_init): Clear the filter_ variables.
+
+ * folder-browser.h: Two new members of FolderBrowser: filter_menu_paths,
+ a list of fb_ondemand_closures so that the menu items can be freed and
+ removed; and filter_context, a permanently loaded FilterContext for
+ running the ondemand filters. Prototype the new fb_ondemand_closure
+ structure.
+
+ * mail-autofilter.c (filter_gui_add_from_message): Pass NULLs as the
+ new parameters to rule_context_load (we don't need to hook up ondemand
+ menu items...)
+
+ * mail-tools.c (mail_tool_filter_get_folder_func): Rename from
+ get_folder_func() and make public so mail-callbacks.c:run_filter_ondemand()
+ can use it too.
+ (mail_tool_filter_contents_into): Use the new name of get_folder_func.
+ Pass NULLs as the extra arguments to rule_context_load. Pass the
+ extra source type to filter_driver_run (only use INCOMING).
+
+ * mail-tools.h: Publicly prototype mail_tool_filter_get_folder_func()
+
+ * mail-vfolder.c (vfolder_create_storage): Pass NULLs as the extra
+ arguments to rule_context_load.
+
+ * message-list.c (message_list_init): Free our strdup'd uids when
+ the table model gets destroyed.
+ (nuke_uids): New function. Walk the tree nodes to free the uids.
+ (nuke_uids_cb): New callback for nuke_uids();
+
+
2000-08-16 Richard Hult <rhult@hem.passagen.se>
* mail-ops.c (cleanup_display_message): Use a configurable timeout.
diff --git a/mail/folder-browser-factory.c b/mail/folder-browser-factory.c
index 2c29d78f26..9a71dbe8ab 100644
--- a/mail/folder-browser-factory.c
+++ b/mail/folder-browser-factory.c
@@ -53,6 +53,61 @@ static GnomeUIInfo gnome_toolbar [] = {
};
static void
+register_ondemand (RuleContext *f, FilterRule *rule, gpointer data)
+{
+ FolderBrowser *fb = FOLDER_BROWSER (data);
+ BonoboUIHandler *uih = gtk_object_get_data (GTK_OBJECT (fb), "uih");
+ gchar *text;
+ struct fb_ondemand_closure *oc;
+
+ oc = g_new (struct fb_ondemand_closure, 1);
+ oc->rule = rule;
+ oc->fb = fb;
+ oc->path = g_strdup_printf ("/Actions/Filter-%s", rule->name);
+
+ if (fb->filter_menu_paths == NULL)
+ bonobo_ui_handler_menu_new_separator (uih, "/Actions/separator2", -1);
+
+ text = g_strdup_printf (_("Run filter \"%s\""), rule->name);
+ fb->filter_menu_paths = g_slist_prepend (fb->filter_menu_paths, oc);
+
+ bonobo_ui_handler_menu_new_item (uih, oc->path, text,
+ NULL, -1,
+ BONOBO_UI_HANDLER_PIXMAP_NONE,
+ 0,
+ 0, 0, run_filter_ondemand, oc);
+ g_free (text);
+}
+
+static void
+create_ondemand_hooks (FolderBrowser *fb, BonoboUIHandler *uih)
+{
+ gchar *system, *user;
+
+ user = g_strdup_printf ("%s/filters.xml", evolution_dir);
+ system = EVOLUTION_DATADIR "/evolution/filtertypes.xml";
+ fb->filter_context = filter_context_new();
+ gtk_object_set_data (GTK_OBJECT (fb), "uih", uih);
+ rule_context_load ((RuleContext *) fb->filter_context, system, user,
+ register_ondemand, fb);
+ gtk_object_remove_data (GTK_OBJECT (fb), "uih");
+ g_free (user);
+}
+
+static void
+remove_ondemand_hooks (FolderBrowser *fb, BonoboUIHandler *uih)
+{
+ GSList *iter;
+ struct fb_ondemand_closure *oc;
+
+ for (iter = fb->filter_menu_paths; iter; iter = iter->next) {
+ oc = (struct fb_ondemand_closure *) iter->data;
+
+ bonobo_ui_handler_menu_remove (uih, oc->path);
+ }
+}
+
+static void
control_activate (BonoboControl *control, BonoboUIHandler *uih,
FolderBrowser *fb)
{
@@ -143,7 +198,9 @@ control_activate (BonoboControl *control, BonoboUIHandler *uih,
BONOBO_UI_HANDLER_PIXMAP_NONE,
0,
0, 0, configure_folder, folder_browser);
-
+
+ create_ondemand_hooks (fb, uih);
+
toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL,
GTK_TOOLBAR_BOTH);
@@ -196,6 +253,8 @@ control_deactivate (BonoboControl *control,
bonobo_ui_handler_menu_remove (uih, "/Tools/Configure Folder");
bonobo_ui_handler_dock_remove (uih, toolbar_name);
g_free (toolbar_name);
+
+ remove_ondemand_hooks (fb, uih);
}
static void
diff --git a/mail/folder-browser.c b/mail/folder-browser.c
index 4707351f8c..8534378143 100644
--- a/mail/folder-browser.c
+++ b/mail/folder-browser.c
@@ -33,6 +33,14 @@
static GtkObjectClass *folder_browser_parent_class;
+static void oc_destroy (gpointer obj, gpointer user)
+{
+ struct fb_ondemand_closure *oc = (struct fb_ondemand_closure *) obj;
+
+ g_free (oc->path);
+ g_free (oc);
+}
+
static void
folder_browser_destroy (GtkObject *object)
{
@@ -60,6 +68,14 @@ folder_browser_destroy (GtkObject *object)
if (folder_browser->mail_display)
gtk_widget_destroy (GTK_WIDGET (folder_browser->mail_display));
+ if (folder_browser->filter_context)
+ gtk_object_unref (GTK_OBJECT (folder_browser->filter_context));
+
+ if (folder_browser->filter_menu_paths) {
+ g_slist_foreach (folder_browser->filter_menu_paths, oc_destroy, NULL);
+ g_slist_free (folder_browser->filter_menu_paths);
+ }
+
folder_browser_parent_class->destroy (object);
}
@@ -402,6 +418,9 @@ my_folder_browser_init (GtkObject *object)
gtk_signal_connect (GTK_OBJECT (fb->message_list->etable),
"key_press", GTK_SIGNAL_FUNC (etable_key), fb);
+ fb->filter_menu_paths = NULL;
+ fb->filter_context = NULL;
+
folder_browser_gui_init (fb);
}
diff --git a/mail/folder-browser.h b/mail/folder-browser.h
index 53bcb5b925..86c1c6f149 100644
--- a/mail/folder-browser.h
+++ b/mail/folder-browser.h
@@ -8,6 +8,8 @@
#include <gtk/gtktable.h>
#include "camel/camel-stream.h"
#include <bonobo/bonobo-property-bag.h>
+#include "filter/filter-rule.h"
+#include "filter/filter-context.h" /*eek*/
#include "message-list.h"
#include "mail-display.h"
#include "shell/Evolution.h"
@@ -19,7 +21,6 @@
#define IS_FOLDER_BROWSER(o) (GTK_CHECK_TYPE ((o), FOLDER_BROWSER_TYPE))
#define IS_FOLDER_BROWSER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), FOLDER_BROWSER_TYPE))
-
struct _FolderBrowser {
GtkTable parent;
@@ -44,7 +45,10 @@ struct _FolderBrowser {
GtkWidget *search_entry;
gboolean preview_shown;
-
+
+ /* Stuff to allow on-demand filtering */
+ GSList *filter_menu_paths;
+ FilterContext *filter_context;
};
@@ -52,8 +56,11 @@ typedef struct {
GtkTableClass parent_class;
} FolderBrowserClass;
-
-
+struct fb_ondemand_closure {
+ FilterRule *rule;
+ FolderBrowser *fb;
+ gchar *path;
+};
GtkType folder_browser_get_type (void);
GtkWidget *folder_browser_new (void);
diff --git a/mail/mail-autofilter.c b/mail/mail-autofilter.c
index 4aa246666a..2de013a448 100644
--- a/mail/mail-autofilter.c
+++ b/mail/mail-autofilter.c
@@ -255,7 +255,7 @@ filter_gui_add_from_message(CamelMimeMessage *msg, int flags)
fc = filter_context_new();
userrules = g_strdup_printf("%s/filters.xml", evolution_dir);
systemrules = g_strdup_printf("%s/evolution/filtertypes.xml", EVOLUTION_DATADIR);
- rule_context_load((RuleContext *)fc, systemrules, userrules);
+ rule_context_load((RuleContext *)fc, systemrules, userrules, NULL, NULL);
rule = filter_rule_from_message(fc, msg, flags);
rule_context_add_rule_gui((RuleContext *)fc, rule, "Add Filter Rule", userrules);
g_free (userrules);
diff --git a/mail/mail-callbacks.c b/mail/mail-callbacks.c
index 2156145d59..33b44c1c6c 100644
--- a/mail/mail-callbacks.c
+++ b/mail/mail-callbacks.c
@@ -525,7 +525,7 @@ filter_edit (BonoboUIHandler *uih, void *user_data, const char *path)
fc = filter_context_new();
user = g_strdup_printf ("%s/filters.xml", evolution_dir);
system = g_strdup_printf ("%s/evolution/filtertypes.xml", EVOLUTION_DATADIR);
- rule_context_load ((RuleContext *)fc, system, user);
+ rule_context_load ((RuleContext *)fc, system, user, NULL, NULL);
g_free (user);
g_free (system);
@@ -634,4 +634,21 @@ edit_message (BonoboUIHandler *uih, void *user_data, const char *path)
edit_msg (NULL, user_data);
}
+void
+run_filter_ondemand (BonoboUIHandler *uih, gpointer user_data, const char *path)
+{
+ struct fb_ondemand_closure *oc = (struct fb_ondemand_closure *) user_data;
+ FilterDriver *d;
+
+ if (oc->fb->folder == NULL)
+ return;
+
+ printf ("Running filter \"%s\"\n", oc->rule->name);
+ d = filter_driver_new (oc->fb->filter_context,
+ mail_tool_filter_get_folder_func,
+ NULL);
+ filter_driver_run (d, oc->fb->folder, oc->fb->folder,
+ FILTER_SOURCE_DEMAND, TRUE,
+ NULL, NULL);
+}
diff --git a/mail/mail-tools.c b/mail/mail-tools.c
index 18996ed946..2d10411f91 100644
--- a/mail/mail-tools.c
+++ b/mail/mail-tools.c
@@ -487,7 +487,8 @@ mail_tool_fetch_mail_into_searchable (const char *source_url, gboolean keep_on_s
return search_folder;
}
-static CamelFolder *get_folder_func (FilterDriver *d, const char *uri, void *data)
+CamelFolder *
+mail_tool_filter_get_folder_func (FilterDriver *d, const char *uri, void *data)
{
return mail_tool_uri_to_folder_noex (uri);
}
@@ -506,17 +507,18 @@ mail_tool_filter_contents_into (CamelFolder *source, CamelFolder *dest,
userrules = g_strdup_printf ("%s/filters.xml", evolution_dir);
systemrules = g_strdup_printf ("%s/evolution/filtertypes.xml", EVOLUTION_DATADIR);
fc = filter_context_new();
- rule_context_load ((RuleContext *)fc, systemrules, userrules);
+ rule_context_load ((RuleContext *)fc, systemrules, userrules, NULL, NULL);
g_free (userrules);
g_free (systemrules);
- filter = filter_driver_new (fc, get_folder_func, 0);
+ filter = filter_driver_new (fc, mail_tool_filter_get_folder_func, 0);
if (hook_func)
camel_object_hook_event (CAMEL_OBJECT (dest), "folder_changed",
hook_func, hook_data);
- filter_driver_run (filter, source, dest, TRUE, hook_func, hook_data);
+ filter_driver_run (filter, source, dest, FILTER_SOURCE_INCOMING,
+ TRUE, hook_func, hook_data);
camel_folder_sync (CAMEL_FOLDER (source), TRUE, ex);
camel_folder_sync (CAMEL_FOLDER (dest), TRUE, ex);
diff --git a/mail/mail-tools.h b/mail/mail-tools.h
index 106a971530..3aba7dde2c 100644
--- a/mail/mail-tools.h
+++ b/mail/mail-tools.h
@@ -26,6 +26,7 @@
#define MAIL_TOOLS_H
#include <camel/camel.h>
+#include <filter/filter-driver.h> /*eek*/
/* A global recursive lock on Camel */
void mail_tool_camel_lock_up (void);
@@ -106,4 +107,9 @@ mail_tool_uri_to_folder_noex (const char *uri);
GHashTable *
mail_lookup_url_table (CamelMimeMessage *mime_message);
+/* Appropriate for filter_driver_run */
+CamelFolder *
+mail_tool_filter_get_folder_func (FilterDriver *d, const char *uri, void *data);
+
+
#endif
diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c
index ba1a69517a..b33c5d9660 100644
--- a/mail/mail-vfolder.c
+++ b/mail/mail-vfolder.c
@@ -163,7 +163,7 @@ vfolder_create_storage(EvolutionShellComponent *shell_component)
context = vfolder_context_new();
printf("loading rules %s %s\n", system, user);
- if (rule_context_load((RuleContext *)context, system, user) != 0) {
+ if (rule_context_load((RuleContext *)context, system, user, NULL, NULL) != 0) {
g_warning("cannot load vfolders: %s\n", ((RuleContext *)context)->error);
}
g_free(user);
diff --git a/mail/mail.h b/mail/mail.h
index 03045e1075..8a67d745fb 100644
--- a/mail/mail.h
+++ b/mail/mail.h
@@ -80,6 +80,8 @@ void mail_reply (CamelFolder *folder, CamelMimeMessage *msg, const char *uid, gb
void composer_send_cb (EMsgComposer *composer, gpointer data);
void mail_print_msg (MailDisplay *md);
+void run_filter_ondemand (BonoboUIHandler *uih, gpointer user_data, const char *path);
+
/* mail view */
GtkWidget *mail_view_create (CamelFolder *source, const char *uid, CamelMimeMessage *msg);
diff --git a/mail/message-list.c b/mail/message-list.c
index f9772fa7b0..7499cbb651 100644
--- a/mail/message-list.c
+++ b/mail/message-list.c
@@ -71,6 +71,7 @@ static gint on_right_click (ETableScrolled *table, gint row, gint col, GdkEvent
static void on_double_click (ETableScrolled *table, gint row, MessageList *list);
static void select_msg (MessageList *message_list, gint row);
static char *filter_date (const void *data);
+static void nuke_uids (GtkObject *o);
static struct {
char **image_base;
@@ -591,6 +592,8 @@ message_list_init (GtkObject *object)
ml_tree_is_cell_editable,
message_list);
e_tree_model_root_node_set_visible ((ETreeModel *)message_list->table_model, FALSE);
+ gtk_signal_connect (GTK_OBJECT (message_list->table_model), "destroy",
+ (GtkSignalFunc) nuke_uids, NULL);
message_list_init_renderers (message_list);
message_list_init_header (message_list);
@@ -846,6 +849,23 @@ build_subtree (MessageList *ml, ETreePath *parent,
}
}
+static gboolean
+nuke_uids_cb (GNode *node, gpointer data)
+{
+ g_free (e_tree_model_node_get_data (E_TREE_MODEL (data), node));
+ return FALSE;
+}
+
+static void
+nuke_uids (GtkObject *o)
+{
+ ETreeModel *etm = E_TREE_MODEL (o);
+
+ g_node_traverse (etm->root, G_IN_ORDER,
+ G_TRAVERSE_ALL, 0,
+ nuke_uids_cb, etm);
+}
+
static void
build_flat (MessageList *ml, GPtrArray *uids)
{