diff options
Diffstat (limited to 'mail/mail-local.c')
-rw-r--r-- | mail/mail-local.c | 197 |
1 files changed, 150 insertions, 47 deletions
diff --git a/mail/mail-local.c b/mail/mail-local.c index 0eff59e77d..ad80f11e64 100644 --- a/mail/mail-local.c +++ b/mail/mail-local.c @@ -52,7 +52,7 @@ #include "mail-threads.h" #include "folder-browser.h" -#define d(x) +#define d(x) x /* Local folder metainfo */ @@ -231,7 +231,6 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) char *metapath; char *tmpname; - char *uri; CamelURL *url = NULL; struct _local_meta *meta; guint32 flags; @@ -338,12 +337,6 @@ do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex) } free_metainfo(meta); - /* force a reload of the newly formatted folder */ - d(printf("opening new source\n")); - uri = g_strdup(input->fb->uri); - folder_browser_set_uri(input->fb, uri); - g_free(uri); - /* and unref our copy of the new folder ... */ cleanup: if (tofolder) @@ -364,6 +357,7 @@ static void cleanup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex) { reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data; + char *uri; if (camel_exception_is_set(ex)) { GtkWidget *win = gtk_widget_get_ancestor((GtkWidget *)input->frame, GTK_TYPE_WINDOW); @@ -371,6 +365,12 @@ cleanup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException "you may need to repair it manually."), GTK_WINDOW (win)); } + /* force a reload of the newly formatted folder */ + d(printf("opening new source\n")); + uri = g_strdup(input->fb->uri); + folder_browser_set_uri(input->fb, uri); + g_free(uri); + gtk_object_unref (GTK_OBJECT (input->fb)); g_free (input->newtype); } @@ -390,12 +390,12 @@ reconfigure_clicked(GnomeDialog *d, int button, reconfigure_folder_input_t *data if (button == 0) { GtkMenu *menu; int type; - char *types[] = { "mh", "mbox" }; + char *types[] = { "mbox", "maildir", "mh" }; menu = (GtkMenu *)gtk_option_menu_get_menu(data->optionlist); type = g_list_index(GTK_MENU_SHELL(menu)->children, gtk_menu_get_active(menu)); - if (type < 0 || type > 1) - type = 1; + if (type < 0 || type > 2) + type = 0; gtk_widget_set_sensitive(data->frame, FALSE); gtk_widget_set_sensitive(data->apply, FALSE); @@ -409,6 +409,9 @@ reconfigure_clicked(GnomeDialog *d, int button, reconfigure_folder_input_t *data gnome_dialog_close(d); } +/* kills a very annoying warning */ +void local_reconfigure_folder(FolderBrowser *fb); + void local_reconfigure_folder(FolderBrowser *fb) { @@ -448,7 +451,6 @@ local_reconfigure_folder(FolderBrowser *fb) /* MailLocalStore implementation */ - #define MAIL_LOCAL_STORE_TYPE (mail_local_store_get_type ()) #define MAIL_LOCAL_STORE(obj) (CAMEL_CHECK_CAST((obj), MAIL_LOCAL_STORE_TYPE, MailLocalStore)) #define MAIL_LOCAL_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), MAIL_LOCAL_STORE_TYPE, MailLocalStoreClass)) @@ -462,7 +464,8 @@ typedef struct { char *local_path; int local_pathlen; - GHashTable *folders, *unread; + GHashTable *folders, /* points to MailLocalFolder */ + *unread; } MailLocalStore; typedef struct { @@ -476,17 +479,18 @@ typedef struct { int last_unread; } MailLocalFolder; +static void local_folder_changed_proxy (CamelObject *folder, gpointer event_data, gpointer user_data); + CamelType mail_local_store_get_type (void); -static char *get_name (CamelService *service, gboolean brief); -static CamelFolder *get_folder (CamelStore *store, const char *folder_name, - guint32 flags, CamelException *ex); -static void delete_folder (CamelStore *store, const char *folder_name, - CamelException *ex); -static void rename_folder (CamelStore *store, const char *old_name, - const char *new_name, CamelException *ex); -static char *get_folder_name (CamelStore *store, const char *folder_name, - CamelException *ex); +static char *get_name(CamelService *service, gboolean brief); +static CamelFolder *get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex); +static void delete_folder(CamelStore *store, const char *folder_name, CamelException *ex); +static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); +static char *get_folder_name(CamelStore *store, const char *folder_name, CamelException *ex); +static CamelFolder *lookup_folder(CamelStore *store, const char *folder_name); + +static CamelStoreClass *local_parent_class; static void mail_local_store_class_init (MailLocalStoreClass *mail_local_store_class) @@ -503,6 +507,9 @@ mail_local_store_class_init (MailLocalStoreClass *mail_local_store_class) camel_store_class->delete_folder = delete_folder; camel_store_class->rename_folder = rename_folder; camel_store_class->get_folder_name = get_folder_name; + camel_store_class->lookup_folder = lookup_folder; + + local_parent_class = (CamelStoreClass *)camel_type_get_global_classfuncs(camel_store_get_type ()); } static void @@ -514,13 +521,29 @@ mail_local_store_init (gpointer object, gpointer klass) } static void +free_local_folder(MailLocalFolder *lf) +{ + if (lf->folder) { + camel_object_unhook_event((CamelObject *)lf->folder, + "folder_changed", local_folder_changed_proxy, + lf); + camel_object_unhook_event((CamelObject *)lf->folder, + "message_changed", local_folder_changed_proxy, + lf); + camel_object_unref((CamelObject *)lf->folder); + } + g_free(lf->path); + g_free(lf->name); + camel_object_unref((CamelObject *)lf->local_store); +} + +static void free_folder (gpointer key, gpointer data, gpointer user_data) { MailLocalFolder *lf = data; - g_free (key); - camel_object_unref (CAMEL_OBJECT (lf->folder)); - g_free (lf->path); + g_free(key); + free_local_folder(lf); } static void @@ -564,19 +587,103 @@ mail_local_store_get_type (void) return mail_local_store_type; } +/* sigh, + because of all this LocalStore nonsense, we have to snoop cache hits to find out + if our local folder type has changed under us (sort of the whole point of most + of this file, is the storage type of the folder), and then reload the new folder + to match. + + The only other way would be to poke it even more directly, which seems worse. + + Not sure if the ref stuff is 100%, but its probably no worse than it was. +*/ +static CamelFolder * +lookup_folder (CamelStore *store, const char *folder_name) +{ + char *name, *type; + struct _local_meta *meta; + MailLocalFolder *local_folder; + CamelStore *newstore; + MailLocalStore *local_store = (MailLocalStore *)store; + CamelFolder *folder; + CamelException *ex; + + folder = local_parent_class->lookup_folder(store, folder_name); + + d(printf("looking up local folder: %s = %p\n", folder_name, folder)); + + if (folder != NULL) { + type = ((CamelService *)folder->parent_store)->url->protocol; + name = g_strdup_printf("/%s/local-metadata.xml", folder_name); + meta = load_metainfo(name); + g_free(name); + d(printf("found folder, checking type '%s' against meta '%s'\n", type, meta->format)); + if (strcmp(meta->format, type) != 0) { + d(printf("ok, mismatch, checking ...\n")); + local_parent_class->uncache_folder(store, folder); + local_folder = g_hash_table_lookup(local_store->folders, folder_name); + if (local_folder) { + d(printf("we have to update the old folder ...\n")); + camel_object_unhook_event(CAMEL_OBJECT (local_folder->folder), + "folder_changed", local_folder_changed_proxy, + local_folder); + camel_object_unhook_event(CAMEL_OBJECT (local_folder->folder), + "message_changed", local_folder_changed_proxy, + local_folder); + camel_object_unref((CamelObject *)local_folder->folder); + folder = local_folder->folder = NULL; + + ex = camel_exception_new(); + name = g_strdup_printf ("%s:/%s", meta->format, folder_name); + newstore = camel_session_get_store (session, name, ex); + d(printf("getting new store %s = %p\n", name, newstore)); + g_free (name); + if (newstore) { + guint32 flags = CAMEL_STORE_FOLDER_CREATE; + if (meta->indexed) + flags |= CAMEL_STORE_FOLDER_BODY_INDEX; + folder = local_folder->folder = + camel_store_get_folder(newstore, meta->name, flags, ex); + camel_object_unref((CamelObject *)newstore); + + d(printf("we got the new folder: %s : %p\n", folder_name, folder)); + camel_object_hook_event (CAMEL_OBJECT (local_folder->folder), + "folder_changed", local_folder_changed_proxy, + local_folder); + camel_object_hook_event (CAMEL_OBJECT (local_folder->folder), + "message_changed", local_folder_changed_proxy, + local_folder); + } + if (folder) + local_parent_class->cache_folder(store, folder_name, folder); + + camel_exception_free(ex); + } + } + free_metainfo(meta); + } + + if (folder) + camel_object_ref((CamelObject *)folder); + + return folder; +} + static CamelFolder * get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) { MailLocalStore *local_store = (MailLocalStore *)store; CamelFolder *folder; + MailLocalFolder *local_folder; - folder = g_hash_table_lookup (local_store->folders, folder_name); - if (folder) + local_folder = g_hash_table_lookup (local_store->folders, folder_name); + if (local_folder) { + folder = local_folder->folder; camel_object_ref (CAMEL_OBJECT (folder)); - else { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - "No such folder %s", folder_name); + } else { + folder = NULL; + camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, "No such folder %s", folder_name); } return folder; } @@ -632,8 +739,7 @@ local_folder_changed (CamelObject *object, gpointer event_data, CORBA_exception_init (&ev); if (unread > 0) { - display = g_strdup_printf ("%s (%d)", - local_folder->name, unread); + display = g_strdup_printf ("%s (%d)", local_folder->name, unread); GNOME_Evolution_LocalStorage_updateFolder ( local_folder->local_store->corba_local_storage, local_folder->path, display, TRUE, &ev); @@ -651,8 +757,7 @@ local_folder_changed (CamelObject *object, gpointer event_data, } static void -local_folder_changed_proxy (CamelObject *folder, gpointer event_data, - gpointer user_data) +local_folder_changed_proxy (CamelObject *folder, gpointer event_data, gpointer user_data) { int unread; @@ -685,6 +790,7 @@ do_register_folder (gpointer in_data, gpointer op_data, CamelException *ex) name = g_strdup_printf ("%s:/%s", meta->format, local_folder->name); store = camel_session_get_store (session, name, ex); + printf("getting new store %s = %p\n", name, store); g_free (name); if (!store) { free_metainfo (meta); @@ -695,26 +801,23 @@ do_register_folder (gpointer in_data, gpointer op_data, CamelException *ex) if (meta->indexed) flags |= CAMEL_STORE_FOLDER_BODY_INDEX; local_folder->folder = camel_store_get_folder (store, meta->name, flags, ex); - local_folder->last_unread = camel_folder_get_unread_message_count ( - local_folder->folder); + local_folder->last_unread = camel_folder_get_unread_message_count(local_folder->folder); camel_object_unref (CAMEL_OBJECT (store)); free_metainfo (meta); } static void -cleanup_register_folder (gpointer in_data, gpointer op_data, - CamelException *ex) +cleanup_register_folder (gpointer in_data, gpointer op_data, CamelException *ex) { MailLocalFolder *local_folder = in_data; int unread; if (!local_folder->folder) { - g_free (local_folder); + free_local_folder(local_folder); return; } - g_hash_table_insert (local_folder->local_store->folders, - local_folder->name, local_folder->folder); + g_hash_table_insert (local_folder->local_store->folders, local_folder->name, local_folder); local_folder->name = strrchr (local_folder->path, '/') + 1; camel_object_hook_event (CAMEL_OBJECT (local_folder->folder), @@ -725,8 +828,7 @@ cleanup_register_folder (gpointer in_data, gpointer op_data, local_folder); unread = local_folder->last_unread; local_folder->last_unread = 0; - local_folder_changed (CAMEL_OBJECT (local_folder->folder), - GINT_TO_POINTER (unread), local_folder); + local_folder_changed (CAMEL_OBJECT (local_folder->folder), GINT_TO_POINTER (unread), local_folder); } static const mail_operation_spec op_register_folder = @@ -757,6 +859,7 @@ local_storage_new_folder_cb (EvolutionStorageListener *storage_listener, local_folder->name = g_strdup (folder->physical_uri + 8); local_folder->path = g_strdup (path); local_folder->local_store = local_store; + camel_object_ref((CamelObject *)local_store); mail_operation_queue (&op_register_folder, local_folder, FALSE); } @@ -766,7 +869,7 @@ local_storage_removed_folder_cb (EvolutionStorageListener *storage_listener, void *data) { MailLocalStore *local_store = data; - CamelFolder *folder; + MailLocalFolder *local_folder; if (strncmp (path, "file://", 7) != 0 || strncmp (path + 7, local_store->local_path, @@ -775,10 +878,10 @@ local_storage_removed_folder_cb (EvolutionStorageListener *storage_listener, path += 7 + local_store->local_pathlen; - folder = g_hash_table_lookup (local_store->folders, path); - if (folder) { - camel_object_unref (CAMEL_OBJECT (folder)); + local_folder = g_hash_table_lookup (local_store->folders, path); + if (local_folder) { g_hash_table_remove (local_store->folders, path); + free_local_folder(local_folder); } } |