From 79154e4ac8759f24656fe55253b25d1c84834337 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Mon, 9 Oct 2000 12:57:36 +0000 Subject: New widget, full search dialogue for mail. 2000-10-06 Not Zed * mail-search-dialogue.c: New widget, full search dialogue for mail. * folder-browser.c (search_set): If we click on custom search, run the full search dialogue. (folder_browser_gui_init): Add a button to perform a full search. (search_full): Bring up the mail search dialogue asynchronously. (search_full_clicked): Handle search options. (folder_browser_destroy): Free the saved rule if there is one there. (search_options[]): Added a custom option option - brings up the full search dialogue. (search_set): Disable the search entry if we are doing a full search. * mail-vfolder.c (vfolder_create_storage): Yay, finally depeterised this stuff. (vfolder_uri_to_folder): Removed an irrelevant comment. * mail-callbacks.c (filter_edit): And here. * mail-ops.c (do_fetch_mail): And here too. * mail-autofilter.c (filter_gui_add_from_message): Fixed call to context_load. (filter_gui_add_for_mailing_list): And here too. * folder-browser-factory.c (create_ondemand_hooks): Remove that ondemand callback snot. 2000-10-05 Not Zed * message-list.c (message_list_init_etable): Build the etable once we know what folder we are going to use. (save_header_state): Save the header spec to a cache file. (message_list_destroy): Save the header spec. (message_list_setup_etable): Setup the etable spec for this folder, from a saved version if one exists, or to suit the folder type (sent/received). (message_list_set_folder): Setup the etable here once we have a folder. svn path=/trunk/; revision=5798 --- mail/ChangeLog | 44 ++++++++++++++++ mail/Makefile.am | 2 + mail/folder-browser-factory.c | 15 +++--- mail/folder-browser.c | 114 ++++++++++++++++++++++++++++++++++++------ mail/folder-browser.h | 3 +- mail/mail-autofilter.c | 4 +- mail/mail-callbacks.c | 2 +- mail/mail-format.c | 5 +- mail/mail-ops.c | 2 +- mail/mail-vfolder.c | 21 ++------ mail/message-list.c | 57 ++++++++++++++++++++- mail/message-list.h | 2 +- 12 files changed, 221 insertions(+), 50 deletions(-) (limited to 'mail') diff --git a/mail/ChangeLog b/mail/ChangeLog index 42e30b5e00..c78fdbf918 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,46 @@ +2000-10-06 Not Zed + + * mail-search-dialogue.c: New widget, full search dialogue for + mail. + + * folder-browser.c (search_set): If we click on custom search, run + the full search dialogue. + (folder_browser_gui_init): Add a button to perform a full search. + (search_full): Bring up the mail search dialogue asynchronously. + (search_full_clicked): Handle search options. + (folder_browser_destroy): Free the saved rule if there is one + there. + (search_options[]): Added a custom option option - brings up the + full search dialogue. + (search_set): Disable the search entry if we are doing a full + search. + + * mail-vfolder.c (vfolder_create_storage): Yay, finally + depeterised this stuff. + (vfolder_uri_to_folder): Removed an irrelevant comment. + + * mail-callbacks.c (filter_edit): And here. + + * mail-ops.c (do_fetch_mail): And here too. + + * mail-autofilter.c (filter_gui_add_from_message): Fixed call to + context_load. + (filter_gui_add_for_mailing_list): And here too. + + * folder-browser-factory.c (create_ondemand_hooks): Remove that + ondemand callback snot. + +2000-10-05 Not Zed + + * message-list.c (message_list_init_etable): Build the etable once + we know what folder we are going to use. + (save_header_state): Save the header spec to a cache file. + (message_list_destroy): Save the header spec. + (message_list_setup_etable): Setup the etable spec for this + folder, from a saved version if one exists, or to suit the folder + type (sent/received). + (message_list_set_folder): Setup the etable here once we have a folder. + 2000-10-09 Michael Meeks * message-list.c (message_list_toggle_threads): re-write. @@ -146,6 +189,7 @@ * mail-ops.c (do_scan_subfolders): Don't try to add_folders if get_folder_info returned NULL. +>>>>>>> 1.611 2000-10-04 Not Zed * message-list.c (message_list_init_header): Fix the attachment diff --git a/mail/Makefile.am b/mail/Makefile.am index eaefe9f32b..fb68f7a7b0 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -65,6 +65,8 @@ evolution_mail_SOURCES = \ mail-mlist-magic.h \ mail-ops.c \ mail-ops.h \ + mail-search-dialogue.c \ + mail-search-dialogue.h \ mail-summary.c \ mail-summary.h \ mail-threads.c \ diff --git a/mail/folder-browser-factory.c b/mail/folder-browser-factory.c index 7f590465ea..1bc493b381 100644 --- a/mail/folder-browser-factory.c +++ b/mail/folder-browser-factory.c @@ -32,10 +32,8 @@ static GList *control_list = NULL; static void -register_ondemand (RuleContext *f, FilterRule *rule, gpointer data) +register_ondemand (RuleContext *f, FilterRule *rule, FolderBrowser *fb, BonoboUIComponent *uic) { - FolderBrowser *fb = FOLDER_BROWSER (data); - BonoboUIComponent *uic = gtk_object_get_data (GTK_OBJECT (fb), "uih"); BonoboUIHandler *uih; gchar *text; struct fb_ondemand_closure *oc; @@ -67,14 +65,15 @@ static void create_ondemand_hooks (FolderBrowser *fb, BonoboUIComponent *uic) { gchar *system, *user; - + FilterRule *rule = NULL; + 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", uic); - rule_context_load ((RuleContext *) fb->filter_context, system, user, - register_ondemand, fb); - gtk_object_remove_data (GTK_OBJECT (fb), "uih"); + rule_context_load ((RuleContext *) fb->filter_context, system, user); + while ( (rule = rule_context_next_rule((RuleContext *)fb->filter_context, rule)) != NULL ) { + register_ondemand((RuleContext *)fb->filter_context, rule, fb, uic); + } g_free (user); } diff --git a/mail/folder-browser.c b/mail/folder-browser.c index 6530929b42..9518ff8e7b 100644 --- a/mail/folder-browser.c +++ b/mail/folder-browser.c @@ -27,6 +27,8 @@ #include "filter/filter-option.h" #include "filter/filter-input.h" +#include "mail-search-dialogue.h" + #include "mail-local.h" #include "mail-config.h" @@ -53,12 +55,14 @@ folder_browser_destroy (GtkObject *object) folder_browser = FOLDER_BROWSER (object); CORBA_exception_init (&ev); - + + if (folder_browser->search_full) + gtk_object_unref((GtkObject *)folder_browser->search_full); + if (folder_browser->shell != CORBA_OBJECT_NIL) CORBA_Object_release (folder_browser->shell, &ev); - - if (folder_browser->uri) - g_free (folder_browser->uri); + + g_free (folder_browser->uri); if (folder_browser->folder) { mail_do_sync_folder (folder_browser->folder); @@ -135,6 +139,7 @@ static char * search_options[] = { "Subject contains", "Body does not contain", "Subject does not contain", + "Custom search", NULL }; @@ -146,8 +151,55 @@ static char * search_string[] = { "(body-contains %s)", "(match-all (header-contains \"Subject\" %s)", "(match-all (not (body-contains %s)))", - "(match-all (not (header-contains \"Subject\" %s)))" + "(match-all (not (header-contains \"Subject\" %s)))", + "%s", }; +#define CUSTOM_SEARCH_ID (5) + +static void +search_full_clicked(MailSearchDialogue *msd, guint button, FolderBrowser *fb) +{ + char *query; + + switch (button) { + case 0: /* 'ok' */ + case 1: /* 'search' */ + query = mail_search_dialogue_get_query(msd); + mail_do_regenerate_messagelist(fb->message_list, query); + g_free(query); + /* save the search as well */ + if (fb->search_full) + gtk_object_unref((GtkObject *)fb->search_full); + fb->search_full = msd->rule; + gtk_object_ref((GtkObject *)fb->search_full); + if (button == 0) + gnome_dialog_close((GnomeDialog *)msd); + break; + case 2: /* 'cancel' */ + gnome_dialog_close((GnomeDialog *)msd); + case -1: /* dialogue closed */ + mail_do_regenerate_messagelist(fb->message_list, 0); + /* reset the search buttons state */ + gtk_menu_set_active(GTK_MENU(GTK_OPTION_MENU(fb->search_menu)->menu), 0); + gtk_widget_set_sensitive(fb->search_entry, TRUE); + break; + } +} + +/* bring up the 'full search' dialogue and let the user use that to search with */ +static void +search_full(GtkWidget *w, FolderBrowser *fb) +{ + MailSearchDialogue *msd; + + /* make search dialogue thingy match */ + gtk_menu_set_active(GTK_MENU(GTK_OPTION_MENU(fb->search_menu)->menu), CUSTOM_SEARCH_ID); + gtk_widget_set_sensitive(fb->search_entry, FALSE); + + msd = mail_search_dialogue_new_with_rule(fb->search_full); + gtk_signal_connect((GtkObject *)msd, "clicked", search_full_clicked, fb); + gtk_widget_show((GtkWidget*)msd); +} static void search_set(FolderBrowser *fb) @@ -158,16 +210,23 @@ search_set(FolderBrowser *fb) int index; char *text; + widget = gtk_menu_get_active (GTK_MENU(GTK_OPTION_MENU(fb->search_menu)->menu)); + index = (int)gtk_object_get_data((GtkObject *)widget, "search_option"); + if (index == CUSTOM_SEARCH_ID) { + search_full(NULL, fb); + return; + } + gtk_widget_set_sensitive(fb->search_entry, TRUE); + text = e_utf8_gtk_entry_get_text((GtkEntry *)fb->search_entry); if (text == NULL || text[0] == 0) { - if (text) g_free (text); + if (text) + g_free(text); mail_do_regenerate_messagelist (fb->message_list, NULL); return; } - widget = gtk_menu_get_active (GTK_MENU(GTK_OPTION_MENU(fb->search_menu)->menu)); - index = (int)gtk_object_get_data((GtkObject *)widget, "search_option"); if (index > sizeof(search_string)/sizeof(search_string[0])) index = 0; str = search_string[index]; @@ -242,18 +301,39 @@ search_save(GtkWidget *w, FolderBrowser *fb) text = e_utf8_gtk_entry_get_text((GtkEntry *)fb->search_entry); - if (text == NULL || text[0] == 0) { - if (text) g_free (text); - return; - } - widget = gtk_menu_get_active (GTK_MENU(GTK_OPTION_MENU(fb->search_menu)->menu)); index = (int)gtk_object_get_data((GtkObject *)widget, "search_option"); + + /* some special case code for the custom search position */ + if (index == CUSTOM_SEARCH_ID) { + g_free(text); + text = g_strdup("Custom"); + } else { + if (text == NULL || text[0] == 0) { + g_free (text); + return; + } + } + rule = vfolder_rule_new(); ((FilterRule *)rule)->grouping = FILTER_GROUP_ANY; vfolder_rule_add_source(rule, fb->uri); filter_rule_set_name((FilterRule *)rule, text); switch(index) { + case 5: /* custom search */ + if (fb->search_full) { + GList *partl; + + /* copy the parts from the search rule to the vfolder rule */ + partl = fb->search_full->parts; + while (partl) { + FilterPart *old = partl->data; + part = filter_part_clone(old); + filter_rule_add_part((FilterRule *)rule, part); + partl = g_list_next(partl); + } + break; + } default: /* header or body contains */ index = 0; case 1: case 2: @@ -290,6 +370,7 @@ search_save(GtkWidget *w, FolderBrowser *fb) element = filter_part_find_element(part, "subject"); filter_input_set_value((FilterInput *)element, text); break; + } vfolder_gui_add_rule(rule); @@ -380,7 +461,7 @@ static void folder_browser_gui_init (FolderBrowser *fb) { GtkWidget *hbox, *label; - GtkButton *button; + GtkButton *button, *searchbutton; /* * The panned container @@ -402,16 +483,20 @@ folder_browser_gui_init (FolderBrowser *fb) gtk_widget_show(fb->search_entry); gtk_signal_connect(GTK_OBJECT (fb->search_entry), "activate", search_activate, fb); /* gtk_signal_connect(fb->search_entry, "changed", search_activate, fb); */ + searchbutton = (GtkButton *)gtk_button_new_with_label(_("Full Search")); + gtk_widget_show((GtkWidget *)searchbutton); label = gtk_label_new(_("Search")); gtk_widget_show(label); fb->search_menu = create_option_menu(search_options, 0, fb); button = (GtkButton *)gtk_button_new_with_label(_("Save")); gtk_widget_show((GtkWidget *)button); gtk_signal_connect((GtkObject *)button, "clicked", search_save, fb); + gtk_signal_connect((GtkObject *)searchbutton, "clicked", search_full, fb); gtk_box_pack_end((GtkBox *)hbox, (GtkWidget *)button, FALSE, FALSE, 3); gtk_box_pack_end((GtkBox *)hbox, fb->search_entry, FALSE, FALSE, 3); gtk_box_pack_end((GtkBox *)hbox, fb->search_menu, FALSE, FALSE, 3); gtk_box_pack_end((GtkBox *)hbox, label, FALSE, FALSE, 3); + gtk_box_pack_end((GtkBox *)hbox, (GtkWidget *)searchbutton, FALSE, FALSE, 3); gtk_table_attach ( GTK_TABLE (fb), hbox, 0, 1, 0, 1, @@ -423,7 +508,6 @@ folder_browser_gui_init (FolderBrowser *fb) e_paned_add1 (E_PANED (fb->vpaned), fb->message_list_w); gtk_widget_show (fb->message_list_w); - /* (jwise) <-- for searching purposes :) */ gtk_signal_connect (GTK_OBJECT (fb->message_list_w), "size_allocate", GTK_SIGNAL_FUNC (fb_resize_cb), NULL); diff --git a/mail/folder-browser.h b/mail/folder-browser.h index 14c75c3367..0e82ba2a49 100644 --- a/mail/folder-browser.h +++ b/mail/folder-browser.h @@ -43,7 +43,8 @@ struct _FolderBrowser { GtkWidget *vpaned; GtkWidget *search_menu; GtkWidget *search_entry; - + FilterRule *search_full; /* if we have a full search active */ + gboolean preview_shown; /* Stuff to allow on-demand filtering */ diff --git a/mail/mail-autofilter.c b/mail/mail-autofilter.c index e7c9f8997c..81ed429e40 100644 --- a/mail/mail-autofilter.c +++ b/mail/mail-autofilter.c @@ -278,7 +278,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, NULL, NULL); + rule_context_load((RuleContext *)fc, systemrules, userrules); rule = filter_rule_from_message(fc, msg, flags); rule_context_add_rule_gui((RuleContext *)fc, rule, _("Add Filter Rule"), userrules); g_free (userrules); @@ -309,7 +309,7 @@ filter_gui_add_for_mailing_list (CamelMimeMessage *msg, 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, NULL, NULL); + rule_context_load((RuleContext *)fc, systemrules, userrules); rule = (FilterRule *) filter_filter_new (); diff --git a/mail/mail-callbacks.c b/mail/mail-callbacks.c index 35d59b688f..91afe99a93 100644 --- a/mail/mail-callbacks.c +++ b/mail/mail-callbacks.c @@ -696,7 +696,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, NULL, NULL); + rule_context_load ((RuleContext *)fc, system, user); g_free (user); g_free (system); diff --git a/mail/mail-format.c b/mail/mail-format.c index 5d7cb1f695..8d690a1c84 100644 --- a/mail/mail-format.c +++ b/mail/mail-format.c @@ -599,9 +599,8 @@ write_headers (CamelMimeMessage *message, MailDisplay *md) md->html, md->stream); g_free (string); - recipients = camel_mime_message_get_recipients ( - message, CAMEL_RECIPIENT_TYPE_CC); - string = camel_address_encode (CAMEL_ADDRESS (recipients)); + recipients = camel_mime_message_get_recipients(message, CAMEL_RECIPIENT_TYPE_CC); + string = camel_address_encode(CAMEL_ADDRESS(recipients)); if (string) { write_field_to_stream ("Cc:", string, TRUE, md->html, md->stream); diff --git a/mail/mail-ops.c b/mail/mail-ops.c index 59cf938840..ff4ff8ed1b 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -91,7 +91,7 @@ mail_load_evolution_rule_context () 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, NULL, NULL); + rule_context_load ((RuleContext *)fc, systemrules, userrules); g_free (userrules); g_free (systemrules); diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index 40e3cd7f11..a26c2986fc 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -87,16 +87,11 @@ vfolder_refresh(void) g_free(info->query); info->query = g_strdup(expr->str); - /*uri = g_strdup_printf("vfolder:%s/vfolder/%s?%s", evolution_dir, info->name, info->query);*/ uri = g_strdup_printf("vfolder:%s", info->name); path = g_strdup_printf("/%s", info->name); evolution_storage_removed_folder(vfolder_storage, path); - evolution_storage_new_folder (vfolder_storage, - path, - g_basename (path), - "mail", - uri, - info->name); + evolution_storage_new_folder(vfolder_storage, path, g_basename(path), + "mail", uri, info->name); g_free(uri); g_free(path); } @@ -106,15 +101,10 @@ vfolder_refresh(void) info->query = g_strdup(expr->str); d(printf("Adding new vfolder: %s %s\n", rule->name, expr->str)); - /*uri = g_strdup_printf("vfolder:%s/vfolder/%s?%s", evolution_dir, info->name, info->query);*/ uri = g_strdup_printf("vfolder:%s", info->name); path = g_strdup_printf("/%s", info->name); - evolution_storage_new_folder (vfolder_storage, - path, - g_basename (path), - "mail", - uri, - info->name); + evolution_storage_new_folder(vfolder_storage, path, g_basename(path), + "mail", uri, info->name); g_free(uri); g_free(path); } @@ -167,7 +157,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, NULL, NULL) != 0) { + if (rule_context_load((RuleContext *)context, system, user) != 0) { g_warning("cannot load vfolders: %s\n", ((RuleContext *)context)->error); } g_free(user); @@ -175,7 +165,6 @@ vfolder_create_storage(EvolutionShellComponent *shell_component) vfolder_refresh(); } -/* THIS IS ANALOGOUS TO mail_tool_uri_to_folder. IT IS NOT ASYNCHRONOUS */ /* maps the shell's uri to the real vfolder uri and open the folder */ CamelFolder * vfolder_uri_to_folder(const char *uri, CamelException *ex) diff --git a/mail/message-list.c b/mail/message-list.c index 4f02e1d7b8..22f6cb741d 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -87,6 +87,7 @@ static void select_msg (MessageList *message_list, gint row); static char *filter_date (const void *data); static void nuke_uids (GtkObject *o); +static char *folder_to_cachename(CamelFolder *folder, const char *prefix); static void save_tree_state(MessageList *ml); static struct { @@ -933,6 +934,20 @@ message_list_init_header (MessageList *message_list) } } +static void +save_header_state(MessageList *ml) +{ + char *filename; + + if (ml->folder == NULL + || ml->etable == NULL) + return; + + filename = folder_to_cachename(ml->folder, "et-header-"); + e_table_scrolled_save_specification(E_TABLE_SCROLLED(ml->etable), filename); + g_free(filename); +} + static char * message_list_get_layout (MessageList *message_list) { @@ -940,6 +955,39 @@ message_list_get_layout (MessageList *message_list) return g_strdup (" 0 3 4 5 "); } +static void +message_list_setup_etable(MessageList *message_list) +{ + char *spec = " " + " 0 7 " + " 4 5 " + " "; + + /* build the spec based on the folder, and possibly from a saved file */ + /* otherwise, leave default */ + if (message_list->folder) { + char *name; + char *path; + struct stat st; + + path = folder_to_cachename(message_list->folder, "et-header-"); + if (stat(path, &st) == 0 && st.st_size > 0 && S_ISREG(st.st_mode)) { + e_table_scrolled_load_specification(E_TABLE_SCROLLED(message_list->etable), path); + } else { + /* I wonder if there's a better way to do this ...? */ + name = camel_service_get_name((CAMEL_SERVICE(message_list->folder->parent_store)), TRUE); + printf("folder name is '%s'\n", name); + if (strstr(name, "/Drafts") == 0 + || strstr(name, "/Outbox") == 0 + || strstr(name, "/Sent") == 0) { + e_table_scrolled_set_specification(E_TABLE_SCROLLED(message_list->etable), spec); + } + g_free(name); + } + g_free(path); + } +} + /* * GtkObject::init */ @@ -997,7 +1045,7 @@ message_list_init (GtkObject *object) GTK_SIGNAL_FUNC (on_double_click), message_list); gtk_widget_show (message_list->etable); - + gtk_object_ref (GTK_OBJECT (message_list->table_model)); gtk_object_sink (GTK_OBJECT (message_list->table_model)); @@ -1020,8 +1068,10 @@ message_list_destroy (GtkObject *object) MessageList *message_list = MESSAGE_LIST (object); int i; - if (message_list->folder) + if (message_list->folder) { save_tree_state(message_list); + save_header_state(message_list); + } gtk_object_unref (GTK_OBJECT (message_list->table_model)); gtk_object_unref (GTK_OBJECT (message_list->header_model)); @@ -1425,6 +1475,9 @@ message_list_set_folder (MessageList *message_list, CamelFolder *camel_folder) message_list->folder = camel_folder; + /* build the etable suitable for this folder */ + message_list_setup_etable(message_list); + camel_object_hook_event(CAMEL_OBJECT (camel_folder), "folder_changed", folder_changed, message_list); camel_object_hook_event(CAMEL_OBJECT (camel_folder), "message_changed", diff --git a/mail/message-list.h b/mail/message-list.h index 4d02e7815a..15267f8293 100644 --- a/mail/message-list.h +++ b/mail/message-list.h @@ -67,7 +67,7 @@ struct _MessageList { ETreePath *tree_root; /* for tree view */ GtkWidget *etable; - + CamelFolder *folder; GHashTable *uid_rowmap; -- cgit v1.2.3