Configurable vfolder sources, and a button to save a search

as a new vfolder.

2000-07-31  Not Zed  <NotZed@HelixCode.com>

        * mail-vfolder.h: Header for vfolder functions.

        * folder-browser.c (mail_uri_to_folder): Use new scheme to open
        vfolders.
        (search_save): New button/function to save a search as a vfolder.

        * mail-vfolder.c (vfolder_edit): Made asynchronous.
        (vfolder_uri_to_folder): New function for loading vfolders and
        setting up their source folders.
        (vfolder_refresh): Change shell vfolder uri's to indirect
        references rather than the real vfolder uri.
        (vfolder_gui_add_rule): Add a rule with user confirmation.
        (vfolder_create_part): Get a new part by name, for creating rules
        in code.

        * message-thread.c (thread_messages): Check for uid lookup
        failure, which indicates an error in the folder or calling code.

svn path=/trunk/; revision=4422
This commit is contained in:
Not Zed
2000-07-31 15:07:49 +00:00
committed by Michael Zucci
parent 9ddabfee03
commit 72092414aa
5 changed files with 265 additions and 42 deletions

View File

@ -1,3 +1,23 @@
2000-07-31 Not Zed <NotZed@HelixCode.com>
* mail-vfolder.h: Header for vfolder functions.
* folder-browser.c (mail_uri_to_folder): Use new scheme to open
vfolders.
(search_save): New button/function to save a search as a vfolder.
* mail-vfolder.c (vfolder_edit): Made asynchronous.
(vfolder_uri_to_folder): New function for loading vfolders and
setting up their source folders.
(vfolder_refresh): Change shell vfolder uri's to indirect
references rather than the real vfolder uri.
(vfolder_gui_add_rule): Add a rule with user confirmation.
(vfolder_create_part): Get a new part by name, for creating rules
in code.
* message-thread.c (thread_messages): Check for uid lookup
failure, which indicates an error in the folder or calling code.
2000-07-29 Not Zed <NotZed@HelixCode.com>
* component-factory.c (create_view): Remove hack to pass the

View File

