From 7cf30eb79276d4f255c1d603e2c203bb054cf50e Mon Sep 17 00:00:00 2001 From: Peter Williams Date: Thu, 17 Aug 2000 17:42:21 +0000 Subject: Filtering on demand! booyeah! svn path=/trunk/; revision=4864 --- mail/ChangeLog | 53 +++++++++++++++++++++++++++++++++++++ mail/folder-browser-factory.c | 61 ++++++++++++++++++++++++++++++++++++++++++- mail/folder-browser.c | 19 ++++++++++++++ mail/folder-browser.h | 15 ++++++++--- mail/mail-autofilter.c | 2 +- mail/mail-callbacks.c | 19 +++++++++++++- mail/mail-tools.c | 10 ++++--- mail/mail-tools.h | 6 +++++ mail/mail-vfolder.c | 2 +- mail/mail.h | 2 ++ mail/message-list.c | 20 ++++++++++++++ 11 files changed, 197 insertions(+), 12 deletions(-) (limited to 'mail') 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 + + 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 * 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 @@ -52,6 +52,61 @@ static GnomeUIInfo gnome_toolbar [] = { GNOMEUIINFO_END }; +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 #include "camel/camel-stream.h" #include +#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 +#include /*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) { -- cgit v1.2.3