aboutsummaryrefslogtreecommitdiffstats
path: root/mail/mail-local.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/mail-local.c')
-rw-r--r--mail/mail-local.c197
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);
}
}