@ -17,6 +17,12 @@
#include "message-list.h"
#include <widgets/e-paned/e-vpaned.h>
#include "mail-vfolder.h"
#include "filter/vfolder-rule.h"
#include "filter/vfolder-context.h"
#include "filter/filter-option.h"
#include "filter/filter-input.h"
#define PARENT_TYPE (gtk_table_get_type ())
static GtkObjectClass *folder_browser_parent_class;
@ -68,37 +74,7 @@ mail_uri_to_folder (const char *name)
ex = camel_exception_new ();
if (!strncmp (name, "vfolder:", 8)) {
char *query, *newquery;
store_name = g_strdup (name);
query = strchr (store_name, '?');
if (query) {
*query++ = 0;
} else {
query = "";
}
newquery = g_strdup_printf("mbox?%s", query);
store = camel_session_get_store (session, store_name, ex);
if (store) {
folder = camel_store_get_folder (store, newquery, TRUE, ex);
/* FIXME: do this properly rather than hardcoding */
#warning "Find a way not to hardcode vfolder source"
{
char *source_name;
CamelFolder *source_folder;
extern char *evolution_dir;
source_name = g_strdup_printf ("file://%s/local/Inbox", evolution_dir);
source_folder = mail_uri_to_folder (source_name);
g_free (source_name);
#warning "Not Good (tm). It might be better to have some sort of high level Camel interface for this"
if (source_folder)
camel_vee_folder_add_folder (folder, source_folder);
}
}
g_free (newquery);
g_free (store_name);
folder = vfolder_uri_to_folder(name);
} else if (!strncmp (name, "imap:", 5)) {
char *service, *ptr;
@ -227,6 +203,7 @@ static char * search_options[] = {
NULL
};
/* NOTE: If this is changed, then change the search_save() function to match! */
/* %s is replaced by the whole search string in quotes ...
possibly could split the search string into words as well ? */
static char * search_string[] = {
@ -315,6 +292,70 @@ search_activate(GtkEntry *entry, FolderBrowser *fb)
search_set(fb);
}
static void
search_save(GtkWidget *w, FolderBrowser *fb)
{
GtkWidget *widget;
int index;
char *text;
FilterElement *element;
VfolderRule *rule;
FilterPart *part;
text = gtk_entry_get_text((GtkEntry *)fb->search_entry);
if (text == NULL || text[0] == 0) {
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");
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) {
default: /* header or body contains */
index = 0;
case 1: case 2:
if (index == 0 || index == 1) { /* body-contains */
part = vfolder_create_part("body");
filter_rule_add_part((FilterRule *)rule, part);
element = filter_part_find_element(part, "body-type");
filter_option_set_current((FilterOption *)element, "contains");
element = filter_part_find_element(part, "word");
filter_input_set_value((FilterInput *)element, text);
}
if (index == 0 || index == 2) { /* subject contains */
part = vfolder_create_part("subject");
filter_rule_add_part((FilterRule *)rule, part);
element = filter_part_find_element(part, "subject-type");
filter_option_set_current((FilterOption *)element, "contains");
element = filter_part_find_element(part, "subject");
filter_input_set_value((FilterInput *)element, text);
}
break;
case 3: /* not body contains */
part = vfolder_create_part("body");
filter_rule_add_part((FilterRule *)rule, part);
element = filter_part_find_element(part, "body-type");
filter_option_set_current((FilterOption *)element, "not contains");
element = filter_part_find_element(part, "word");
filter_input_set_value((FilterInput *)element, text);
break;
case 4: /* not header contains */
part = vfolder_create_part("subject");
filter_rule_add_part((FilterRule *)rule, part);
element = filter_part_find_element(part, "subject-type");
filter_option_set_current((FilterOption *)element, "not contains");
element = filter_part_find_element(part, "subject");
filter_input_set_value((FilterInput *)element, text);
break;
}
vfolder_gui_add_rule(rule);
}
void
folder_browser_clear_search (FolderBrowser *fb)
{
@ -373,6 +414,7 @@ static void
folder_browser_gui_init (FolderBrowser *fb)
{
GtkWidget *hbox, *label;
GtkButton *button;
/*
* The panned container
@ -397,6 +439,10 @@ folder_browser_gui_init (FolderBrowser *fb)
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_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);

View File

@ -18,11 +18,16 @@
#include "evolution-shell-component.h"
#include "folder-browser.h"
#include "mail-vfolder.h"
#include "camel/camel.h"
#include "filter/vfolder-context.h"
#include "filter/filter-rule.h"
#include "filter/vfolder-rule.h"
#include "filter/vfolder-editor.h"
#define d(x) x
struct _vfolder_info {
char *name;
char *query;
@ -35,10 +40,13 @@ static EvolutionStorage *vfolder_storage;
/* GROSS HACK: for passing to other parts of the program */
EvolutionShellClient *global_shell_client = NULL;
/* more globals ... */
extern char *evolution_dir;
extern CamelSession *session;
static struct _vfolder_info *
vfolder_find(char *name)
vfolder_find(const char *name)
{
GList *l = available_vfolders;
struct _vfolder_info *info;
@ -74,11 +82,12 @@ vfolder_refresh(void)
/* check if the rule has changed ... otherwise, leave it */
if (strcmp(expr->str, info->query)) {
printf("Must reconfigure vfolder with new rule?\n");
d(printf("Must reconfigure vfolder with new rule?\n"));
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/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,
@ -92,9 +101,10 @@ vfolder_refresh(void)
info = g_malloc(sizeof(*info));
info->name = g_strdup(rule->name);
info->query = g_strdup(expr->str);
printf("Adding new vfolder: %s %s\n", rule->name, 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/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,
"mail",
@ -109,7 +119,7 @@ vfolder_refresh(void)
l = available_vfolders;
while (l) {
info = l->data;
printf("removing vfolders %s %s\n", info->name, info->query);
d(printf("removing vfolders %s %s\n", info->name, info->query));
path = g_strdup_printf("/%s", info->name);
evolution_storage_removed_folder(vfolder_storage, path);
g_free(path);
@ -160,17 +170,137 @@ vfolder_create_storage(EvolutionShellComponent *shell_component)
vfolder_refresh();
}
/* maps the shell's uri to the real vfolder uri and open the folder */
CamelFolder *
vfolder_uri_to_folder(const char *uri)
{
CamelFolder *mail_uri_to_folder(const char *);
void camel_vee_folder_add_folder(CamelFolder *, CamelFolder *);
struct _vfolder_info *info;
char *storeuri, *foldername;
VfolderRule *rule;
CamelStore *store = NULL;
CamelFolder *folder = NULL, *sourcefolder;
CamelException *ex;
const char *sourceuri;
int sources;
if (strncmp (uri, "vfolder:", 8))
return NULL;
info = vfolder_find(uri+8);
if (info == NULL) {
g_warning("Shell trying to open unknown vFolder: %s", uri);
return NULL;
}
d(printf("Opening vfolder: %s\n", uri));
rule = (VfolderRule *)rule_context_find_rule((RuleContext *)context, info->name);
storeuri = g_strdup_printf("vfolder:%s/vfolder/%s", evolution_dir, info->name);
foldername = g_strdup_printf("mbox?%s", info->query);
ex = camel_exception_new ();
store = camel_session_get_store (session, storeuri, ex);
if (store == NULL)
goto cleanup;
folder = camel_store_get_folder (store, foldername, TRUE, ex);
if (folder == NULL)
goto cleanup;
sourceuri = NULL;
sources = 0;
while ( (sourceuri = vfolder_rule_next_source(rule, sourceuri)) ) {
d(printf("adding vfolder source: %s\n", sourceuri));
sourcefolder = mail_uri_to_folder(sourceuri);
if (sourcefolder) {
sources++;
camel_vee_folder_add_folder(folder, sourcefolder);
}
}
/* if we didn't have any sources, just use Inbox as the default */
if (sources == 0) {
char *defaulturi;
defaulturi = g_strdup_printf("file://%s/local/Inbox", evolution_dir);
d(printf("No sources configured/found, using default: %s\n", defaulturi));
sourcefolder = mail_uri_to_folder(defaulturi);
g_free(defaulturi);
if (sourcefolder)
camel_vee_folder_add_folder(folder, sourcefolder);
}
cleanup:
g_free(foldername);
g_free(storeuri);
return folder;
}
static void
vfolder_editor_clicked(GtkWidget *w, int button, void *data)
{
if (button == 0) {
char *user;
user = g_strdup_printf("%s/vfolders.xml", evolution_dir);
rule_context_save((RuleContext *)context, user);
g_free(user);
vfolder_refresh();
}
if (button != -1) {
gnome_dialog_close((GnomeDialog *)w);
}
}
void
vfolder_edit(void)
{
GtkWidget *w;
char *user;
w = vfolder_editor_construct(context);
if (gnome_dialog_run_and_close((GnomeDialog *)w) == 0) {
user = g_strdup_printf ("%s/vfolders.xml", evolution_dir);
rule_context_save(context, user);
gtk_signal_connect((GtkObject *)w, "clicked", vfolder_editor_clicked, NULL);
gtk_widget_show(w);
}
static void
new_rule_clicked(GtkWidget *w, int button, void *data)
{
if (button == 0) {
char *user;
FilterRule *rule = gtk_object_get_data((GtkObject *)w, "rule");
gtk_object_ref((GtkObject *)rule);
rule_context_add_rule((RuleContext *)context, rule);
user = g_strdup_printf("%s/vfolders.xml", evolution_dir);
rule_context_save((RuleContext *)context, user);
g_free(user);
vfolder_refresh();
}
if (button != -1) {
gnome_dialog_close((GnomeDialog *)w);
}
}
FilterPart *
vfolder_create_part(const char *name)
{
return rule_context_create_part((RuleContext *)context, name);
}
/* adds a rule with a gui */
void
vfolder_gui_add_rule(VfolderRule *rule)
{
GtkWidget *w;
GnomeDialog *gd;
w = filter_rule_get_widget((FilterRule *)rule, (RuleContext *)context);
gd = (GnomeDialog *)gnome_dialog_new("New VFolder", "Ok", "Cancel", NULL);
gtk_box_pack_start((GtkBox *)gd->vbox, w, FALSE, TRUE, 0);
gtk_widget_show((GtkWidget *)gd);
gtk_object_set_data_full((GtkObject *)gd, "rule", rule, (GtkDestroyNotify)gtk_object_unref);
gtk_signal_connect((GtkObject *)gd, "clicked", new_rule_clicked, NULL);
gtk_widget_show((GtkWidget *)gd);
}

22
mail/mail-vfolder.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef _MAIL_VFOLDER_H
#define _MAIL_VFOLDER_H
#include <bonobo.h>
#include "Evolution.h"
#include "evolution-storage.h"
#include "evolution-shell-component.h"
#include "camel/camel-folder.h"
#include "filter/vfolder-rule.h"
#include "filter/filter-part.h"
void vfolder_create_storage(EvolutionShellComponent *shell_component);
CamelFolder *vfolder_uri_to_folder(const char *uri);
void vfolder_edit(void);
FilterPart *vfolder_create_part(const char *name);
void vfolder_gui_add_rule(VfolderRule *rule);
#endif

View File

@ -421,6 +421,11 @@ thread_messages(CamelFolder *folder, GPtrArray *uids)
const CamelMessageInfo *mi;
mi = camel_folder_get_message_info (folder, uids->pdata[i]);
if (mi == NULL) {
g_warning("Folder doesn't contain uid %s", uids->pdata[i]);
continue;
}
if (mi->message_id) {
d(printf("doing : %s\n", mi->message_id));
c = g_hash_table_lookup(id_table, mi->message_id);