aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog35
-rw-r--r--mail/Makefile.am2
-rw-r--r--mail/folder-browser-factory.c32
-rw-r--r--mail/folder-browser.c5
-rw-r--r--mail/mail-callbacks.c19
-rw-r--r--mail/mail-folder-cache.c798
-rw-r--r--mail/mail-folder-cache.h59
-rw-r--r--mail/mail-local.c95
-rw-r--r--mail/mail-ops.c16
-rw-r--r--mail/mail-tools.c109
10 files changed, 973 insertions, 197 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 643551da72..587933ba7f 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,38 @@
+2001-07-02 Peter Williams <peterw@ximian.com>
+
+ * mail-folder-cache.h: New file. Protoypes for the Mail Folder Cache, which
+ provides a place for all the disparate pieces of the mailer to save bits of
+ information about a folder. Centralizes the information display code.
+
+ * mail-folder-cache.c: New file. Implements the Mail Folder Cache.
+
+ * Makefile.am (evolution_mail_SOURCES): Add the mail-folder-cache.{c,h}
+
+ * folder-browser-factory.c (fb_get_svi): Copy of that absurdly long-named
+ function in mail-display.c that gets the GNOME_Evolution_ShellView.
+ (control_activate): Set the ShellView for the folder cache.
+
+ * folder-browser.c (got_folder): Tell the folder browser about this folder.
+
+ * mail-callbacks.c (create_folders): Tell the folder cache about the new
+ folders.
+
+ * mail-local.c (reconfigure_folder_reconfigure): Don't unhook our
+ events as we no longer hook them up.
+ (register_folder_registered): Tell the folder cache about this
+ folder's place in the local storage.
+ (register_folder_register): No longer hook events; the Folder Cache
+ will do this.
+ (local_folder_changed, local_folder_changed_proxy): Move to mail-folder-cache.c
+ (free_local_folder): No longer unhook events.
+
+ * mail-ops.c (do_update_subfolders_rec): Instead of setting the
+ folder status ourselves, inform the Folder Cache about the changes.
+
+ * mail-tools.c (mail_tool_uri_to_folder): Replace danw's cache
+ with the new Mail Folder Cache.
+ (cache_folder, etc): removed.
+
2001-07-02 Jeffrey Stedfast <fejj@ximian.com>
* mail-accounts.c: #include widgets/misc/e-charset-picker.h since
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 1c31e5c080..76566dea47 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -66,6 +66,8 @@ evolution_mail_SOURCES = \
mail-crypto.h \
mail-display.c \
mail-display.h \
+ mail-folder-cache.c \
+ mail-folder-cache.h \
mail-format.c \
mail-identify.c \
mail-importer.c \
diff --git a/mail/folder-browser-factory.c b/mail/folder-browser-factory.c
index 021ae363cf..a3ad7f2fbe 100644
--- a/mail/folder-browser-factory.c
+++ b/mail/folder-browser-factory.c
@@ -37,6 +37,7 @@
#include "mail-config.h"
#include "mail-ops.h"
#include "mail-session.h"
+#include "mail-folder-cache.h"
#include "evolution-shell-component-utils.h"
#include "camel/camel-vtrash-folder.h"
@@ -44,6 +45,35 @@
/* The FolderBrowser BonoboControls we have. */
static EList *control_list = NULL;
+/* copied from mail-display.c for now.... */
+static GNOME_Evolution_ShellView
+fb_get_svi (BonoboControl *control)
+{
+ Bonobo_ControlFrame control_frame;
+ GNOME_Evolution_ShellView shell_view_interface;
+ CORBA_Environment ev;
+
+ control_frame = bonobo_control_get_control_frame (control);
+
+ if (control_frame == NULL)
+ return CORBA_OBJECT_NIL;
+
+ CORBA_exception_init (&ev);
+ shell_view_interface = Bonobo_Unknown_queryInterface (control_frame,
+ "IDL:GNOME/Evolution/ShellView:1.0",
+ &ev);
+ CORBA_exception_free (&ev);
+
+ if (shell_view_interface != CORBA_OBJECT_NIL)
+ gtk_object_set_data (GTK_OBJECT (control),
+ "mail_threads_shell_view_interface",
+ shell_view_interface);
+ else
+ g_warning ("Control frame doesn't have Evolution/ShellView.");
+
+ return shell_view_interface;
+}
+
static void
control_activate (BonoboControl *control,
BonoboUIComponent *uic,
@@ -66,6 +96,8 @@ control_activate (BonoboControl *control,
folder_browser_ui_add_list (fb);
folder_browser_ui_add_message (fb);
+ mail_folder_cache_set_shell_view (fb_get_svi (control));
+
if (fb->folder)
mail_refresh_folder (fb->folder, NULL, NULL);
}
diff --git a/mail/folder-browser.c b/mail/folder-browser.c
index 3c5d44cc25..85a9084d68 100644
--- a/mail/folder-browser.c
+++ b/mail/folder-browser.c
@@ -42,6 +42,7 @@
#include "mail-vfolder.h"
#include "mail-autofilter.h"
#include "mail-mt.h"
+#include "mail-folder-cache.h"
#include "mail-local.h"
#include "mail-config.h"
@@ -620,6 +621,10 @@ got_folder(char *uri, CamelFolder *folder, void *data)
folder_browser_is_sent (fb) ||
folder_browser_is_outbox (fb));
vfolder_register_source (folder);
+
+ mail_folder_cache_note_folder (fb->uri, folder);
+ mail_folder_cache_note_message_list (fb->uri, fb->message_list);
+
done:
gtk_object_unref (GTK_OBJECT (fb));
diff --git a/mail/mail-callbacks.c b/mail/mail-callbacks.c
index a4d1647515..3e737788a0 100644
--- a/mail/mail-callbacks.c
+++ b/mail/mail-callbacks.c
@@ -56,6 +56,7 @@
#include "mail-search.h"
#include "mail-send-recv.h"
#include "mail-vfolder.h"
+#include "mail-folder-cache.h"
#include "folder-browser.h"
#include "subscribe-dialog.h"
#include "e-messagebox.h"
@@ -374,7 +375,7 @@ composer_get_message (EMsgComposer *composer)
return NULL;
}
}
-
+
/* Check for no subject */
subject = camel_mime_message_get_subject (message);
if (subject == NULL || subject[0] == '\0') {
@@ -1971,21 +1972,17 @@ empty_trash (BonoboUIComponent *uih, void *user_data, const char *path)
static void
create_folders (EvolutionStorage *storage, const char *prefix, CamelFolderInfo *fi)
{
- char *name, *path;
-
- if (fi->unread_message_count > 0)
- name = g_strdup_printf ("%s (%d)", fi->name,
- fi->unread_message_count);
- else
- name = g_strdup (fi->name);
+ char *path;
+ mail_folder_cache_set_update_estorage (fi->url, storage);
+ mail_folder_cache_note_folderinfo (fi->url, fi);
+
path = g_strdup_printf ("%s/%s", prefix, fi->name);
- evolution_storage_new_folder (storage, path, name,
+ evolution_storage_new_folder (storage, path, fi->name,
"mail", fi->url ? fi->url : "",
fi->name, /* description */
fi->unread_message_count > 0);
- g_free (name);
-
+
if (fi->child)
create_folders (storage, path, fi->child);
g_free (path);
diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c
new file mode 100644
index 0000000000..db1d0e034d
--- /dev/null
+++ b/mail/mail-folder-cache.c
@@ -0,0 +1,798 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* mail-folder-cache.c: Stores information about open folders */
+
+/*
+ * Authors: Peter Williams <peterw@ximian.com>
+ *
+ * Copyright 2000,2001 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <bonobo/bonobo-exception.h>
+
+#include "mail-mt.h"
+#include "mail-folder-cache.h"
+
+#define ld(x)
+#define d(x)
+#define dm(args...) /*g_message ("folder cache: " args)*/
+
+/* Structures */
+
+typedef enum mail_folder_info_flags {
+ MAIL_FIF_UNREAD_VALID = (1 << 0),
+ MAIL_FIF_TOTAL_VALID = (1 << 1),
+ MAIL_FIF_HIDDEN_VALID = (1 << 2),
+ MAIL_FIF_FOLDER_VALID = (1 << 3),
+ MAIL_FIF_NEED_UPDATE = (1 << 4),
+ MAIL_FIF_PATH_VALID = (1 << 5),
+ MAIL_FIF_NAME_VALID = (1 << 6),
+ MAIL_FIF_UPDATE_QUEUED = (1 << 7)
+} mfif;
+
+typedef enum mail_folder_info_update_mode {
+ MAIL_FIUM_UNKNOWN,
+ MAIL_FIUM_EVOLUTION_STORAGE,
+ MAIL_FIUM_LOCAL_STORAGE /*,*/
+ /*MAIL_FIUM_SHELL_VIEW*/
+} mfium;
+
+typedef union mail_folder_info_update_info {
+ EvolutionStorage *es;
+ GNOME_Evolution_LocalStorage ls;
+} mfiui;
+
+typedef struct _mail_folder_info {
+ gchar *uri;
+ gchar *path;
+
+ CamelFolder *folder;
+ gchar *name;
+
+ guint flags;
+ guint unread, total, hidden;
+
+ mfium update_mode;
+ mfiui update_info;
+} mail_folder_info;
+
+static GHashTable *folders = NULL;
+static GStaticMutex folders_lock = G_STATIC_MUTEX_INIT;
+
+#define LOCK_FOLDERS() G_STMT_START { ld(dm ("Locking folders")); g_static_mutex_lock (&folders_lock); } G_STMT_END
+#define UNLOCK_FOLDERS() G_STMT_START { ld(dm ("Unocking folders")); g_static_mutex_unlock (&folders_lock); } G_STMT_END
+
+static GNOME_Evolution_ShellView shell_view = CORBA_OBJECT_NIL;
+
+/* Private functions */
+
+static mail_folder_info *
+get_folder_info (const gchar *uri)
+{
+ mail_folder_info *mfi;
+
+ g_return_val_if_fail (uri, NULL);
+
+ LOCK_FOLDERS ();
+
+ if (folders == NULL) {
+ dm("Initializing");
+ folders = g_hash_table_new (g_str_hash, g_str_equal);
+ }
+
+ mfi = g_hash_table_lookup (folders, uri);
+
+ if (!mfi) {
+ dm("New entry for uri %s", uri);
+
+ mfi = g_new (mail_folder_info, 1);
+ mfi->uri = g_strdup (uri); /* XXX leak leak leak */
+ mfi->path = NULL;
+ mfi->folder = NULL;
+ mfi->name = NULL;
+ mfi->flags = 0;
+ mfi->update_mode = MAIL_FIUM_UNKNOWN;
+ mfi->update_info.es = NULL;
+
+ g_hash_table_insert (folders, mfi->uri, mfi);
+ } else
+ dm("Hit cache for uri %s", uri);
+
+ UNLOCK_FOLDERS ();
+
+ return mfi;
+}
+
+static gchar *
+make_string (mail_folder_info *mfi, gboolean full)
+{
+ gboolean set_one = FALSE;
+ GString *work;
+ gchar *ret;
+
+ LOCK_FOLDERS ();
+
+ /* Build the display string */
+
+ work = g_string_new (mfi->name);
+
+ if (mfi->flags == 0)
+ goto done;
+
+ if (!full &&
+ (!(mfi->flags & MAIL_FIF_UNREAD_VALID) ||
+ mfi->unread == 0))
+ goto done;
+
+ work = g_string_append (work, " (");
+
+ if (full) {
+ if (mfi->flags & MAIL_FIF_UNREAD_VALID) {
+ g_string_sprintfa (work, _("%d new"), mfi->unread);
+ set_one = TRUE;
+ }
+
+ if (mfi->flags & MAIL_FIF_HIDDEN_VALID) {
+ if (set_one)
+ work = g_string_append (work, _(", "));
+ g_string_sprintfa (work, _("%d hidden"), mfi->hidden);
+ set_one = TRUE;
+ }
+
+ if (mfi->flags & MAIL_FIF_TOTAL_VALID) {
+ if (set_one)
+ work = g_string_append (work, _(", "));
+ g_string_sprintfa (work, _("%d total"), mfi->total);
+ }
+ } else {
+ g_string_sprintfa (work, "%d", mfi->unread);
+ }
+
+ work = g_string_append (work, ")");
+
+ done:
+ UNLOCK_FOLDERS ();
+ ret = work->str;
+ g_string_free (work, FALSE);
+ return ret;
+}
+
+static gboolean
+update_idle (gpointer user_data)
+{
+ mail_folder_info *mfi = (mail_folder_info *) user_data;
+ gchar *wide, *thin;
+ gboolean bold;
+ gchar *uri, *path;
+ mfiui info;
+ mfium mode;
+ CORBA_Environment ev;
+
+ LOCK_FOLDERS ();
+
+ dm("update_idle called");
+
+ mfi->flags &= (~MAIL_FIF_UPDATE_QUEUED);
+
+ /* Check if this makes sense */
+
+ if (!(mfi->flags & MAIL_FIF_NAME_VALID)) {
+ g_warning ("Folder cache update info without \'name\' set");
+ UNLOCK_FOLDERS ();
+ return FALSE;
+ }
+
+ if (mfi->update_mode == MAIL_FIUM_UNKNOWN) {
+ g_warning ("Folder cache update info without \'mode\' set");
+ UNLOCK_FOLDERS ();
+ return FALSE;
+ }
+
+ /* Get the display string */
+
+ UNLOCK_FOLDERS ();
+ wide = make_string (mfi, TRUE);
+ thin = make_string (mfi, FALSE);
+ LOCK_FOLDERS ();
+
+ /* bold? */
+
+ if (mfi->flags & MAIL_FIF_UNREAD_VALID &&
+ mfi->unread)
+ bold = TRUE;
+ else
+ bold = FALSE;
+
+ /* Set the value */
+ /* Who knows how long these corba calls will take? */
+ info = mfi->update_info;
+ uri = g_strdup (mfi->uri);
+ if (mfi->flags & MAIL_FIF_PATH_VALID)
+ path = g_strdup (mfi->path);
+ else
+ path = NULL;
+ mode = mfi->update_mode;
+
+ UNLOCK_FOLDERS ();
+
+ switch (mode) {
+ case MAIL_FIUM_LOCAL_STORAGE:
+ dm("Updating via LocalStorage");
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_LocalStorage_updateFolder (info.ls,
+ path,
+ thin,
+ bold,
+ &ev);
+ if (BONOBO_EX (&ev))
+ g_warning ("Exception in local storage update: %s",
+ bonobo_exception_get_text (&ev));
+ CORBA_exception_free (&ev);
+ break;
+ case MAIL_FIUM_EVOLUTION_STORAGE:
+ dm("Updating via EvolutionStorage");
+ evolution_storage_update_folder_by_uri (info.es,
+ uri,
+ thin,
+ bold);
+ break;
+ case MAIL_FIUM_UNKNOWN:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ /* Now set the folder bar if possible */
+
+ if (shell_view != CORBA_OBJECT_NIL) {
+ dm("Updating via ShellView");
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_ShellView_setFolderBarLabel (shell_view,
+ wide,
+ &ev);
+ if (BONOBO_EX (&ev))
+ g_warning ("Exception in folder bar label update: %s",
+ bonobo_exception_get_text (&ev));
+ CORBA_exception_free (&ev);
+
+#if 0
+ GNOME_Evolution_ShellView_setTitle (shell_view,
+ wide,
+ &ev);
+ if (BONOBO_EX (&ev))
+ g_warning ("Exception in shell view title update: %s",
+ bonobo_exception_get_text (&ev));
+ CORBA_exception_free (&ev);
+#endif
+ }
+
+ /* Cleanup */
+
+ g_free (uri);
+ if (path)
+ g_free (path);
+ g_free (wide);
+ g_free (thin);
+ return FALSE;
+}
+
+static void
+maybe_update (mail_folder_info *mfi)
+{
+ if (mfi->flags & MAIL_FIF_UPDATE_QUEUED)
+ return;
+
+ mfi->flags |= MAIL_FIF_UPDATE_QUEUED;
+ g_idle_add (update_idle, mfi);
+}
+
+static void
+update_message_counts_main (CamelObject *object, gpointer event_data,
+ gpointer user_data)
+{
+ mail_folder_info *mfi = user_data;
+
+ LOCK_FOLDERS ();
+ dm("Message counts in CamelFolder changed, queuing idle");
+ mfi->flags &= (~MAIL_FIF_NEED_UPDATE);
+ maybe_update (mfi);
+ UNLOCK_FOLDERS ();
+}
+
+static void
+update_message_counts (CamelObject *object, gpointer event_data,
+ gpointer user_data)
+{
+ CamelFolder *folder = CAMEL_FOLDER (object);
+ mail_folder_info *mfi = user_data;
+ int unread;
+ int total;
+
+ dm("CamelFolder %p changed, examining message counts", object);
+
+ unread = camel_folder_get_unread_message_count (folder);
+ total = camel_folder_get_message_count (folder);
+
+ LOCK_FOLDERS ();
+
+ mfi->flags &= (~MAIL_FIF_NEED_UPDATE);
+
+ if (mfi->flags & MAIL_FIF_UNREAD_VALID) {
+ if (mfi->unread != unread) {
+ dm ("-> Unread value is changed");
+ mfi->unread = unread;
+ mfi->flags |= MAIL_FIF_NEED_UPDATE;
+ } else
+ dm ("-> Unread value is the same");
+ } else {
+ dm ("-> Unread value being initialized");
+ mfi->flags |= (MAIL_FIF_UNREAD_VALID | MAIL_FIF_NEED_UPDATE);
+ mfi->unread = unread;
+ }
+
+ if (mfi->flags & MAIL_FIF_TOTAL_VALID) {
+ if (mfi->total != total) {
+ dm ("-> Total value is changed");
+ mfi->total = total;
+ mfi->flags |= MAIL_FIF_NEED_UPDATE;
+ } else
+ dm ("-> Total value is the same");
+ } else {
+ dm ("-> Total value being initialized");
+ mfi->flags |= (MAIL_FIF_TOTAL_VALID | MAIL_FIF_NEED_UPDATE);
+ mfi->total = total;
+ }
+
+ /* while we're here... */
+ if (!(mfi->flags & MAIL_FIF_NAME_VALID)) {
+ mfi->name = g_strdup (camel_folder_get_name (CAMEL_FOLDER (object)));
+ dm ("-> setting name to %s as well", mfi->name);
+ mfi->flags |= MAIL_FIF_NAME_VALID;
+ }
+
+ if (mfi->flags & MAIL_FIF_NEED_UPDATE) {
+ UNLOCK_FOLDERS ();
+ dm ("-> Queuing change");
+ mail_proxy_event (update_message_counts_main, object, event_data, user_data);
+ } else {
+ UNLOCK_FOLDERS ();
+ dm ("-> No proxy event needed");
+ }
+}
+
+static void
+camel_folder_finalized (CamelObject *object, gpointer event_data,
+ gpointer user_data)
+{
+ mail_folder_info *mfi = user_data;
+
+ dm ("CamelFolder %p finalized, unsetting FOLDER_VALID", object);
+
+ camel_object_unhook_event (object, "message_changed",
+ update_message_counts, mfi);
+ camel_object_unhook_event (object, "folder_changed",
+ update_message_counts, mfi);
+
+ LOCK_FOLDERS ();
+ mfi->flags &= (~MAIL_FIF_FOLDER_VALID);
+ mfi->folder = NULL;
+ UNLOCK_FOLDERS ();
+}
+
+static void
+message_list_built (MessageList *ml, gpointer user_data)
+{
+ mail_folder_info *mfi = user_data;
+
+ dm ("Message list %p rebuilt, checking hidden", ml);
+
+ LOCK_FOLDERS ();
+
+ if (ml->folder != mfi->folder) {
+ g_warning ("folder cache: different folders in cache and messagelist");
+ gtk_signal_disconnect_by_data (GTK_OBJECT (ml), user_data);
+ UNLOCK_FOLDERS ();
+ return;
+ }
+
+ MESSAGE_LIST_LOCK (ml, hide_lock);
+ if (ml->hidden)
+ mfi->hidden = g_hash_table_size (ml->hidden);
+ else
+ mfi->hidden = 0;
+ MESSAGE_LIST_UNLOCK (ml, hide_lock);
+
+ mfi->flags |= MAIL_FIF_HIDDEN_VALID;
+
+ UNLOCK_FOLDERS ();
+
+ maybe_update (mfi);
+}
+
+/* get folder info operation */
+
+struct get_mail_info_msg {
+ struct _mail_msg msg;
+
+ CamelFolder *folder;
+ mail_folder_info *mfi;
+};
+
+static char *
+get_mail_info_describe (struct _mail_msg *msg, int complete)
+{
+ struct get_mail_info_msg *gmim = (struct get_mail_info_msg *) msg;
+
+ return g_strdup_printf ("Examining \'%s\'", camel_folder_get_full_name (gmim->folder));
+}
+
+static void
+get_mail_info_receive (struct _mail_msg *msg)
+{
+ struct get_mail_info_msg *gmim = (struct get_mail_info_msg *) msg;
+
+ LOCK_FOLDERS ();
+
+ if (!(gmim->mfi->flags & MAIL_FIF_NAME_VALID)) {
+ gmim->mfi->name = g_strdup (camel_folder_get_name (gmim->folder));
+ gmim->mfi->flags |= MAIL_FIF_NAME_VALID;
+ }
+
+ gmim->mfi->unread = camel_folder_get_unread_message_count (gmim->folder);
+ gmim->mfi->total = camel_folder_get_message_count (gmim->folder);
+ gmim->mfi->flags |= (MAIL_FIF_UNREAD_VALID | MAIL_FIF_TOTAL_VALID);
+
+ UNLOCK_FOLDERS ();
+}
+
+static void
+get_mail_info_reply (struct _mail_msg *msg)
+{
+ struct get_mail_info_msg *gmim = (struct get_mail_info_msg *) msg;
+
+ maybe_update (gmim->mfi);
+}
+
+static void
+get_mail_info_destroy (struct _mail_msg *msg)
+{
+ struct get_mail_info_msg *gmim = (struct get_mail_info_msg *) msg;
+
+ camel_object_unref (CAMEL_OBJECT (gmim->folder));
+}
+
+static mail_msg_op_t get_mail_info_op = {
+ get_mail_info_describe,
+ get_mail_info_receive,
+ get_mail_info_reply,
+ get_mail_info_destroy
+};
+
+static void
+get_mail_info (CamelFolder *folder, mail_folder_info *mfi)
+{
+ struct get_mail_info_msg *gmim;
+
+ gmim = mail_msg_new (&get_mail_info_op, NULL, sizeof (*gmim));
+ gmim->folder = folder;
+ camel_object_ref (CAMEL_OBJECT (folder));
+ gmim->mfi = mfi;
+
+ e_thread_put (mail_thread_new, (EMsg *) gmim);
+}
+
+/* Public functions */
+
+void
+mail_folder_cache_set_update_estorage (const gchar *uri, EvolutionStorage *estorage)
+{
+ mail_folder_info *mfi;
+
+ mfi = get_folder_info (uri);
+ g_return_if_fail (mfi);
+
+ LOCK_FOLDERS ();
+
+ if (mfi->update_mode != MAIL_FIUM_UNKNOWN) {
+ /* we could check to see that update_mode = ESTORAGE */
+ /*g_warning ("folder cache: update mode already set??");*/
+ UNLOCK_FOLDERS ();
+ return;
+ }
+
+ dm ("Uri %s updates with EVOLUTION_STORAGE", uri);
+ mfi->update_mode = MAIL_FIUM_EVOLUTION_STORAGE;
+ mfi->update_info.es = estorage;
+
+ UNLOCK_FOLDERS ();
+}
+
+void
+mail_folder_cache_set_update_lstorage (const gchar *uri, GNOME_Evolution_LocalStorage lstorage, const gchar *path)
+{
+ mail_folder_info *mfi;
+
+ mfi = get_folder_info (uri);
+ g_return_if_fail (mfi);
+
+ LOCK_FOLDERS ();
+
+ if (mfi->update_mode != MAIL_FIUM_UNKNOWN) {
+ /*we could check to see that update_mode = lstorage */
+ /*g_warning ("folder cache: update mode already set??");*/
+ UNLOCK_FOLDERS ();
+ return;
+ }
+
+ dm ("Uri %s updates with LOCAL_STORAGE", uri);
+ /* Note that we don't dup the object or anything. Too lazy. */
+ mfi->update_mode = MAIL_FIUM_LOCAL_STORAGE;
+ mfi->update_info.ls = lstorage;
+
+ mfi->path = g_strdup (path);
+ mfi->flags |= MAIL_FIF_PATH_VALID;
+
+ UNLOCK_FOLDERS ();
+}
+
+#if 0
+void
+mail_folder_cache_set_update_shellview (const gchar *uri)
+{
+ mail_folder_info *mfi;
+
+ mfi = get_folder_info (uri);
+ g_return_if_fail (mfi);
+
+ LOCK_FOLDERS ();
+
+ if (mfi->update_mode != MAIL_FIUM_UNKNOWN) {
+ /*we could check to see that update_mode = shellview */
+ /*g_warning ("folder cache: update mode already set??");*/
+ UNLOCK_FOLDERS ();
+ return;
+ }
+
+ dm ("Uri %s updates with SHELL VIEW", uri);
+ mfi->update_mode = MAIL_FIUM_SHELL_VIEW;
+
+ UNLOCK_FOLDERS ();
+}
+#endif
+
+void
+mail_folder_cache_note_folder (const gchar *uri, CamelFolder *folder)
+{
+ mail_folder_info *mfi;
+
+ mfi = get_folder_info (uri);
+ g_return_if_fail (mfi);
+
+ LOCK_FOLDERS ();
+
+ if (mfi->flags & MAIL_FIF_FOLDER_VALID) {
+ if (mfi->folder != folder)
+ g_warning ("folder cache: CamelFolder being changed for %s??? I refuse.", uri);
+ UNLOCK_FOLDERS ();
+ return;
+ }
+
+ dm ("Setting uri %s to watch folder %p", uri, folder);
+
+ mfi->flags |= MAIL_FIF_FOLDER_VALID;
+ mfi->folder = folder;
+
+ UNLOCK_FOLDERS ();
+
+ camel_object_hook_event (CAMEL_OBJECT (folder), "message_changed",
+ update_message_counts, mfi);
+ camel_object_hook_event (CAMEL_OBJECT (folder), "folder_changed",
+ update_message_counts, mfi);
+ camel_object_hook_event (CAMEL_OBJECT (folder), "finalize",
+ camel_folder_finalized, mfi);
+
+ get_mail_info (folder, mfi);
+}
+
+void
+mail_folder_cache_note_message_list (const gchar *uri, MessageList *ml)
+{
+ mail_folder_info *mfi;
+
+ mfi = get_folder_info (uri);
+ g_return_if_fail (mfi);
+
+ LOCK_FOLDERS ();
+
+ if (!(mfi->flags & MAIL_FIF_FOLDER_VALID)) {
+ dm ("No folder specified so ignoring NOTE_ML at %s", uri);
+ /* cache the FB? maybe later */
+ UNLOCK_FOLDERS ();
+ return;
+ }
+
+ dm ("Noting message list %p for %s", ml, uri);
+
+ gtk_signal_connect (GTK_OBJECT (ml), "message_list_built",
+ message_list_built, mfi);
+
+ UNLOCK_FOLDERS ();
+
+ dm ("-> faking message_list_built", ml, uri);
+ message_list_built (ml, mfi);
+}
+
+void
+mail_folder_cache_note_folderinfo (const gchar *uri, CamelFolderInfo *fi)
+{
+ mail_folder_info *mfi;
+
+ mfi = get_folder_info (uri);
+ g_return_if_fail (mfi);
+
+ LOCK_FOLDERS ();
+
+ dm ("Noting folderinfo %p for %s", fi, uri);
+
+ mfi->unread = fi->unread_message_count;
+ mfi->flags |= MAIL_FIF_UNREAD_VALID;
+
+ if (!(mfi->flags & MAIL_FIF_NAME_VALID)) {
+ dm ("-> setting name %s", fi->name);
+ mfi->name = g_strdup (fi->name);
+ mfi->flags |= MAIL_FIF_NAME_VALID;
+ }
+
+ UNLOCK_FOLDERS ();
+
+ maybe_update (mfi);
+}
+
+void
+mail_folder_cache_note_name (const gchar *uri, const gchar *name)
+{
+ mail_folder_info *mfi;
+
+ mfi = get_folder_info (uri);
+ g_return_if_fail (mfi);
+
+ LOCK_FOLDERS ();
+
+ dm ("Noting name %s for %s", name, uri);
+
+ if (mfi->flags & MAIL_FIF_NAME_VALID) {
+ /* we could complain.. */
+ dm ("-> name already set: %s", mfi->name);
+ UNLOCK_FOLDERS ();
+ return;
+ }
+
+ mfi->name = g_strdup (name);
+ mfi->flags |= MAIL_FIF_NAME_VALID;
+
+ UNLOCK_FOLDERS ();
+
+ maybe_update (mfi);
+}
+
+CamelFolder *
+mail_folder_cache_try_folder (const gchar *uri)
+{
+ mail_folder_info *mfi;
+ CamelFolder *ret;
+
+ mfi = get_folder_info (uri);
+ g_return_val_if_fail (mfi, NULL);
+
+ LOCK_FOLDERS ();
+
+ if (mfi->flags & MAIL_FIF_FOLDER_VALID)
+ ret = mfi->folder;
+ else
+ ret = NULL;
+
+ UNLOCK_FOLDERS ();
+
+ return ret;
+}
+
+void
+mail_folder_cache_set_shell_view (GNOME_Evolution_ShellView sv)
+{
+ CORBA_Environment ev;
+
+ g_return_if_fail (sv != CORBA_OBJECT_NIL);
+
+ CORBA_exception_init (&ev);
+
+ if (shell_view != CORBA_OBJECT_NIL)
+ CORBA_Object_release (shell_view, &ev);
+
+ if (BONOBO_EX (&ev))
+ g_warning ("Exception in releasing old shell view: %s",
+ bonobo_exception_get_text (&ev));
+ CORBA_exception_free (&ev);
+
+ shell_view = CORBA_Object_duplicate (sv, &ev);
+ if (BONOBO_EX (&ev))
+ g_warning ("Exception in duping new shell view: %s",
+ bonobo_exception_get_text (&ev));
+ CORBA_exception_free (&ev);
+}
+
+#if d(!)0
+#include <stdio.h>
+
+static void
+print_item (gpointer key, gpointer value, gpointer user_data)
+{
+ gchar *uri = key;
+ mail_folder_info *mfi = value;
+
+ printf ("* %s\n", uri);
+
+ if (mfi->flags & MAIL_FIF_PATH_VALID)
+ printf (" Path: %s\n", mfi->path);
+ if (mfi->flags & MAIL_FIF_NAME_VALID)
+ printf (" Name: %s\n", mfi->name);
+ if (mfi->flags & MAIL_FIF_FOLDER_VALID)
+ printf (" Folder: %p\n", mfi->folder);
+ if (mfi->flags & MAIL_FIF_UNREAD_VALID)
+ printf (" Unread: %d\n", mfi->unread);
+ if (mfi->flags & MAIL_FIF_HIDDEN_VALID)
+ printf (" Hidden: %d\n", mfi->hidden);
+ if (mfi->flags & MAIL_FIF_TOTAL_VALID)
+ printf (" Total: %d\n", mfi->total);
+ if (mfi->flags & MAIL_FIF_NEED_UPDATE)
+ printf (" Needs an update\n");
+ switch (mfi->update_mode) {
+ case MAIL_FIUM_UNKNOWN:
+ printf (" Update mode: UNKNOWN\n");
+ break;
+ case MAIL_FIUM_EVOLUTION_STORAGE:
+ printf (" Update mode: Evolution\n");
+ break;
+ case MAIL_FIUM_LOCAL_STORAGE:
+ printf (" Update mode: Local\n");
+ break;
+/*
+ case MAIL_FIUM_SHELL_VIEW:
+ printf (" Update mode: Shell View\n");
+ break;
+*/
+ }
+
+ printf ("\n");
+}
+
+void mail_folder_cache_dump_cache (void);
+
+void
+mail_folder_cache_dump_cache (void)
+{
+ printf ("********** MAIL FOLDER CACHE DUMP ************\n\n");
+ LOCK_FOLDERS ();
+ g_hash_table_foreach (folders, print_item, NULL);
+ UNLOCK_FOLDERS ();
+ printf ("********** END OF CACHE DUMP. ****************\n");
+}
+
+#endif
diff --git a/mail/mail-folder-cache.h b/mail/mail-folder-cache.h
new file mode 100644
index 0000000000..dbb4be7fd6
--- /dev/null
+++ b/mail/mail-folder-cache.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* mail-folder-cache.h: Stores information about open folders */
+
+/*
+ * Authors: Peter Williams <peterw@ximian.com>
+ *
+ * Copyright 2000,2001 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef _MAIL_FOLDER_CACHE_H
+#define _MAIL_FOLDER_CACHE_H
+
+#include <camel/camel-folder.h>
+#include <camel/camel-store.h>
+#include <shell/evolution-storage.h>
+#include <shell/Evolution.h>
+
+#include "folder-browser.h"
+
+/* No real order that these functions should be called. The idea is that whenever a
+ * chunk of the mailer gets some up-to-date information about a URI, it calls one
+ * of the _note_ functions and the folder cache sees to it that the information is
+ * put to good use.
+ *
+ * Thus there is no way to remove items from the cache. So it leaks a lot.
+ */
+
+void mail_folder_cache_set_update_estorage (const gchar *uri, EvolutionStorage *estorage);
+void mail_folder_cache_set_update_lstorage (const gchar *uri,
+ GNOME_Evolution_LocalStorage lstorage,
+ const gchar *path);
+/* We always update the shell view */
+/*void mail_folder_cache_set_update_shellview (const gchar *uri);*/
+
+void mail_folder_cache_note_folder (const gchar *uri, CamelFolder *folder);
+void mail_folder_cache_note_message_list (const gchar *uri, MessageList *ml);
+void mail_folder_cache_note_folderinfo (const gchar *uri, CamelFolderInfo *fi);
+void mail_folder_cache_note_name (const gchar *uri, const gchar *name);
+
+CamelFolder *mail_folder_cache_try_folder (const gchar *uri);
+
+void mail_folder_cache_set_shell_view (GNOME_Evolution_ShellView sv);
+
+#endif
diff --git a/mail/mail-local.c b/mail/mail-local.c
index 017125f8b2..56b68344e0 100644
--- a/mail/mail-local.c
+++ b/mail/mail-local.c
@@ -65,7 +65,7 @@
#include "mail-tools.h"
#include "folder-browser.h"
#include "mail-mt.h"
-
+#include "mail-folder-cache.h"
#include "mail-vfolder.h"
#define d(x)
@@ -183,7 +183,6 @@ typedef struct {
char *local_path;
int local_pathlen;
GHashTable *folders; /* points to MailLocalFolder */
- GHashTable *unread;
} MailLocalStore;
typedef struct {
@@ -194,15 +193,12 @@ typedef struct {
CamelFolder *folder;
MailLocalStore *local_store;
char *path, *name, *uri;
- int last_unread;
} MailLocalFolder;
static MailLocalStore *local_store;
CamelType mail_local_store_get_type (void);
-static void local_folder_changed_proxy (CamelObject *folder, gpointer event_data, gpointer user_data);
-
static char *get_name (CamelService *service, gboolean brief);
static CamelFolder *get_folder (CamelStore *store, const char *folder_name,
@@ -254,15 +250,9 @@ 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);
+ if (lf->folder)
camel_object_unref((CamelObject *)lf->folder);
- }
+
g_free(lf->path);
g_free(lf->name);
g_free(lf->uri);
@@ -447,47 +437,6 @@ local_storage_destroyed_cb (EvolutionStorageListener *storage_listener,
g_warning ("%s -- The LocalStorage has gone?!", __FILE__);
}
-
-static void
-local_folder_changed (CamelObject *object, gpointer event_data,
- gpointer user_data)
-{
- MailLocalFolder *local_folder = user_data;
- int unread = GPOINTER_TO_INT (event_data);
- char *display;
-
- if (unread != local_folder->last_unread) {
- CORBA_Environment ev;
-
- CORBA_exception_init (&ev);
- if (unread > 0) {
- 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);
- g_free (display);
- } else {
- GNOME_Evolution_LocalStorage_updateFolder (
- local_folder->local_store->corba_local_storage,
- local_folder->path, local_folder->name,
- FALSE, &ev);
- }
- CORBA_exception_free (&ev);
-
- local_folder->last_unread = unread;
- }
-}
-
-static void
-local_folder_changed_proxy (CamelObject *folder, gpointer event_data, gpointer user_data)
-{
- int unread;
-
- unread = camel_folder_get_unread_message_count (CAMEL_FOLDER (folder));
- mail_proxy_event (local_folder_changed, folder,
- GINT_TO_POINTER (unread), user_data);
-}
-
/* ********************************************************************** */
/* Register folder */
@@ -536,15 +485,6 @@ register_folder_register(struct _mail_msg *mm)
if (meta->indexed)
flags |= CAMEL_STORE_FOLDER_BODY_INDEX;
local_folder->folder = camel_store_get_folder (store, meta->name, flags, &mm->ex);
- if (local_folder->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);
- local_folder->last_unread = camel_folder_get_unread_message_count(local_folder->folder);
- }
camel_object_unref (CAMEL_OBJECT (store));
free_metainfo (meta);
@@ -557,9 +497,10 @@ register_folder_registered(struct _mail_msg *mm)
{
struct _register_msg *m = (struct _register_msg *)mm;
MailLocalFolder *local_folder = m->local_folder;
- int unread;
if (local_folder->folder) {
+ gchar *name;
+
g_hash_table_insert (local_folder->local_store->folders, local_folder->uri + 8,
local_folder);
/* Remove the circular ref once the local store knows aboutthe folder */
@@ -567,11 +508,20 @@ register_folder_registered(struct _mail_msg *mm)
/* add the folder to the vfolder lists FIXME: merge stuff above with this */
vfolder_register_source(local_folder->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);
+
+ mail_folder_cache_set_update_lstorage (local_folder->uri,
+ local_folder->local_store->corba_local_storage,
+ local_folder->path);
+
+ name = strrchr (local_folder->path, '/');
+ if (name) /* should always be true... */ {
+ name += 1; /* skip the slash */
+ mail_folder_cache_note_name (local_folder->uri, name);
+ }
+
+ /* Do this after specifying the name so it isn't 'mbox' */
+ mail_folder_cache_note_folder (local_folder->uri, local_folder->folder);
+
m->local_folder = NULL;
}
}
@@ -860,12 +810,7 @@ reconfigure_folder_reconfigure(struct _mail_msg *mm)
/* first, 'close' the old folder */
update_progress(_("Closing current folder"), 0.0);
camel_folder_sync(local_folder->folder, FALSE, &mm->ex);
- 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);
+
/* Once for the FolderBrowser, once for the local store */
camel_object_unref(CAMEL_OBJECT(local_folder->folder));
camel_object_unref(CAMEL_OBJECT(local_folder->folder));
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index 02b936d1f8..0fd73805fa 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -46,6 +46,7 @@
#include "filter/filter-filter.h"
#include "mail-mt.h"
+#include "mail-folder-cache.h"
#define d(x) x
@@ -360,20 +361,19 @@ struct _update_info {
static void
do_update_subfolders_rec (CamelStore *store, CamelFolderInfo *info, EvolutionStorage *storage, const char *prefix)
{
- char *path, *name;
+ char *path;
+ /* info->url == URI??? */
+ mail_folder_cache_set_update_estorage (info->url, storage);
+ mail_folder_cache_note_folderinfo (info->url, info);
+
path = g_strdup_printf("%s/%s", prefix, info->name);
- if (info->unread_message_count > 0)
- name = g_strdup_printf("%s (%d)", info->name, info->unread_message_count);
- else
- name = g_strdup(info->name);
-
- evolution_storage_update_folder(storage, path, name, info->unread_message_count > 0);
- g_free(name);
+
if (info->child)
do_update_subfolders_rec(store, info->child, storage, path);
if (info->sibling)
do_update_subfolders_rec(store, info->sibling, storage, prefix);
+
g_free(path);
}
diff --git a/mail/mail-tools.c b/mail/mail-tools.c
index 971f4fcc1c..8ca30bced8 100644
--- a/mail/mail-tools.c
+++ b/mail/mail-tools.c
@@ -44,6 +44,7 @@
#include "mail-tools.h"
#include "mail-local.h"
#include "mail-mt.h"
+#include "mail-folder-cache.h"
#include "e-util/e-html-utils.h"
/* **************************************** */
@@ -245,92 +246,6 @@ mail_tool_make_message_attachment (CamelMimeMessage *message)
return part;
}
-struct folder_cache_info {
- char *uri;
- CamelFolder *folder;
- int unread;
-};
-
-static void
-update_unread_count_main (CamelObject *object, gpointer event_data,
- gpointer user_data)
-{
- CamelFolder *folder = (CamelFolder *)object;
- struct folder_cache_info *fci = user_data;
- EvolutionStorage *storage;
- char *name;
-
- storage = mail_lookup_storage (folder->parent_store);
- if (fci->unread == 0)
- name = g_strdup (camel_folder_get_name (folder));
- else
- name = g_strdup_printf ("%s (%d)", camel_folder_get_name (folder), fci->unread);
-
- evolution_storage_update_folder_by_uri (storage, fci->uri, name,
- fci->unread != 0);
- g_free (name);
- gtk_object_unref (GTK_OBJECT (storage));
- camel_object_unref (object);
-}
-
-static void
-update_unread_count (CamelObject *object, gpointer event_data,
- gpointer user_data)
-{
- CamelFolder *folder = (CamelFolder *)object;
- struct folder_cache_info *fci = user_data;
- int unread;
-
- unread = camel_folder_get_unread_message_count (folder);
- if (unread == fci->unread)
- return;
- fci->unread = unread;
- camel_object_ref (object);
- mail_proxy_event (update_unread_count_main, object, event_data, user_data);
-}
-
-static GHashTable *folders = NULL;
-static GStaticMutex folders_lock = G_STATIC_MUTEX_INIT;
-
-static void
-uncache_folder (CamelObject *folder, gpointer event_data, gpointer user_data)
-{
- struct folder_cache_info *fci = user_data;
-
- g_static_mutex_lock (&folders_lock);
- g_hash_table_remove (folders, fci->uri);
- g_static_mutex_unlock (&folders_lock);
-
- g_free (fci->uri);
- g_free (fci);
-}
-
-static void
-cache_folder (CamelFolder *folder, const char *uri)
-{
- CamelObject *object = CAMEL_OBJECT (folder);
- EvolutionStorage *storage;
- struct folder_cache_info *fci;
-
- fci = g_new (struct folder_cache_info, 1);
- fci->folder = folder;
- fci->uri = g_strdup (uri);
- fci->unread = 0;
-
- g_hash_table_insert (folders, fci->uri, fci);
- camel_object_hook_event (object, "finalize", uncache_folder, fci);
-
- storage = mail_lookup_storage (folder->parent_store);
- if (storage) {
- gtk_object_unref (GTK_OBJECT (storage));
- update_unread_count (object, NULL, fci);
- camel_object_hook_event (object, "message_changed",
- update_unread_count, fci);
- camel_object_hook_event (object, "folder_changed",
- update_unread_count, fci);
- }
-}
-
CamelFolder *
mail_tool_uri_to_folder (const char *uri, CamelException *ex)
{
@@ -341,19 +256,10 @@ mail_tool_uri_to_folder (const char *uri, CamelException *ex)
g_return_val_if_fail (uri != NULL, NULL);
- g_static_mutex_lock (&folders_lock);
- if (folders) {
- struct folder_cache_info *fci;
-
- fci = g_hash_table_lookup (folders, uri);
- g_static_mutex_unlock (&folders_lock);
- if (fci) {
- camel_object_ref (CAMEL_OBJECT (fci->folder));
- return fci->folder;
- }
- } else {
- folders = g_hash_table_new (g_str_hash, g_str_equal);
- g_static_mutex_unlock (&folders_lock);
+ folder = mail_folder_cache_try_folder (uri);
+ if (folder) {
+ camel_object_ref (CAMEL_OBJECT (folder));
+ return folder;
}
if (!strncmp (uri, "vtrash:", 7))
@@ -399,10 +305,7 @@ mail_tool_uri_to_folder (const char *uri, CamelException *ex)
}
camel_url_free (url);
- g_static_mutex_lock (&folders_lock);
- if (!g_hash_table_lookup (folders, uri))
- cache_folder (folder, uri);
- g_static_mutex_unlock (&folders_lock);
+ mail_folder_cache_note_folder (uri, folder);
return folder;
}