From c2a0bf66ba4970b4a5afb29cfbadeaabbea88d4f Mon Sep 17 00:00:00 2001 From: 5 Date: Sat, 15 Sep 2001 08:13:41 +0000 Subject: Major rewrite of most of the guts, handle changes based on signals and 2001-09-15 * mail-vfolder.c: Major rewrite of most of the guts, handle changes based on signals and events, etc. Use the main storage handling code that imap uses, etc. * mail-tools.c (mail_tool_uri_to_folder): Dont special case vfolder: anymore. * component-factory.c (owner_set_cb): use vfolder_load_storage(), new function to setup vfolder storage, after interaction has been enabled only. This might need some tweaking ... (storage_remove_folder): Removed all the folder lookup stuff. Just delete the folder based on the path passed in. There should be no reason this wouldn't work, right? 2001-09-14 * mail-ops.c (get_folderinfo_get): Only add vtrash folder info, if store supports vtrash. * component-factory.c (mail_load_storage_by_uri): Let 'vfolder' stores show up too. 2001-09-13 * mail-vfolder.c (vfolder_uri_to_folder): Open a vfolder then set its expression, since name?query open method is removed. svn path=/trunk/; revision=12856 --- mail/ChangeLog | 31 +++ mail/component-factory.c | 29 ++- mail/mail-ops.c | 2 +- mail/mail-tools.c | 46 ++-- mail/mail-vfolder.c | 583 ++++++++++++++++++++++++----------------------- mail/mail-vfolder.h | 4 +- 6 files changed, 371 insertions(+), 324 deletions(-) diff --git a/mail/ChangeLog b/mail/ChangeLog index ddaa383a83..08b95312ad 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,32 @@ +2001-09-15 + + * mail-vfolder.c: Major rewrite of most of the guts, handle + changes based on signals and events, etc. Use the main storage + handling code that imap uses, etc. + + * mail-tools.c (mail_tool_uri_to_folder): Dont special case + vfolder: anymore. + + * component-factory.c (owner_set_cb): use vfolder_load_storage(), + new function to setup vfolder storage, after interaction has been + enabled only. This might need some tweaking ... + (storage_remove_folder): Removed all the folder lookup stuff. + Just delete the folder based on the path passed in. There should + be no reason this wouldn't work, right? + +2001-09-14 + + * mail-ops.c (get_folderinfo_get): Only add vtrash folder info, if + store supports vtrash. + + * component-factory.c (mail_load_storage_by_uri): Let 'vfolder' + stores show up too. + +2001-09-13 + + * mail-vfolder.c (vfolder_uri_to_folder): Open a vfolder then set + its expression, since name?query open method is removed. + 2001-09-14 Jeffrey Stedfast * subscribe-dialog.c (fe_root_value_at): Return the cached value @@ -56,6 +85,8 @@ * mail-vfolder.c (vfolder_remove_cb): Fixed the remove callback prototype, and return the result properly using the listener. + (vfolder_uri_to_folder): Always use the same store uri, so we dont + create a new store for each folder. 2001-09-12 Jeffrey Stedfast diff --git a/mail/component-factory.c b/mail/component-factory.c index 32194cc177..6a238ea2aa 100644 --- a/mail/component-factory.c +++ b/mail/component-factory.c @@ -647,7 +647,7 @@ owner_set_cb (EvolutionShellComponent *shell_component, storages_hash = g_hash_table_new (NULL, NULL); - vfolder_create_storage (shell_component); + /*vfolder_create_storage (shell_component);*/ corba_shell = bonobo_object_corba_objref (BONOBO_OBJECT (shell_client)); @@ -668,6 +668,8 @@ owner_set_cb (EvolutionShellComponent *shell_component, } mail_session_enable_interaction (TRUE); + + vfolder_load_storage(corba_shell); mail_autoreceive_setup (); } @@ -900,9 +902,13 @@ storage_remove_folder (EvolutionStorage *storage, gpointer user_data) { CamelStore *store = user_data; +#if 0 CamelURL *url = NULL; CamelFolderInfo *fi; +#endif CamelException ex; + + /* FIXME: Jeff does this look right? */ g_warning ("storage_remove_folder: path=\"%s\"; uri=\"%s\"", path, physical_uri); @@ -911,12 +917,14 @@ storage_remove_folder (EvolutionStorage *storage, notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); return; } - + +#if 0 url = camel_url_new (physical_uri, NULL); if (!url) { notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); return; } +#endif } else { if (!*path) { notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); @@ -925,32 +933,37 @@ storage_remove_folder (EvolutionStorage *storage, } camel_exception_init (&ex); +#if 0 fi = camel_store_get_folder_info (store, url ? url->path + 1 : path + 1, CAMEL_STORE_FOLDER_INFO_FAST, &ex); if (url) camel_url_free (url); if (camel_exception_is_set (&ex)) goto exception; - + camel_store_delete_folder (store, fi->full_name, &ex); +#endif + camel_store_delete_folder (store, path+1, &ex); if (camel_exception_is_set (&ex)) goto exception; if (camel_store_supports_subscriptions (store)) - camel_store_unsubscribe_folder (store, fi->full_name, NULL); + /*camel_store_unsubscribe_folder (store, fi->full_name, NULL);*/ + camel_store_unsubscribe_folder (store, path+1, NULL); evolution_storage_removed_folder (storage, path); - camel_store_free_folder_info (store, fi); + /*camel_store_free_folder_info (store, fi);*/ notify_listener (listener, GNOME_Evolution_Storage_OK); return; exception: /* FIXME: do better than this... */ - +#if 0 if (fi) camel_store_free_folder_info (store, fi); +#endif notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); } @@ -1016,11 +1029,13 @@ mail_load_storage_by_uri (GNOME_Evolution_Shell shell, const char *uri, const ch * That issue can't be resolved on the provider level * -- it's a per-URL problem. * MPZ Added a hack to let spool protocol through temporarily ... + * And vfolder, and maildir ... */ if ((!(prov->flags & CAMEL_PROVIDER_IS_STORAGE) || !(prov->flags & CAMEL_PROVIDER_IS_REMOTE)) && !((strcmp (prov->protocol, "spool") == 0) - || strcmp (prov->protocol, "maildir") == 0)) + || (strcmp (prov->protocol, "maildir") == 0) + || (strcmp (prov->protocol, "vfolder") == 0))) return; store = camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex); diff --git a/mail/mail-ops.c b/mail/mail-ops.c index 15fe17c4e9..b8f8e29df4 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -1117,7 +1117,7 @@ get_folderinfo_get (struct _mail_msg *mm) flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; m->info = camel_store_get_folder_info (m->store, NULL, flags, &mm->ex); - if (m->info && m->info->url) + if (m->info && m->info->url && (m->store->flags & CAMEL_STORE_VTRASH)) add_vtrash_info (m->store, m->info); } diff --git a/mail/mail-tools.c b/mail/mail-tools.c index 0848044b92..1cbf3163a2 100644 --- a/mail/mail-tools.c +++ b/mail/mail-tools.c @@ -333,32 +333,30 @@ mail_tool_uri_to_folder (const char *uri, CamelException *ex) if (!url) { return NULL; } - - if (!strcmp (url->protocol, "vfolder")) { - folder = vfolder_uri_to_folder (uri, ex); - } else { - store = camel_session_get_store (session, uri + offset, ex); - if (store) { - const char *name; - - /* if we have a fragment, then the path is actually used by the store, - so the fragment is the path to the folder instead */ - if (url->fragment) { - name = url->fragment; - } else { - if (url->path && *url->path) - name = url->path + 1; - else - name = ""; - } - - if (offset) - folder = camel_store_get_trash (store, ex); + + store = camel_session_get_store (session, uri + offset, ex); + if (store) { + const char *name; + + /* if we have a fragment, then the path is actually used by the store, + so the fragment is the path to the folder instead */ + if (url->fragment) { + name = url->fragment; + } else { + if (url->path && *url->path) + name = url->path + 1; else - folder = camel_store_get_folder (store, name, - CAMEL_STORE_FOLDER_CREATE, ex); - camel_object_unref (CAMEL_OBJECT (store)); + name = ""; } + + printf("opening folder '%s' on store (%p) '%s'\n", name, store, uri); + + if (offset) + folder = camel_store_get_trash (store, ex); + else + folder = camel_store_get_folder (store, name, + CAMEL_STORE_FOLDER_CREATE, ex); + camel_object_unref (CAMEL_OBJECT (store)); } if (camel_exception_is_set (ex)) { diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index 84523a1b69..0f4c271255 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -24,6 +24,8 @@ #include "mail-autofilter.h" #include "mail-folder-cache.h" #include "mail.h" +#include "mail-ops.h" +#include "mail-mt.h" #include "camel/camel.h" #include "camel/camel-remote-store.h" @@ -44,10 +46,12 @@ struct _vfolder_info { }; /* list of vfolders available */ -static GList *available_vfolders = NULL; static VfolderContext *context; +static CamelStore *vfolder_store; static GList *source_folders; /* list of source folders */ +static GHashTable *vfolder_hash; + /* Ditto below */ EvolutionStorage *vfolder_storage; @@ -57,59 +61,46 @@ extern EvolutionShellClient *global_shell_client; extern char *evolution_dir; extern CamelSession *session; -static struct _vfolder_info * -vfolder_find (const char *name) -{ - GList *l = available_vfolders; - struct _vfolder_info *info; - - while (l) { - info = l->data; - if (!strcmp (info->name, name)) - return info; - l = g_list_next (l); - } - return NULL; -} +/* ********************************************************************** */ -static void -register_new_source (struct _vfolder_info *info, CamelFolder *folder) +/* return true if this folder should be added to this rule */ +static int +check_source(FilterRule *rule, CamelFolder *folder) { - FilterRule *rule = info->rule; - - if (rule && info->folder && rule->source) { + if (rule->source) { int remote = (((CamelService *)folder->parent_store)->provider->flags & CAMEL_PROVIDER_IS_REMOTE) != 0; if (!strcmp(rule->source, "local")) { if (!remote) { - printf("adding local folder to vfolder %s\n", rule->name); - camel_vee_folder_add_folder(info->folder, folder); + return TRUE; } } else if (!strcmp(rule->source, "remote_active")) { if (remote) { - printf("adding remote folder to vfolder %s\n", rule->name); - camel_vee_folder_add_folder(info->folder, folder); + return TRUE; } } else if (!strcmp(rule->source, "local_remote_active")) { - printf("adding local or remote folder to vfolder %s\n", rule->name); - camel_vee_folder_add_folder(info->folder, folder); + return TRUE; } } + + return FALSE; } static void -source_finalise (CamelFolder *sub, gpointer type, CamelFolder *vf) +register_source(char *key, CamelVeeFolder *vfolder, CamelFolder *folder) { - GList *l = available_vfolders; + FilterRule *rule; - while (l) { - struct _vfolder_info *info = l->data; - - if (info->folder) - camel_vee_folder_remove_folder(info->folder, sub); - - l = l->next; - } + rule = rule_context_find_rule((RuleContext *)context, key, NULL); + if (rule && check_source(rule, folder)) + camel_vee_folder_add_folder(vfolder, folder); +} + +/* the source will never be finalised while a vfolder has it */ +static void +source_finalise(CamelFolder *folder, void *event_data, void *data) +{ + source_folders = g_list_remove(source_folders, folder); } /* for registering potential vfolder sources */ @@ -124,309 +115,326 @@ vfolder_register_source (CamelFolder *folder) if (g_list_find(source_folders, folder)) return; - /* FIXME: Hook to destroy event */ + /* note that once we register a source, it will be ref'd + by our vfolder ... and wont go away with this, but we + do this so our source_folders list doesn't get stale */ camel_object_hook_event((CamelObject *)folder, "finalize", (CamelObjectEventHookFunc)source_finalise, folder); source_folders = g_list_append(source_folders, folder); - l = available_vfolders; + g_hash_table_foreach(vfolder_hash, (GHFunc)register_source, folder); +} + +/* ********************************************************************** */ + +struct _setup_msg { + struct _mail_msg msg; + + CamelFolder *folder; + char *query; + GList *sources_uri; + GList *sources_folder; +}; + +static void +vfolder_setup_do(struct _mail_msg *mm) +{ + struct _setup_msg *m = (struct _setup_msg *)mm; + GList *l, *list = NULL; + CamelFolder *folder; + + camel_vee_folder_set_expression((CamelVeeFolder *)m->folder, m->query); + + l = m->sources_uri; + while (l) { + folder = mail_tool_uri_to_folder(l->data, &mm->ex); + if (folder) { + list = g_list_append(list, folder); + } else { + g_warning("Could not open vfolder source: %s", (char *)l->data); + camel_exception_clear(&mm->ex); + } + l = l->next; + } + + l = m->sources_folder; while (l) { - register_new_source(l->data, folder); + camel_object_ref((CamelObject *)l->data); + list = g_list_append(list, l->data); l = l->next; } + + camel_vee_folder_set_folders((CamelVeeFolder *)m->folder, list); + + l = list; + while (l) { + camel_object_unref((CamelObject *)l->data); + l = l->next; + } + g_list_free(list); } -/* go through the list of what we have, what we want, and make - them match, deleting/reconfiguring as required */ static void -vfolder_refresh (void) +vfolder_setup_done(struct _mail_msg *mm) { + struct _setup_msg *m = (struct _setup_msg *)mm; + + m = m; +} + +static void +vfolder_setup_free (struct _mail_msg *mm) +{ + struct _setup_msg *m = (struct _setup_msg *)mm; GList *l; - GList *head = NULL; /* processed list */ - struct _vfolder_info *info; - FilterRule *rule; - GString *expr = g_string_new (""); - char *uri, *path; - - rule = NULL; - while ( (rule = rule_context_next_rule((RuleContext *)context, rule, NULL)) ) { - info = vfolder_find(rule->name); - g_string_truncate(expr, 0); - filter_rule_build_code(rule, expr); - if (info) { - gtk_object_ref((GtkObject *)rule); - if (info->rule) - gtk_object_unref((GtkObject *)info->rule); - info->rule = rule; - - available_vfolders = g_list_remove(available_vfolders, info); - - /* check if the rule has changed ... otherwise, leave it */ - if (strcmp(expr->str, info->query)) { - 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", 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, 0); - g_free(uri); - g_free(path); - } - } else { - info = g_malloc(sizeof(*info)); - info->name = g_strdup(rule->name); - info->query = g_strdup(expr->str); - gtk_object_ref((GtkObject *)rule); - info->rule = rule; - info->folder = NULL; - d(printf("Adding new vfolder: %s %s\n", rule->name, expr->str)); - - 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, 0); - g_free(uri); - g_free(path); - } - head = g_list_append(head, info); + + camel_object_unref((CamelObject *)m->folder); + g_free(m->query); + + l = m->sources_uri; + while (l) { + g_free(l->data); + l = l->next; } - /* everything in available_vfolders are to be removed ... */ - l = available_vfolders; + g_list_free(m->sources_uri); + + l = m->sources_folder; while (l) { - info = l->data; - 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); - g_free(info->name); - g_free(info->query); - gtk_object_unref((GtkObject *)info->rule); - g_free(info); - l = g_list_next(l); + camel_object_unref(l->data); + l = l->next; } + g_list_free(m->sources_folder); +} + +static struct _mail_msg_op vfolder_setup_op = { + NULL, + vfolder_setup_do, + vfolder_setup_done, + vfolder_setup_free, +}; + +static int +vfolder_setup(CamelFolder *folder, const char *query, GList *sources_uri, GList *sources_folder) +{ + struct _setup_msg *m; + int id; - /* setup the virtual unmatched folder */ - info = vfolder_find("UNMATCHED"); - if (info == NULL) { - char *uri, *path; - - info = g_malloc(sizeof(*info)); - info->name = g_strdup("UNMATCHED"); - info->query = g_strdup("UNMATCHED"); - info->rule = NULL; - info->folder = NULL; - d(printf("Adding new vfolder: %s %s\n", 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, 0); - g_free(uri); - g_free(path); - } - head = g_list_append(head, info); + m = mail_msg_new(&vfolder_setup_op, NULL, sizeof (*m)); + m->folder = folder; + camel_object_ref((CamelObject *)folder); + m->query = g_strdup(query); + m->sources_uri = sources_uri; + m->sources_folder = sources_folder; - g_list_free(available_vfolders); - available_vfolders = head; - g_string_free(expr, TRUE); + id = m->msg.seq; + e_thread_put(mail_thread_queued, (EMsg *)m); + + return id; } +/* ********************************************************************** */ + +static void context_rule_added(RuleContext *ctx, FilterRule *rule); + static void -unlist_vfolder (CamelObject *folder, gpointer event_data, gpointer user_data) +rule_changed(FilterRule *rule, CamelFolder *folder) { + const char *sourceuri; GList *l; + GList *sources_uri = NULL, *sources_folder = NULL; + GString *query; - l = available_vfolders; - while (l) { - struct _vfolder_info *info = l->data; + /* if the folder has changed name, then add it, then remove the old manually */ + if (strcmp(folder->full_name, rule->name) != 0) { + char *uri, *path, *key; + CamelFolder *old; + + gtk_signal_disconnect_by_func((GtkObject *)rule, rule_changed, folder); - if ((CamelObject *)info->folder == folder) { - info->folder = NULL; - return; + context_rule_added((RuleContext *)context, rule); + + uri = g_strdup_printf("vfolder:%s/vfolder#%s", evolution_dir, folder->full_name); + mail_folder_cache_remove_folder(uri); + g_free(uri); + + path = g_strdup_printf("/%s", folder->full_name); + evolution_storage_removed_folder(mail_lookup_storage(vfolder_store), path); + g_free(path); + + if (g_hash_table_lookup_extended(vfolder_hash, folder->full_name, (void **)&key, (void **)&old)) { + g_hash_table_remove(vfolder_hash, key); + g_free(key); + camel_object_unref((CamelObject *)folder); + } else { + g_warning("couldn't find a vfolder rule in our table? %s", folder->full_name); } + return; + } + + printf("Filter rule changed? for folder '%s'!!\n", folder->name); + + /* work out the work to do, then do it in another thread */ + sourceuri = NULL; + while ( (sourceuri = vfolder_rule_next_source((VfolderRule *)rule, sourceuri)) ) { + sources_uri = g_list_append(sources_uri, g_strdup(sourceuri)); + } + + l = source_folders; + while (l) { + if (check_source(rule, l->data)) { + camel_object_ref(l->data); + sources_folder = g_list_append(sources_folder, l->data); + } l = l->next; } - g_message ("Whoa, unlisting vfolder %p but can't find it", folder); + query = g_string_new(""); + filter_rule_build_code(rule, query); + + vfolder_setup(folder, query->str, sources_uri, sources_folder); + + g_string_free(query, TRUE); } -static void -vfolder_remove_cb (EvolutionStorage *storage, - const Bonobo_Listener listener, - const char *path, - const char *physical_uri, - gpointer user_data) +static void context_rule_added(RuleContext *ctx, FilterRule *rule) { - CORBA_any any; - CORBA_Environment ev; - GNOME_Evolution_Storage_Result corba_result = GNOME_Evolution_Storage_OK; + CamelFolder *folder; + char *uri, *path; + + printf("rule added: %s\n", rule->name); - if (strncmp(physical_uri, "vfolder:", 8) != 0) - corba_result = GNOME_Evolution_Storage_UNSUPPORTED_TYPE; - else if (vfolder_find(physical_uri + 8) == NULL) - corba_result = GNOME_Evolution_Storage_INVALID_URI; - else - vfolder_remove (physical_uri); + /* this always runs quickly */ + folder = camel_store_get_folder(vfolder_store, rule->name, 0, NULL); + if (folder) { + gtk_signal_connect((GtkObject *)rule, "changed", rule_changed, folder); - CORBA_exception_init (&ev); + g_hash_table_insert(vfolder_hash, g_strdup(rule->name), folder); - any._type = TC_GNOME_Evolution_Storage_Result; - any._value = &corba_result; + /* Ok, so the mail_folder_cache api is a complete fuckup, + I think this mess probably does what it is supposed to do */ + uri = g_strdup_printf("vfolder:%s/vfolder#%s", evolution_dir, rule->name); + printf("Noting folder '%s', storage = %p\n", uri, mail_lookup_storage(vfolder_store)); + path = g_strdup_printf("/%s", rule->name); + evolution_storage_new_folder(mail_lookup_storage(vfolder_store), + path, rule->name, + "mail", uri, + rule->name, + FALSE); - Bonobo_Listener_event (listener, "result", &any, &ev); + mail_folder_cache_note_folder(uri, folder); + mail_folder_cache_set_update_estorage(uri, mail_lookup_storage(vfolder_store)); + g_free(uri); + g_free(path); - CORBA_exception_free (&ev); + rule_changed(rule, folder); + } } -void -vfolder_create_storage (EvolutionShellComponent *shell_component) +static void context_rule_removed(RuleContext *ctx, FilterRule *rule) { - GNOME_Evolution_Shell corba_shell; - EvolutionStorage *storage; - char *user, *system; - - if (global_shell_client == NULL) { - g_warning ("We have no shell!?"); - return; - } - - corba_shell = bonobo_object_corba_objref (BONOBO_OBJECT (global_shell_client)); - - storage = evolution_storage_new (U_("VFolders"), NULL, NULL); - if (evolution_storage_register_on_shell (storage, corba_shell) != EVOLUTION_STORAGE_OK) { - g_warning ("Cannot register storage"); - return; - } - - vfolder_storage = storage; - gtk_signal_connect (GTK_OBJECT (storage), "remove_folder", - GTK_SIGNAL_FUNC (vfolder_remove_cb), - NULL); - - user = g_strdup_printf ("%s/vfolders.xml", evolution_dir); - system = EVOLUTION_DATADIR "/evolution/vfoldertypes.xml"; - - context = vfolder_context_new (); - printf("loading rules %s %s\n", system, user); - if (rule_context_load ((RuleContext *)context, system, user) != 0) { - g_warning("cannot load vfolders: %s\n", ((RuleContext *)context)->error); + char *uri, *key, *path; + CamelFolder *folder; + + printf("rule removed; %s\n", rule->name); + + /* have to remove this first before unrefing the folder, otherwise it gets itself lost */ + uri = g_strdup_printf("vfolder:%s/vfolder#%s", evolution_dir, rule->name); + mail_folder_cache_remove_folder(uri); + g_free(uri); + + path = g_strdup_printf("/%s", rule->name); + evolution_storage_removed_folder(mail_lookup_storage(vfolder_store), path); + g_free(path); + + if (g_hash_table_lookup_extended(vfolder_hash, rule->name, (void **)&key, (void **)&folder)) { + g_hash_table_remove(vfolder_hash, key); + g_free(key); + camel_object_unref((CamelObject *)folder); } - g_free (user); - vfolder_refresh (); + + camel_store_delete_folder(vfolder_store, rule->name, NULL); } -void -vfolder_remove (const char *uri) +static void +store_folder_created(CamelObject *o, void *event_data, void *data) { - struct _vfolder_info *info; - VfolderRule *rule; + CamelStore *store = (CamelStore *)o; + CamelFolderInfo *info = event_data; + + store = store; + info = info; +} + +static void +store_folder_deleted(CamelObject *o, void *event_data, void *data) +{ + CamelStore *store = (CamelStore *)o; + CamelFolderInfo *info = event_data; + FilterRule *rule; char *user; - - g_warning ("vfolder_remove (\"%s\");", uri); - - if (strncmp (uri, "vfolder:", 8)) - return; - - info = vfolder_find (uri + 8); - if (!info) - return; - - user = g_strdup_printf ("%s/vfolders.xml", evolution_dir); - rule = (VfolderRule *)rule_context_find_rule ((RuleContext *) context, info->name, NULL); - rule_context_remove_rule ((RuleContext *) context, (FilterRule *) rule); - rule_context_save ((RuleContext *) context, user); - g_free (user); - vfolder_refresh (); + + printf("Folder deleted: %s\n", info->name); + store = store; + + /* delete it from our list */ + rule = rule_context_find_rule((RuleContext *)context, info->name, NULL); + if (rule) { + /* We need to stop listening to removed events, otherwise we'll try and remove it again */ + gtk_signal_disconnect_by_func((GtkObject *)context, context_rule_removed, context); + rule_context_remove_rule((RuleContext *)context, rule); + gtk_object_unref((GtkObject *)rule); + gtk_signal_connect((GtkObject *)context, "rule_removed", context_rule_removed, context); + + user = g_strdup_printf("%s/vfolders.xml", evolution_dir); + rule_context_save((RuleContext *)context, user); + g_free(rule); + } else { + g_warning("Cannot find rule for deleted vfolder '%s'", info->name); + } } -/* maps the shell's uri to the real vfolder uri and open the folder */ -CamelFolder * -vfolder_uri_to_folder(const char *uri, CamelException *ex) +void +vfolder_load_storage(GNOME_Evolution_Shell shell) { - struct _vfolder_info *info; - char *storeuri, *foldername; - VfolderRule *rule; - CamelFolder *folder = NULL, *sourcefolder; - const char *sourceuri; - int sources; - GList *l; - - 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; + char *user, *storeuri; + FilterRule *rule; + + vfolder_hash = g_hash_table_new(g_str_hash, g_str_equal); + + /* first, create the vfolder store, and set it up */ + storeuri = g_strdup_printf("vfolder:%s/vfolder", evolution_dir); + vfolder_store = camel_session_get_store(session, storeuri, NULL); + if (vfolder_store == NULL) { + g_warning("Cannot open vfolder store - no vfolders available"); + return; } - - if (info->folder) { - camel_object_ref((CamelObject *)info->folder); - return (CamelFolder *)info->folder; + + camel_object_hook_event((CamelObject *)vfolder_store, "folder_created", + (CamelObjectEventHookFunc)store_folder_created, NULL); + camel_object_hook_event((CamelObject *)vfolder_store, "folder_deleted", + (CamelObjectEventHookFunc)store_folder_deleted, NULL); + + printf("got store '%s' = %p\n", storeuri, vfolder_store); + mail_load_storage_by_uri(shell, storeuri, U_("VFolders")); + + /* load our rules */ + user = g_strdup_printf ("%s/vfolders.xml", evolution_dir); + context = vfolder_context_new (); + if (rule_context_load ((RuleContext *)context, EVOLUTION_DATADIR "/evolution/vfoldertypes.xml", user) != 0) { + g_warning("cannot load vfolders: %s\n", ((RuleContext *)context)->error); } + g_free (user); - d(printf("Opening vfolder: %s\n", uri)); - - rule = (VfolderRule *)rule_context_find_rule((RuleContext *)context, info->name, NULL); - - storeuri = g_strdup_printf("vfolder:%s/vfolder/%s", evolution_dir, info->name); - foldername = g_strdup_printf("%s?%s", info->name, info->query); - - /* we dont have indexing on vfolders */ - folder = mail_tool_get_folder_from_urlname (storeuri, foldername, CAMEL_STORE_FOLDER_CREATE, ex); - info->folder = (CamelVeeFolder *)folder; - camel_object_hook_event ((CamelObject *) info->folder, "finalize", unlist_vfolder, NULL); - - mail_folder_cache_set_update_estorage (uri, vfolder_storage); - mail_folder_cache_note_folder (uri, CAMEL_FOLDER (info->folder)); - - bonobo_object_ref (BONOBO_OBJECT (vfolder_storage)); - mail_hash_storage ((CamelService *)folder->parent_store, vfolder_storage); - - if (strcmp (uri + 8, "UNMATCHED") != 0) { - sourceuri = NULL; - sources = 0; - while ( (sourceuri = vfolder_rule_next_source(rule, sourceuri)) ) { - d(printf("adding vfolder source: %s\n", sourceuri)); - sourcefolder = mail_tool_uri_to_folder (sourceuri, ex); - printf("source folder = %p\n", sourcefolder); - if (sourcefolder) { - sources++; - camel_vee_folder_add_folder((CamelVeeFolder *)folder, sourcefolder); - } else { - /* we'll just silently ignore now-missing sources */ - camel_exception_clear(ex); - } - } + gtk_signal_connect((GtkObject *)context, "rule_added", context_rule_added, context); + gtk_signal_connect((GtkObject *)context, "rule_removed", context_rule_removed, context); - l = source_folders; - while (l) { - register_new_source(info, l->data); - l = l->next; - } -#if 0 - /* 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_tool_uri_to_folder (defaulturi, ex); - g_free(defaulturi); - if (sourcefolder) { - camel_vee_folder_add_folder(folder, sourcefolder); - } - } -#endif + /* and setup the rules we have */ + rule = NULL; + while ( (rule = rule_context_next_rule((RuleContext *)context, rule, NULL)) ) { + context_rule_added((RuleContext *)context, rule); } - g_free(foldername); g_free(storeuri); - - return folder; } static GtkWidget *vfolder_editor = NULL; @@ -446,7 +454,6 @@ vfolder_editor_clicked (GtkWidget *dialog, int button, void *data) 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 (GNOME_DIALOG (dialog)); @@ -479,7 +486,6 @@ new_rule_clicked(GtkWidget *w, int button, void *data) 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); @@ -555,6 +561,5 @@ vfolder_gui_add_from_mlist(CamelMimeMessage *msg, const char *mlist, const char EvolutionStorage * mail_vfolder_get_vfolder_storage (void) { - bonobo_object_ref (BONOBO_OBJECT (vfolder_storage)); - return vfolder_storage; + return mail_lookup_storage(vfolder_store); } diff --git a/mail/mail-vfolder.h b/mail/mail-vfolder.h index 052d2b976a..1245a4cd77 100644 --- a/mail/mail-vfolder.h +++ b/mail/mail-vfolder.h @@ -11,7 +11,7 @@ #include "filter/vfolder-rule.h" #include "filter/filter-part.h" -void vfolder_create_storage (EvolutionShellComponent *shell_component); +void vfolder_load_storage(GNOME_Evolution_Shell shell); CamelFolder *vfolder_uri_to_folder (const char *uri, CamelException *ex); void vfolder_edit (void); @@ -24,8 +24,6 @@ void vfolder_gui_add_from_mlist (CamelMimeMessage *msg, const char *mlist, const /* for registering all open folders as potential vfolder sources */ void vfolder_register_source (CamelFolder *folder); -void vfolder_remove (const char *uri); - EvolutionStorage *mail_vfolder_get_vfolder_storage (void); #endif -- cgit v1.2.3