[evolution-patches] IMAP startup patch
- From: Not Zed <notzed ximian com>
- To: asdf <evolution-patches lists ximian com>
- Subject: [evolution-patches] IMAP startup patch
- Date: Wed, 20 Jul 2005 17:59:28 +0800
Hi all,
This is a bigger patch than it looks, it changes the semantics of
getting unread counts and how they are updated in the ui a bit.
I dont know how it affects anything other than imap and local, in which
case it works. nntp should work as well as it used to. imap4 and
groupwise i dont know - thats why i'm sending the patch here, so anyone
who cares at least knows about it.
Basically get_folder_info should return counts it can get quickly (the
FAST flag is always passed now). And folder.refresh_info() is the one
which forces an update, under client control.
The code also tries to force a get mail on auto-get-mail'd accounts at
startup, but for various sequence issues this doesn't work yet.
I also made another slight change so that if it can't load a message for
whatever reason, it just displays 'cant load message\nreason' in the
message area, rather than popping up a 'cant load message\nreason' box.
Which makes things work a lot cleaner and nicer in offline mode.
Michael
Index: camel/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/ChangeLog,v
retrieving revision 1.2455
diff -u -p -r1.2455 ChangeLog
--- camel/ChangeLog 14 Jul 2005 03:05:11 -0000 1.2455
+++ camel/ChangeLog 20 Jul 2005 09:30:40 -0000
@@ -1,3 +1,22 @@
+2005-07-20 Not Zed <NotZed Ximian com>
+
+ * camel-store.c (camel_store_get_folder_info): Changed the
+ semantics slightly. !FAST makes no guarantees about message
+ counts anymore.
+
+ * camel-disco-store.c: fix up some stupid hidden logic here.
+
+2005-07-19 Not Zed <NotZed Ximian com>
+
+ * camel-folder.c (camel_folder_refresh_info): remove the folder
+ lock.
+
+ * camel-disco-store.c (disco_get_folder_info): dont force a
+ connect here, it doesn't belong here.
+
+ * camel-store.c (camel_store_get_folder_info): remove subscription
+ assert.
+
2005-07-13 Not Zed <NotZed Ximian com>
* camel-store.c (camel_store_init): initialise the mode to
Index: camel/camel-disco-store.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-disco-store.c,v
retrieving revision 1.14
diff -u -p -r1.14 camel-disco-store.c
--- camel/camel-disco-store.c 20 Sep 2004 05:59:53 -0000 1.14
+++ camel/camel-disco-store.c 20 Jul 2005 09:30:40 -0000
@@ -193,7 +193,6 @@ disco_cancel_connect (CamelService *serv
/* Fall back */
store->status = CAMEL_DISCO_STORE_OFFLINE;
-
CAMEL_SERVICE_CLASS (parent_class)->cancel_connect (service);
}
@@ -246,16 +245,6 @@ disco_get_folder_info (CamelStore *store
{
CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (store);
- /* Do this first so if we get forced offline, we'll switch to
- * the correct branch below. (FIXME: This only works because
- * we know that get_folder_info is the first call that the
- * mailer makes on a store.)
- */
- if (CAMEL_SERVICE (store)->status == CAMEL_SERVICE_DISCONNECTED) {
- if (!camel_service_connect (CAMEL_SERVICE (store), ex))
- return NULL;
- }
-
switch (camel_disco_store_status (disco_store)) {
case CAMEL_DISCO_STORE_ONLINE:
return CDS_CLASS (store)->get_folder_info_online (store, top, flags, ex);
@@ -292,15 +281,13 @@ camel_disco_store_status (CamelDiscoStor
g_return_val_if_fail (CAMEL_IS_DISCO_STORE (store), CAMEL_DISCO_STORE_ONLINE);
- if (service->status == CAMEL_SERVICE_CONNECTING &&
- store->status == CAMEL_DISCO_STORE_ONLINE &&
- !camel_session_is_online (service->session))
+ if (store->status != CAMEL_DISCO_STORE_OFFLINE
+ && !camel_session_is_online (service->session))
store->status = CAMEL_DISCO_STORE_OFFLINE;
return store->status;
}
-
static void
set_status(CamelDiscoStore *disco_store, CamelDiscoStoreStatus status, CamelException *ex)
{
@@ -362,7 +349,6 @@ camel_disco_store_set_status (CamelDisco
CDS_CLASS (store)->set_status (store, status, ex);
}
-
static gboolean
can_work_offline (CamelDiscoStore *disco_store)
Index: camel/camel-folder.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-folder.c,v
retrieving revision 1.210
diff -u -p -r1.210 camel-folder.c
--- camel/camel-folder.c 6 Jul 2005 04:09:36 -0000 1.210
+++ camel/camel-folder.c 20 Jul 2005 09:30:40 -0000
@@ -296,11 +296,7 @@ camel_folder_refresh_info (CamelFolder *
{
g_return_if_fail (CAMEL_IS_FOLDER (folder));
- CAMEL_FOLDER_LOCK(folder, lock);
-
CF_CLASS (folder)->refresh_info (folder, ex);
-
- CAMEL_FOLDER_UNLOCK(folder, lock);
}
static int
Index: camel/camel-service.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-service.c,v
retrieving revision 1.99
diff -u -p -r1.99 camel-service.c
--- camel/camel-service.c 9 May 2005 20:13:13 -0000 1.99
+++ camel/camel-service.c 20 Jul 2005 09:30:40 -0000
@@ -562,7 +562,6 @@ get_path (CamelService *service)
return path;
}
-
/**
* camel_service_get_path:
* @service: a #CamelService object
Index: camel/camel-store-summary.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-store-summary.c,v
retrieving revision 1.12
diff -u -p -r1.12 camel-store-summary.c
--- camel/camel-store-summary.c 10 May 2005 18:50:37 -0000 1.12
+++ camel/camel-store-summary.c 20 Jul 2005 09:30:41 -0000
@@ -349,7 +349,6 @@ camel_store_summary_path(CamelStoreSumma
return info;
}
-
/**
* camel_store_summary_load:
* @summary: a #CamelStoreSummary object
Index: camel/camel-store.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-store.c,v
retrieving revision 1.165
diff -u -p -r1.165 camel-store.c
--- camel/camel-store.c 14 Jul 2005 03:05:11 -0000 1.165
+++ camel/camel-store.c 20 Jul 2005 09:30:41 -0000
@@ -750,17 +750,22 @@ dump_fi(CamelFolderInfo *fi, int depth)
* This fetches information about the folder structure of @store,
* starting with @top, and returns a tree of CamelFolderInfo
* structures. If @flags includes #CAMEL_STORE_FOLDER_INFO_SUBSCRIBED,
- * only subscribed folders will be listed. (This flag can only be used
- * for stores that support subscriptions.) If @flags includes
+ * only subscribed folders will be listed. If the store doesn't support
+ * subscriptions, then it will list all folders. If @flags includes
* #CAMEL_STORE_FOLDER_INFO_RECURSIVE, the returned tree will include
* all levels of hierarchy below @top. If not, it will only include
* the immediate subfolders of @top. If @flags includes
* #CAMEL_STORE_FOLDER_INFO_FAST, the unread_message_count fields of
* some or all of the structures may be set to %-1, if the store cannot
- * determine that information quickly. If @flags includes
+ * determine that information quickly. If @flags includes
* #CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL, don't include special virtual
* folders (such as vTrash or vJunk).
*
+ * The CAMEL_STORE_FOLDER_INFO_FAST flag should be considered
+ * deprecated; most backends will behave the same whether it is
+ * supplied or not. The only guaranteed way to get updated folder
+ * counts is to both open the folder and invoke refresh_info() it.
+ *
* Returns a #CamelFolderInfo tree, which must be freed with
* #camel_store_free_folder_info
**/
@@ -770,9 +775,6 @@ camel_store_get_folder_info(CamelStore *
CamelFolderInfo *info;
g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
- g_return_val_if_fail ((store->flags & CAMEL_STORE_SUBSCRIPTIONS) ||
- !(flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED),
- NULL);
info = CS_CLASS (store)->get_folder_info (store, top, flags, ex);
Index: camel/camel-store.h
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-store.h,v
retrieving revision 1.77
diff -u -p -r1.77 camel-store.h
--- camel/camel-store.h 14 Jul 2005 03:05:11 -0000 1.77
+++ camel/camel-store.h 20 Jul 2005 09:30:41 -0000
@@ -109,7 +109,6 @@ typedef struct _CamelRenameInfo {
#define CAMEL_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_STORE_TYPE, CamelStoreClass))
#define CAMEL_IS_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_STORE_TYPE))
-
/* Flags for store flags */
#define CAMEL_STORE_SUBSCRIPTIONS (1 << 0)
#define CAMEL_STORE_VTRASH (1 << 1)
Index: camel/providers/imap/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/providers/imap/ChangeLog,v
retrieving revision 1.14
diff -u -p -r1.14 ChangeLog
--- camel/providers/imap/ChangeLog 21 Mar 2005 18:56:49 -0000 1.14
+++ camel/providers/imap/ChangeLog 20 Jul 2005 09:30:41 -0000
@@ -1,3 +1,75 @@
+2005-07-20 Not Zed <NotZed Ximian com>
+
+ * camel-imap-store.h: re-arrange some bitfields (this is not
+ public api), and add a refresh stamp so we know when to next
+ refresh the list of folders from the server.
+
+ * camel-imap-store.c (imap_build_folder_info): set unknown counts
+ -1, not 0.
+ (get_folder_online): if the folder is on disk, just get it
+ offline, only go to the server if we need to.
+ (fill_fi): dont refresh the folder here, let the client code do
+ it.
+
+ * camel-imap-command.c (imap_command_start): add some asserts,
+ time to fix those 'stream == NULL' warnings properly.
+ (camel_imap_command_continuation): same.
+
+ * camel-imap-store.c (get_folder_counts): remove this, we rely on
+ the client calling folder.refresh_info instead.
+ (get_one_folder_offline): removed, handled more directly from the
+ storesummary now.
+ (refresh_refresh): new async function to update the list of
+ folders (not the folder counts) from the server. We now just use
+ "*" to get all the folders rather than frobbing around with
+ partial fetches.
+ (get_folder_info_online): changed radically, if we are getting
+ subscribed folders, always go to the local list, but update it
+ asynchronously if we need to. if we're not, then always go to the
+ server, but use a simplified listing mechanism.
+ (camel_imap_store_connected): changed to hide some hidden logic,
+ we want not only connected, but online as well; so make it
+ actually do that.
+ (fill_fi): dont do anything slow here, dont honour the 'not fast'
+ flag anymore.
+
+2005-07-19 Not Zed <NotZed Ximian com>
+
+ * camel-imap-folder.c (imap_get_message): dont force a connect
+ until we need it.
+ (camel_imap_folder_fetch_data): force a connect if we need it.
+ (imap_refresh_info): force connect if we need to.
+ (imap_get_message): touch the summary if we changed the body
+ content info record.
+
+ * camel-imap-store.c (camel_imap_store_init): we always support
+ subscriptions, this is a backend property not a store instance
+ property.
+ (imap_connect_online, rename_folder, get_one_folder_offline)
+ (get_folder_info_offline): fix for above.
+ (get_folder_offline): wtf is it connecting for???
+
+2005-07-13 Not Zed <NotZed Ximian com>
+
+ * camel-imap-folder.c (imap_refresh_info): copy over counts to the
+ store summary & save all summaries.
+
+2005-07-12 Not Zed <NotZed Ximian com>
+
+ * camel-imap-store.c (imap_connect_online): only get the folder
+ list if we dont have any yet.
+
+2005-07-11 Not Zed <NotZed Ximian com>
+
+ * camel-imap-store.c (get_folder_info_online): if we are fast,
+ then dont go to the server at all, if we have any folders
+ recorded.
+ (get_folder_counts): never request STATUS on unselected folders.
+ (get_folder_info_offline): build the list directly from the
+ summary, dont scan the filesystem.
+ (parse_list_response_as_folder_info): always initialise counts to
+ unknown (-1).
+
2005-03-18 Jeffrey Stedfast <fejj novell com>
* camel-imap-command.c (imap_read_untagged): Continue reading data
Index: camel/providers/imap/camel-imap-command.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/providers/imap/camel-imap-command.c,v
retrieving revision 1.68
diff -u -p -r1.68 camel-imap-command.c
--- camel/providers/imap/camel-imap-command.c 21 Mar 2005 18:56:49 -0000 1.68
+++ camel/providers/imap/camel-imap-command.c 20 Jul 2005 09:30:41 -0000
@@ -176,6 +176,9 @@ imap_command_start (CamelImapStore *stor
const char *cmd, CamelException *ex)
{
ssize_t nwritten;
+
+ g_assert(store->ostream);
+ g_assert(store->istream);
/* Check for current folder */
if (folder && folder != store->current_folder) {
@@ -250,6 +253,9 @@ camel_imap_command_continuation (CamelIm
{
if (!camel_imap_store_connected (store, ex))
return NULL;
+
+ g_assert(store->ostream);
+ g_assert(store->istream);
if (camel_stream_write (store->ostream, cmd, cmdlen) == -1 ||
camel_stream_write (store->ostream, "\r\n", 2) == -1) {
Index: camel/providers/imap/camel-imap-folder.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/providers/imap/camel-imap-folder.c,v
retrieving revision 1.347
diff -u -p -r1.347 camel-imap-folder.c
--- camel/providers/imap/camel-imap-folder.c 14 Mar 2005 19:13:34 -0000 1.347
+++ camel/providers/imap/camel-imap-folder.c 20 Jul 2005 09:30:42 -0000
@@ -70,6 +70,7 @@
#include "camel-file-utils.h"
#include "camel-debug.h"
#include "camel-i18n.h"
+#include "camel/camel-store-summary.h"
#define d(x)
@@ -496,6 +497,7 @@ imap_refresh_info (CamelFolder *folder,
CamelImapStore *imap_store = CAMEL_IMAP_STORE (folder->parent_store);
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
CamelImapResponse *response;
+ CamelStoreInfo *si;
if (camel_disco_store_status (CAMEL_DISCO_STORE (imap_store)) == CAMEL_DISCO_STORE_OFFLINE)
return;
@@ -511,6 +513,10 @@ imap_refresh_info (CamelFolder *folder,
* us with a NOOP of new messages, so force a reselect which
* should do it. */
CAMEL_SERVICE_LOCK (imap_store, connect_lock);
+
+ if (!camel_imap_store_connected(imap_store, ex))
+ goto done;
+
if (imap_store->current_folder != folder
|| g_ascii_strcasecmp(folder->full_name, "INBOX") == 0) {
response = camel_imap_command (imap_store, folder, ex, NULL);
@@ -537,7 +543,24 @@ imap_refresh_info (CamelFolder *folder,
camel_imap_response_free (imap_store, response);
}
+ si = camel_store_summary_path((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary, folder->full_name);
+ if (si) {
+ guint32 unread, total;
+
+ camel_object_get(folder, NULL, CAMEL_FOLDER_TOTAL, &total, CAMEL_FOLDER_UNREAD, &unread, NULL);
+ if (si->total != total
+ || si->unread != unread){
+ si->total = total;
+ si->unread = unread;
+ camel_store_summary_touch((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary);
+ }
+ camel_store_summary_info_free((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary, si);
+ }
+done:
CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
+
+ camel_folder_summary_save(folder->summary);
+ camel_store_summary_save((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary);
}
/* Called with the store's connect_lock locked */
@@ -751,6 +774,7 @@ static void
imap_sync_offline (CamelFolder *folder, CamelException *ex)
{
camel_folder_summary_save (folder->summary);
+ camel_store_summary_save((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary);
}
static void
@@ -1994,11 +2018,6 @@ imap_get_message (CamelFolder *folder, c
retry++;
camel_exception_clear(ex);
- /* If we are online, make sure we're also connected */
- if (camel_disco_store_status((CamelDiscoStore *)store) == CAMEL_DISCO_STORE_ONLINE
- && !camel_imap_store_connected(store, ex))
- goto fail;
-
/* If the message is small or only 1 part, or server doesn't do 4v1 (properly) fetch it in one piece. */
if (store->server_level < IMAP_LEVEL_IMAP4REV1
|| store->braindamaged
@@ -2017,7 +2036,7 @@ imap_get_message (CamelFolder *folder, c
char *body, *found_uid;
int i;
- if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) {
+ if (!camel_imap_store_connected(store, ex)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("This message is not currently available"));
goto fail;
@@ -2038,9 +2057,11 @@ imap_get_message (CamelFolder *folder, c
}
}
- if (body)
+ if (body) {
imap_parse_body ((const char **) &body, folder, mi->info.content);
-
+ camel_folder_summary_touch (folder->summary);
+ }
+
if (fetch_data)
g_datalist_clear (&fetch_data);
@@ -2600,26 +2621,29 @@ camel_imap_folder_fetch_data (CamelImapF
/* EXPUNGE responses have to modify the cache, which means
* they have to grab the cache_lock while holding the
- * connect_lock. So we grab the connect_lock now, in case
- * we're going to need it below, since we can't grab it
- * after the cache_lock.
+ * connect_lock.
+
+ * Because getting the service lock may cause MUCH unecessary
+ * delay when we already have the data locally, we do the
+ * locking separately. This could cause a race
+ * getting the same data from the cache, but that is only
+ * an inefficiency, and bad luck.
*/
- CAMEL_SERVICE_LOCK (store, connect_lock);
-
CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
stream = camel_imap_message_cache_get (imap_folder->cache, uid, section_text, ex);
if (!stream && (!strcmp (section_text, "HEADER") || !strcmp (section_text, "0"))) {
camel_exception_clear (ex);
stream = camel_imap_message_cache_get (imap_folder->cache, uid, "", ex);
}
+ CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
- if (stream || cache_only) {
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ if (stream || cache_only)
return stream;
- }
-
- if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) {
+
+ CAMEL_SERVICE_LOCK (store, connect_lock);
+ CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
+
+ if (!camel_imap_store_connected(store, ex)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("This message is not currently available"));
CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
Index: camel/providers/imap/camel-imap-store.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/providers/imap/camel-imap-store.c,v
retrieving revision 1.317
diff -u -p -r1.317 camel-imap-store.c
--- camel/providers/imap/camel-imap-store.c 2 Mar 2005 02:56:03 -0000 1.317
+++ camel/providers/imap/camel-imap-store.c 20 Jul 2005 09:30:43 -0000
@@ -207,7 +207,8 @@ camel_imap_store_init (gpointer object,
imap_store->current_folder = NULL;
imap_store->connected = FALSE;
imap_store->preauthed = FALSE;
-
+ ((CamelStore *)imap_store)->flags |= CAMEL_STORE_SUBSCRIPTIONS;
+
imap_store->tag_prefix = imap_tag_prefix++;
if (imap_tag_prefix > 'Z')
imap_tag_prefix = 'A';
@@ -258,7 +259,7 @@ construct (CamelService *service, CamelS
imap_store->parameters = 0;
if (camel_url_get_param (url, "use_lsub"))
- store->flags |= CAMEL_STORE_SUBSCRIPTIONS;
+ imap_store->parameters |= IMAP_PARAM_SUBSCRIPTIONS;
if (camel_url_get_param (url, "namespace")) {
imap_store->parameters |= IMAP_PARAM_OVERRIDE_NAMESPACE;
g_free(imap_store->namespace);
@@ -1004,8 +1005,8 @@ imap_build_folder_info(CamelImapStore *i
fi = g_malloc0(sizeof(*fi));
fi->full_name = g_strdup(folder_name);
- fi->unread = 0;
- fi->total = 0;
+ fi->unread = -1;
+ fi->total = -1;
url = camel_url_new (imap_store->base_url, NULL);
g_free (url->path);
@@ -1469,7 +1470,8 @@ imap_connect_online (CamelService *servi
ns = camel_imap_store_summary_namespace_new(store->summary, store->namespace, store->dir_sep);
camel_imap_store_summary_namespace_set(store->summary, ns);
- if (CAMEL_STORE (store)->flags & CAMEL_STORE_SUBSCRIPTIONS) {
+ if ((store->parameters & IMAP_PARAM_SUBSCRIPTIONS)
+ && camel_store_summary_count((CamelStoreSummary *)store->summary) == 0) {
gboolean haveinbox = FALSE;
GPtrArray *folders;
char *pattern;
@@ -1845,8 +1847,19 @@ get_folder_online (CamelStore *store, co
CamelFolder *new_folder;
char *folder_dir, *storage_path;
- if (!camel_imap_store_connected (imap_store, ex))
+ /* Try to get it locally first, if it is, then the client will
+ force a select when necessary */
+ new_folder = get_folder_offline(store, folder_name, flags, ex);
+ if (new_folder)
+ return new_folder;
+ camel_exception_clear(ex);
+
+ CAMEL_SERVICE_LOCK(imap_store, connect_lock);
+
+ if (!camel_imap_store_connected(imap_store, ex)) {
+ CAMEL_SERVICE_UNLOCK(imap_store, connect_lock);
return NULL;
+ }
if (!g_ascii_strcasecmp (folder_name, "INBOX"))
folder_name = "INBOX";
@@ -2048,11 +2061,7 @@ get_folder_offline (CamelStore *store, c
CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
CamelFolder *new_folder;
char *folder_dir, *storage_path;
-
- if (!imap_store->connected &&
- !camel_service_connect (CAMEL_SERVICE (store), ex))
- return NULL;
-
+
if (!g_ascii_strcasecmp (folder_name, "INBOX"))
folder_name = "INBOX";
@@ -2204,14 +2213,14 @@ rename_folder (CamelStore *store, const
imap_store->renaming = TRUE;
- if (store->flags & CAMEL_STORE_SUBSCRIPTIONS)
+ if (imap_store->parameters & IMAP_PARAM_SUBSCRIPTIONS)
manage_subscriptions(store, old_name, FALSE);
new_name = camel_imap_store_summary_path_to_full(imap_store->summary, new_name_in, imap_store->dir_sep);
response = camel_imap_command (imap_store, NULL, ex, "RENAME %F %S", old_name, new_name);
if (!response) {
- if (store->flags & CAMEL_STORE_SUBSCRIPTIONS)
+ if (imap_store->parameters & IMAP_PARAM_SUBSCRIPTIONS)
manage_subscriptions(store, old_name, TRUE);
g_free(new_name);
imap_store->renaming = FALSE;
@@ -2223,7 +2232,7 @@ rename_folder (CamelStore *store, const
/* rename summary, and handle broken server */
rename_folder_info(imap_store, old_name, new_name_in);
- if (store->flags & CAMEL_STORE_SUBSCRIPTIONS)
+ if (imap_store->parameters & IMAP_PARAM_SUBSCRIPTIONS)
manage_subscriptions(store, new_name_in, TRUE);
storage_path = g_strdup_printf("%s/folders", imap_store->storage_path);
@@ -2447,9 +2456,8 @@ parse_list_response_as_folder_info (Came
fi->uri = camel_url_to_string (url, 0);
camel_url_free (url);
- /* FIXME: redundant */
- if (flags & CAMEL_IMAP_FOLDER_UNMARKED)
- fi->unread = -1;
+ fi->total = -1;
+ fi->unread = -1;
return fi;
}
@@ -2565,6 +2573,31 @@ static int imap_match_pattern(char dir_s
return n == 0 && (p == '%' || p == 0);
}
+/* imap needs to treat inbox case insensitive */
+/* we'll assume the names are normalised already */
+static guint folder_hash(const void *ap)
+{
+ const char *a = ap;
+
+ if (g_ascii_strcasecmp(a, "INBOX") == 0)
+ a = "INBOX";
+
+ return g_str_hash(a);
+}
+
+static int folder_eq(const void *ap, const void *bp)
+{
+ const char *a = ap;
+ const char *b = bp;
+
+ if (g_ascii_strcasecmp(a, "INBOX") == 0)
+ a = "INBOX";
+ if (g_ascii_strcasecmp(b, "INBOX") == 0)
+ b = "INBOX";
+
+ return g_str_equal(a, b);
+}
+
static void
get_folders_online (CamelImapStore *imap_store, const char *pattern,
GPtrArray *folders, gboolean lsub, CamelException *ex)
@@ -2582,17 +2615,21 @@ get_folders_online (CamelImapStore *imap
if (!response)
return;
- present = g_hash_table_new(g_str_hash, g_str_equal);
+ present = g_hash_table_new(folder_hash, folder_eq);
for (i = 0; i < response->untagged->len; i++) {
list = response->untagged->pdata[i];
fi = parse_list_response_as_folder_info (imap_store, list);
if (fi) {
+ if (lsub && (fi->flags & (CAMEL_IMAP_FOLDER_MARKED | CAMEL_IMAP_FOLDER_UNMARKED)))
+ imap_store->capabilities |= IMAP_CAPABILITY_useful_lsub;
g_ptr_array_add(folders, fi);
g_hash_table_insert(present, fi->full_name, fi);
}
}
camel_imap_response_free (imap_store, response);
+ /* FIXME: we need to emit folder_create/subscribed/etc events for any new folders */
+
/* update our summary to match the server */
count = camel_store_summary_count((CamelStoreSummary *)imap_store->summary);
for (i=0;i<count;i++) {
@@ -2655,136 +2692,16 @@ fill_fi(CamelStore *store, CamelFolderIn
{
CamelFolder *folder;
- fi->unread = -1;
- fi->total = -1;
folder = camel_object_bag_peek(store->folders, fi->full_name);
if (folder) {
- if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0)
- /* we use connect lock for everything, so this should be safe */
- CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->refresh_info(folder, NULL);
fi->unread = camel_folder_get_unread_message_count(folder);
fi->total = camel_folder_get_message_count(folder);
camel_object_unref(folder);
- } else {
- char *storage_path, *folder_dir, *path;
- CamelFolderSummary *s;
-
- /* This is a lot of work for one path! */
- storage_path = g_strdup_printf("%s/folders", ((CamelImapStore *)store)->storage_path);
- folder_dir = imap_path_to_physical(storage_path, fi->full_name);
- path = g_strdup_printf("%s/summary", folder_dir);
- s = (CamelFolderSummary *)camel_object_new(camel_imap_summary_get_type());
- camel_folder_summary_set_build_content(s, TRUE);
- camel_folder_summary_set_filename(s, path);
- if (camel_folder_summary_header_load(s) != -1) {
- fi->unread = s->unread_count;
- fi->total = s->saved_count;
- }
- g_free(storage_path);
- g_free(folder_dir);
- g_free(path);
-
- camel_object_unref(s);
- }
-}
-
-/* NB: We should have connect_lock at this point */
-static void
-get_folder_counts(CamelImapStore *imap_store, CamelFolderInfo *fi, CamelException *ex)
-{
- GSList *q;
- CamelFolder *folder;
-
- /* non-recursive breath first search */
-
- q = g_slist_append(NULL, fi);
-
- while (q) {
- fi = q->data;
- q = g_slist_remove_link(q, q);
-
- while (fi) {
- /* ignore noselect folders, and check only inbox if we only check inbox */
- if ((fi->flags & CAMEL_FOLDER_NOSELECT) == 0
- && ( (imap_store->parameters & IMAP_PARAM_CHECK_ALL)
- || g_ascii_strcasecmp(fi->full_name, "inbox") == 0) ) {
-
- /* For the current folder, poke it to check for new
- * messages and then report that number, rather than
- * doing a STATUS command.
- */
- if (imap_store->current_folder && strcmp(imap_store->current_folder->full_name, fi->full_name) == 0) {
- /* we bypass the folder locking otherwise we can deadlock. we use the command lock for
- any operations anyway so this is 'safe'. See comment above imap_store_refresh_folders() for info */
- CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(imap_store->current_folder))->refresh_info(imap_store->current_folder, ex);
- fi->unread = camel_folder_get_unread_message_count (imap_store->current_folder);
- fi->total = camel_folder_get_message_count(imap_store->current_folder);
- } else {
- struct imap_status_item *items, *item;
-
- fi->unread = -1;
- fi->total = -1;
-
- item = items = get_folder_status (imap_store, fi->full_name, "MESSAGES UNSEEN");
- while (item != NULL) {
- if (!g_ascii_strcasecmp (item->name, "MESSAGES")) {
- fi->total = item->value;
- } else if (!g_ascii_strcasecmp (item->name, "UNSEEN")) {
- fi->unread = item->value;
- }
-
- item = item->next;
- }
-
- imap_status_item_free (items);
-
- /* if we have this folder open, and the unread count has changed, update */
- folder = camel_object_bag_peek(CAMEL_STORE(imap_store)->folders, fi->full_name);
- if (folder) {
- if (fi->unread != camel_folder_get_unread_message_count(folder)) {
- CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->refresh_info(folder, ex);
- fi->unread = camel_folder_get_unread_message_count(folder);
- fi->total = camel_folder_get_message_count(folder);
- }
- camel_object_unref(folder);
- }
- }
- } else {
- /* since its cheap, get it if they're open/consult summary file */
- fill_fi((CamelStore *)imap_store, fi, 0);
- }
-
- if (fi->child)
- q = g_slist_append(q, fi->child);
- fi = fi->next;
- }
}
}
-/* imap needs to treat inbox case insensitive */
-/* we'll assume the names are normalised already */
-static guint folder_hash(const void *ap)
-{
- const char *a = ap;
-
- if (g_ascii_strcasecmp(a, "INBOX") == 0)
- a = "INBOX";
-
- return g_str_hash(a);
-}
-
-static int folder_eq(const void *ap, const void *bp)
-{
- const char *a = ap;
- const char *b = bp;
-
- if (g_ascii_strcasecmp(a, "INBOX") == 0)
- a = "INBOX";
- if (g_ascii_strcasecmp(b, "INBOX") == 0)
- b = "INBOX";
-
- return g_str_equal(a, b);
-}
+#if 0
+/* TBD eventually ... */
static GSList *
get_folders_add_folders(GSList *p, int recurse, GHashTable *infos, GPtrArray *folders, GPtrArray *folders_out)
@@ -2961,6 +2878,71 @@ fail:
return NULL;
}
+#endif
+
+struct _refresh_msg {
+ CamelSessionThreadMsg msg;
+
+ CamelStore *store;
+ CamelException ex;
+};
+
+static void
+free_folders(GPtrArray *folders)
+{
+ int i;
+
+ for (i=0;i<folders->len;i++) {
+ CamelFolderInfo *fi = folders->pdata[i];
+
+ camel_folder_info_free(fi);
+ }
+ g_ptr_array_free(folders, TRUE);
+}
+
+static void
+refresh_refresh(CamelSession *session, CamelSessionThreadMsg *msg)
+{
+ struct _refresh_msg *m = (struct _refresh_msg *)msg;
+ GPtrArray *folders;
+
+ /* First we get a lsub of all the folders from the server, so we know which
+ folders we have. If the lsub information is incomplete, then we re-get the
+ list using list to get the flags. */
+
+ CAMEL_SERVICE_LOCK(m->store, connect_lock);
+
+ if (!camel_imap_store_connected((CamelImapStore *)m->store, &m->ex))
+ goto done;
+
+ folders = g_ptr_array_new();
+ get_folders_online((CamelImapStore *)m->store, "*", folders, TRUE, &m->ex);
+ free_folders(folders);
+
+ if (!(((CamelImapStore *)m->store)->capabilities & IMAP_CAPABILITY_useful_lsub)) {
+ folders = get_subscribed_folders((CamelImapStore *)m->store, "", &m->ex);
+ if (folders)
+ free_folders(folders);
+ }
+
+ camel_store_summary_save((CamelStoreSummary *)((CamelImapStore *)m->store)->summary);
+done:
+ CAMEL_SERVICE_UNLOCK(m->store, connect_lock);
+}
+
+static void
+refresh_free(CamelSession *session, CamelSessionThreadMsg *msg)
+{
+ struct _refresh_msg *m = (struct _refresh_msg *)msg;
+
+ camel_object_unref(m->store);
+ camel_exception_clear(&m->ex);
+}
+
+static CamelSessionThreadOps refresh_ops = {
+ refresh_refresh,
+ refresh_free,
+};
static CamelFolderInfo *
get_folder_info_online (CamelStore *store, const char *top, guint32 flags, CamelException *ex)
@@ -2968,49 +2950,129 @@ get_folder_info_online (CamelStore *stor
CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
CamelFolderInfo *tree = NULL;
GPtrArray *folders;
-
+
+ /* If we have a list of folders already, use that, but if we haven't
+ updated for a while, then trigger an asynchronous rescan. Otherwise
+ we have to do it the slow hard way. */
+
if (top == NULL)
top = "";
+ CAMEL_SERVICE_LOCK(store, connect_lock);
+
if (camel_debug("imap:folder_info"))
printf("get folder info online\n");
- CAMEL_SERVICE_LOCK(store, connect_lock);
-
if ((flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED)
- && !(imap_store->capabilities & IMAP_CAPABILITY_useful_lsub)
- && (imap_store->parameters & IMAP_PARAM_CHECK_ALL))
- folders = get_subscribed_folders(imap_store, top, ex);
- else
- folders = get_folders(store, top, flags, ex);
+ && camel_store_summary_count((CamelStoreSummary *)imap_store->summary) > 0) {
+ time_t now;
+ int ref;
+
+ now = time(0);
+ ref = now > imap_store->refresh_stamp+60*60*1;
+ if (ref)
+ imap_store->refresh_stamp = now;
+
+ tree = get_folder_info_offline(store, top, flags, ex);
+
+ if (ref) {
+ struct _refresh_msg *m;
+
+ m = camel_session_thread_msg_new(((CamelService *)store)->session, &refresh_ops, sizeof(*m));
+ m->store = store;
+ camel_object_ref(store);
+ camel_exception_init(&m->ex);
+ camel_session_thread_queue(((CamelService *)store)->session, &m->msg, 0);
+ }
+ } else {
+ char *pattern;
+ int i;
- if (folders == NULL)
- goto done;
+ if (!camel_imap_store_connected((CamelImapStore *)store, ex))
+ goto done;
- tree = camel_folder_info_build(folders, top, '/', TRUE);
- g_ptr_array_free(folders, TRUE);
+ if (top[0] == 0) {
+ if (imap_store->namespace && imap_store->namespace[0]) {
+ i = strlen(imap_store->namespace)-1;
+ pattern = g_alloca(i+5);
+ strcpy(pattern, imap_store->namespace);
+ while (i>0 && pattern[i] == imap_store->dir_sep)
+ pattern[i--] = 0;
+ i++;
+ } else {
+ pattern = g_alloca(2);
+ pattern[0] = '*';
+ pattern[1] = 0;
+ i=0;
+ }
+ } else {
+ char *name;
- if (!(flags & CAMEL_STORE_FOLDER_INFO_FAST))
- get_folder_counts(imap_store, tree, ex);
+ name = camel_imap_store_summary_full_from_path(imap_store->summary, top);
+ if (name == NULL)
+ name = camel_imap_store_summary_path_to_full(imap_store->summary, top, imap_store->dir_sep);
- d(dumpfi(tree));
- camel_store_summary_save((CamelStoreSummary *)imap_store->summary);
+ i = strlen(name);
+ pattern = g_alloca(i+5);
+ strcpy(pattern, name);
+ g_free(name);
+ }
+
+ folders = g_ptr_array_new();
+ get_folders_online(imap_store, pattern, folders, flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, ex);
+ if (pattern[0] != '*' && imap_store->dir_sep) {
+ pattern[i] = imap_store->dir_sep;
+ pattern[i+1] = (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE)?'*':'%';
+ pattern[i+2] = 0;
+ get_folders_online(imap_store, pattern, folders, flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, ex);
+ }
+
+ tree = camel_folder_info_build(folders, top, '/', TRUE);
+ g_ptr_array_free(folders, TRUE);
+
+ camel_store_summary_save((CamelStoreSummary *)imap_store->summary);
+ }
done:
CAMEL_SERVICE_UNLOCK(store, connect_lock);
return tree;
}
-static gboolean
-get_one_folder_offline (const char *physical_path, const char *path, gpointer data)
+static CamelFolderInfo *
+get_folder_info_offline (CamelStore *store, const char *top,
+ guint32 flags, CamelException *ex)
{
- GPtrArray *folders = data;
- CamelImapStore *imap_store = folders->pdata[0];
+ CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
CamelFolderInfo *fi;
- CamelStoreInfo *si;
+ GPtrArray *folders;
+ char *pattern, *name;
+ int i;
- if (*path != '/')
- return TRUE;
+ if (camel_debug("imap:folder_info"))
+ printf("get folder info offline\n");
+
+ /* FIXME: obey other flags */
+
+ folders = g_ptr_array_new ();
+
+ /* get starting point & strip trailing '/' */
+ if (top == NULL || top[0] == 0) {
+ if (imap_store->namespace) {
+ top = imap_store->namespace;
+ i = strlen(top)-1;
+ name = g_malloc(i+2);
+ strcpy(name, top);
+ while (i>0 && name[i] == imap_store->dir_sep)
+ name[i--] = 0;
+ } else
+ name = g_strdup("");
+ } else {
+ name = camel_imap_store_summary_full_from_path(imap_store->summary, top);
+ if (name == NULL)
+ name = camel_imap_store_summary_path_to_full(imap_store->summary, top, imap_store->dir_sep);
+ }
+
+ pattern = imap_concat(imap_store, name, "*");
/* folder_info_build will insert parent nodes as necessary and mark
* them as noselect, which is information we actually don't have at
@@ -3018,11 +3080,20 @@ get_one_folder_offline (const char *phys
* not a folder we're explicitly interested in.
*/
- si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, path+1);
- if (si) {
- if ((((CamelStore *)imap_store)->flags & CAMEL_STORE_SUBSCRIPTIONS) == 0
- || (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)) {
- fi = imap_build_folder_info(imap_store, path+1);
+ for (i=0;i<camel_store_summary_count((CamelStoreSummary *)imap_store->summary);i++) {
+ CamelStoreInfo *si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i);
+
+ if (si == NULL)
+ continue;
+
+ if ((!strcmp(name, camel_imap_store_info_full_name(imap_store->summary, si))
+ || imap_match_pattern(imap_store->dir_sep, pattern, camel_imap_store_info_full_name(imap_store->summary, si)))
+ && ((imap_store->parameters & IMAP_PARAM_SUBSCRIPTIONS) == 0
+ || (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) == 0
+ || (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED))) {
+ fi = imap_build_folder_info(imap_store, camel_store_info_path((CamelStoreSummary *)imap_store->summary, si));
+ fi->unread = si->unread;
+ fi->total = si->total;
fi->flags = si->flags;
/* HACK: some servers report noinferiors for all folders (uw-imapd)
We just translate this into nochildren, and let the imap layer enforce
@@ -3044,49 +3115,12 @@ get_one_folder_offline (const char *phys
}
camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si);
}
+ g_free(pattern);
+ g_free(name);
- return TRUE;
-}
-
-static CamelFolderInfo *
-get_folder_info_offline (CamelStore *store, const char *top,
- guint32 flags, CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- CamelFolderInfo *fi;
- GPtrArray *folders;
- char *storage_path;
-
- if (camel_debug("imap:folder_info"))
- printf("get folder info offline\n");
-
- if (!imap_store->connected &&
- !camel_service_connect (CAMEL_SERVICE (store), ex))
- return NULL;
-
- if ((store->flags & CAMEL_STORE_SUBSCRIPTIONS) &&
- !(flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED)) {
- camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex);
- return NULL;
- }
-
- /* FIXME: obey other flags */
-
- folders = g_ptr_array_new ();
-
- /* A kludge to avoid having to pass a struct to the callback */
- g_ptr_array_add (folders, imap_store);
- storage_path = g_strdup_printf("%s/folders", imap_store->storage_path);
- if (!imap_path_find_folders (storage_path, get_one_folder_offline, folders)) {
- camel_disco_store_check_online (CAMEL_DISCO_STORE (imap_store), ex);
- fi = NULL;
- } else {
- g_ptr_array_remove_index_fast (folders, 0);
- fi = camel_folder_info_build (folders, "", '/', TRUE);
- }
- g_free(storage_path);
-
+ fi = camel_folder_info_build (folders, "", '/', TRUE);
g_ptr_array_free (folders, TRUE);
+
return fi;
}
@@ -3193,13 +3227,28 @@ folder_flags_have_changed (CamelFolder *
}
#endif
-
+/* Use this whenever you need to ensure you're both connected and
+ online. */
gboolean
camel_imap_store_connected (CamelImapStore *store, CamelException *ex)
{
- if (store->istream == NULL || !store->connected)
- return camel_service_connect (CAMEL_SERVICE (store), ex);
- return TRUE;
+ /* This looks stupid ... because it is.
+
+ camel-service-connect will return OK if we connect in 'offline mode',
+ which isn't what we want at all. So we have to recheck we actually
+ did connect anyway ... */
+
+ if (store->istream != NULL
+ || (camel_disco_store_check_online((CamelDiscoStore *)store, ex)
+ && camel_service_connect((CamelService *)store, ex)
+ && store->istream != NULL))
+ return TRUE;
+
+ if (!camel_exception_is_set(ex))
+ camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+ _("You must be working online to complete this operation"));
+
+ return FALSE;
}
Index: camel/providers/imap/camel-imap-store.h
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/providers/imap/camel-imap-store.h,v
retrieving revision 1.62
diff -u -p -r1.62 camel-imap-store.h
--- camel/providers/imap/camel-imap-store.h 4 Feb 2005 03:09:23 -0000 1.62
+++ camel/providers/imap/camel-imap-store.h 20 Jul 2005 09:30:43 -0000
@@ -33,6 +33,7 @@ extern "C" {
#include "camel-imap-types.h"
#include <camel/camel-disco-store.h>
+#include <sys/time.h>
#ifdef ENABLE_THREADS
#include <libedataserver/e-msgport.h>
@@ -102,6 +103,7 @@ typedef enum {
#define IMAP_PARAM_FILTER_INBOX (1 << 2)
#define IMAP_PARAM_FILTER_JUNK (1 << 3)
#define IMAP_PARAM_FILTER_JUNK_INBOX (1 << 4)
+#define IMAP_PARAM_SUBSCRIPTIONS (1 << 5)
struct _CamelImapStore {
CamelDiscoStore parent_object;
@@ -114,6 +116,10 @@ struct _CamelImapStore {
/* Information about the command channel / connection status */
guint connected:1;
guint preauthed:1;
+
+ guint braindamaged:1;
+ guint renaming:1;
+
char tag_prefix;
guint32 command;
CamelFolder *current_folder;
@@ -121,14 +127,12 @@ struct _CamelImapStore {
/* Information about the server */
CamelImapServerLevel server_level;
guint32 capabilities, parameters;
- guint braindamaged:1;
/* NB: namespace should be handled by summary->namespace */
char *namespace, dir_sep, *base_url, *storage_path;
GHashTable *authtypes;
- guint renaming:1;
+ time_t refresh_stamp;
};
-
typedef struct {
CamelDiscoStoreClass parent_class;
Index: mail/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/mail/ChangeLog,v
retrieving revision 1.3655
diff -u -p -r1.3655 ChangeLog
--- mail/ChangeLog 13 Jul 2005 10:38:06 -0000 1.3655
+++ mail/ChangeLog 20 Jul 2005 09:33:11 -0000
@@ -1,3 +1,56 @@
+2005-07-20 Not Zed <NotZed Ximian com>
+
+ * mail-send-recv.c (refresh_folders_desc, refresh_folders_get)
+ (refresh_folders_got, refresh_folders_free, get_folders)
+ (receive_update_got_folderinfo, receive_update_got_store): refresh
+ all the folders manually and directly.
+
+ * mail-folder-cache.c (setup_folder): propagate even -1 unread
+ counts, they get ignored later.
+
+ * em-composer-utils.c (emu_handle_receipt_message)
+ (em_utils_handle_receipt): use getmessagex too, so we can always
+ clear any error.
+
+ * em-folder-view.c (emfv_message_selected_timeout)
+ (emfv_list_done_message_selected): use getmessagex and do
+ something meaninful with the error.
+
+ * mail-ops.c (mail_get_messagex): added new get message which
+ returns an exception.
+
+2005-07-19 Not Zed <NotZed Ximian com>
+
+ * mail-tools.c (mail_tool_uri_to_folder): dont get the service
+ connected, it will connect if it needs to.
+
+ * mail-ops.c (get_folderinfo_get): * em-folder-utils.c
+ (emft_copy_folders__copy)
+ (emfu_delete_folders): * em-folder-tree.c
+ (emft_get_folder_info__get): Always request subscribed folders, if
+ the backend doesn't implement it it will ignore it.
+
+2005-07-13 Not Zed <NotZed Ximian com>
+
+ * mail-send-recv.c (mail_autoreceive_init, auto_online): listen to
+ session online events, and if we are online, trigger an
+ auto-receive of all auto-check accounts.
+
+2005-07-11 Not Zed <NotZed Ximian com>
+
+ * mail-send-recv.c (auto_account_commit): force an update
+ immediately if we're setting up the timeout to start with.
+
+ * em-folder-tree-model.c (em_folder_tree_model_set_unread_count):
+ noop if the unread count < 0.
+ (em_folder_tree_model_set_folder_info): only set the unread count
+ if we actually have one.
+
+ * em-folder-tree.c (emft_tree_row_expanded): get the folder list
+ 'fast'.
+
+ * mail-ops.c (get_folderinfo_get): get the folder list 'fast'.
+
2005-07-13 Kjartan Maraas <kmaraas gnome org>
* em-mailer-prefs.c: (em_mailer_prefs_construct): Free font name
Index: mail/em-composer-utils.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-composer-utils.c,v
retrieving revision 1.39
diff -u -p -r1.39 em-composer-utils.c
--- mail/em-composer-utils.c 17 Jun 2005 15:20:29 -0000 1.39
+++ mail/em-composer-utils.c 20 Jul 2005 09:33:11 -0000
@@ -1070,10 +1070,13 @@ em_utils_redirect_message_by_uid (CamelF
}
static void
-emu_handle_receipt_message(CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *data)
+emu_handle_receipt_message(CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *data, CamelException *ex)
{
if (msg)
em_utils_handle_receipt(folder, uid, msg);
+
+ /* we dont care really if we can't get the message */
+ camel_exception_clear(ex);
}
/* Message disposition notifications, rfc 2298 */
@@ -1094,7 +1097,7 @@ em_utils_handle_receipt (CamelFolder *fo
}
if (msg == NULL) {
- mail_get_message(folder, uid, emu_handle_receipt_message, NULL, mail_thread_new);
+ mail_get_messagex(folder, uid, emu_handle_receipt_message, NULL, mail_thread_new);
camel_message_info_free(info);
return;
}
Index: mail/em-folder-tree-model.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-folder-tree-model.c,v
retrieving revision 1.67
diff -u -p -r1.67 em-folder-tree-model.c
--- mail/em-folder-tree-model.c 17 Jun 2005 15:20:29 -0000 1.67
+++ mail/em-folder-tree-model.c 20 Jul 2005 09:33:11 -0000
@@ -443,7 +443,7 @@ em_folder_tree_model_set_folder_info (EM
/* HACK: if we have the folder, and its the outbox folder, we need the total count, not unread */
/* This is duplicated in mail-folder-cache too, should perhaps be functionised */
- unread = fi->unread == -1 ? 0 : fi->unread;
+ unread = fi->unread;
if (mail_note_get_folder_from_uri(fi->uri, &folder) && folder) {
if (folder == mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX)) {
int total;
@@ -482,11 +482,13 @@ em_folder_tree_model_set_folder_info (EM
COL_POINTER_CAMEL_STORE, si->store,
COL_STRING_FULL_NAME, fi->full_name,
COL_STRING_URI, fi->uri,
- COL_UINT_UNREAD, unread,
COL_UINT_FLAGS, flags,
COL_BOOL_IS_STORE, FALSE,
COL_BOOL_LOAD_SUBDIRS, load,
-1);
+
+ if (unread != ~0)
+ gtk_tree_store_set ((GtkTreeStore *) model, iter, COL_UINT_UNREAD, unread, -1);
if (load) {
/* create a placeholder node for our subfolders... */
@@ -1103,7 +1105,7 @@ em_folder_tree_model_set_unread_count (E
u(printf("set unread count %p '%s' %d\n", store, full, unread));
if (unread < 0)
- unread = 0;
+ return;
if (!(si = g_hash_table_lookup (model->store_hash, store))) {
u(printf(" can't find store\n"));
Index: mail/em-folder-tree.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-folder-tree.c,v
retrieving revision 1.150
diff -u -p -r1.150 em-folder-tree.c
--- mail/em-folder-tree.c 19 May 2005 06:06:35 -0000 1.150
+++ mail/em-folder-tree.c 20 Jul 2005 09:33:12 -0000
@@ -1757,10 +1757,7 @@ static void
emft_get_folder_info__get (struct _mail_msg *mm)
{
struct _EMFolderTreeGetFolderInfo *m = (struct _EMFolderTreeGetFolderInfo *) mm;
- guint32 flags = m->flags;
-
- if (camel_store_supports_subscriptions (m->store))
- flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
+ guint32 flags = m->flags | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
m->fi = camel_store_get_folder_info (m->store, m->top, flags, &mm->ex);
}
@@ -1937,7 +1934,7 @@ emft_tree_row_expanded (GtkTreeView *tre
m->emft = emft;
g_object_ref(emft);
m->top = full_name;
- m->flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
+ m->flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST;
e_thread_put (mail_thread_new, (EMsg *) m);
}
Index: mail/em-folder-utils.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-folder-utils.c,v
retrieving revision 1.3
diff -u -p -r1.3 em-folder-utils.c
--- mail/em-folder-utils.c 19 May 2005 06:06:35 -0000 1.3
+++ mail/em-folder-utils.c 20 Jul 2005 09:33:12 -0000
@@ -108,16 +108,13 @@ static void
emft_copy_folders__copy (struct _mail_msg *mm)
{
struct _EMCopyFolders *m = (struct _EMCopyFolders *) mm;
- guint32 flags = CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_RECURSIVE;
+ guint32 flags = CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
GList *pending = NULL, *deleting = NULL, *l;
GString *fromname, *toname;
CamelFolderInfo *fi;
const char *tmp;
int fromlen;
- if (camel_store_supports_subscriptions (m->fromstore))
- flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
-
if (!(fi = camel_store_get_folder_info (m->fromstore, m->frombase, flags, &mm->ex)))
return;
@@ -431,11 +428,8 @@ emfu_delete_rec (CamelStore *store, Came
static void
emfu_delete_folders (CamelStore *store, const char *full_name, CamelException *ex)
{
- guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_FAST;
+ guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
CamelFolderInfo *fi;
-
- if (camel_store_supports_subscriptions (store))
- flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
fi = camel_store_get_folder_info (store, full_name, flags, ex);
if (camel_exception_is_set (ex))
Index: mail/em-folder-view.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-folder-view.c,v
retrieving revision 1.126
diff -u -p -r1.126 em-folder-view.c
--- mail/em-folder-view.c 23 Jun 2005 09:11:06 -0000 1.126
+++ mail/em-folder-view.c 20 Jul 2005 09:33:13 -0000
@@ -87,6 +87,7 @@
#include "em-event.h"
#include <gtkhtml/gtkhtml.h>
+#include <gtkhtml/gtkhtml-stream.h>
#include "mail-mt.h"
#include "mail-ops.h"
@@ -2166,7 +2167,7 @@ do_mark_seen (gpointer user_data)
}
static void
-emfv_list_done_message_selected(CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *data)
+emfv_list_done_message_selected(CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *data, CamelException *ex)
{
EMFolderView *emfv = data;
EMEvent *eme;
@@ -2211,6 +2212,17 @@ emfv_list_done_message_selected(CamelFol
} else {
emfv_set_seen (emfv, uid);
}
+ } else if (camel_exception_is_set(ex)) {
+ GtkHTMLStream *hstream = gtk_html_begin(((EMFormatHTML *)emfv->preview)->html);
+
+ /* Display the error inline rather than popping up an annoying box.
+ We also clear the exception, this stops the box popping up */
+
+ gtk_html_stream_printf(hstream, "<h2>%s</h2><p>%s</p>",
+ _("Unable to retrieve message"),
+ ex->desc);
+ gtk_html_stream_close(hstream, GTK_HTML_STREAM_OK);
+ camel_exception_clear(ex);
}
emfv->priv->nomarkseen = FALSE;
@@ -2231,7 +2243,7 @@ emfv_message_selected_timeout(void *data
g_object_ref (emfv);
/* TODO: we should manage our own thread stuff, would make cancelling outstanding stuff easier */
e_profile_event_emit("goto.load", emfv->displayed_uid, 0);
- mail_get_message(emfv->folder, emfv->displayed_uid, emfv_list_done_message_selected, emfv, mail_thread_queued);
+ mail_get_messagex(emfv->folder, emfv->displayed_uid, emfv_list_done_message_selected, emfv, mail_thread_queued);
} else {
e_profile_event_emit("goto.empty", "", 0);
g_free(emfv->priv->selected_uid);
Index: mail/mail-folder-cache.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-folder-cache.c,v
retrieving revision 1.99
diff -u -p -r1.99 mail-folder-cache.c
--- mail/mail-folder-cache.c 6 Jan 2005 22:12:57 -0000 1.99
+++ mail/mail-folder-cache.c 20 Jul 2005 09:33:14 -0000
@@ -390,7 +390,7 @@ setup_folder(CamelFolderInfo *fi, struct
if (mfi) {
update_1folder(mfi, 0, fi);
} else {
- /*d(printf("Adding new folder: %s (%s) %d unread\n", fi->path, fi->url, fi->unread_message_count));*/
+ d(printf("Adding new folder: %s (%s) %d unread\n", fi->path, fi->url, fi->unread_message_count));
mfi = g_malloc0(sizeof(*mfi));
mfi->full_name = g_strdup(fi->full_name);
mfi->uri = g_strdup(fi->uri);
@@ -403,7 +403,7 @@ setup_folder(CamelFolderInfo *fi, struct
up = g_malloc0(sizeof(*up));
up->full_name = g_strdup(mfi->full_name);
up->uri = g_strdup(fi->uri);
- up->unread = (fi->unread==-1)?0:fi->unread;
+ up->unread = fi->unread;
up->store = si->store;
camel_object_ref(up->store);
Index: mail/mail-ops.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-ops.c,v
retrieving revision 1.447
diff -u -p -r1.447 mail-ops.c
--- mail/mail-ops.c 17 Jun 2005 15:20:29 -0000 1.447
+++ mail/mail-ops.c 20 Jul 2005 09:33:14 -0000
@@ -1061,10 +1061,7 @@ static void
get_folderinfo_get (struct _mail_msg *mm)
{
struct _get_folderinfo_msg *m = (struct _get_folderinfo_msg *)mm;
- guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
-
- if (camel_store_supports_subscriptions (m->store))
- flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
+ guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
m->info = camel_store_get_folder_info (m->store, NULL, flags, &mm->ex);
}
@@ -1786,6 +1783,44 @@ mail_get_message(CamelFolder *folder, co
struct _get_message_msg *m;
m = mail_msg_new(&get_message_op, NULL, sizeof(*m));
+ m->folder = folder;
+ camel_object_ref(folder);
+ m->uid = g_strdup(uid);
+ m->data = data;
+ m->done = done;
+ m->cancel = camel_operation_new(NULL, NULL);
+
+ e_thread_put(thread, (EMsg *)m);
+}
+
+typedef void (*get_done)(CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *data, CamelException *);
+
+static void get_messagex_got(struct _mail_msg *mm)
+{
+ struct _get_message_msg *m = (struct _get_message_msg *)mm;
+
+ if (m->done) {
+ get_done done = (get_done)m->done;
+ done(m->folder, m->uid, m->message, m->data, &mm->ex);
+ }
+}
+
+static struct _mail_msg_op get_messagex_op = {
+ get_message_desc,
+ get_message_get,
+ get_messagex_got,
+ get_message_free,
+};
+
+/* This is temporary, to avoid having to rewrite everything that uses
+ mail_get_message; it adds an exception argument to the callback */
+void
+mail_get_messagex(CamelFolder *folder, const char *uid, void (*done) (CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *data, CamelException *),
+ void *data, EThread *thread)
+{
+ struct _get_message_msg *m;
+
+ m = mail_msg_new(&get_messagex_op, NULL, sizeof(*m));
m->folder = folder;
camel_object_ref(folder);
m->uid = g_strdup(uid);
Index: mail/mail-ops.h
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-ops.h,v
retrieving revision 1.71
diff -u -p -r1.71 mail-ops.h
--- mail/mail-ops.h 3 Dec 2004 03:38:03 -0000 1.71
+++ mail/mail-ops.h 20 Jul 2005 09:33:14 -0000
@@ -57,6 +57,11 @@ void mail_get_message (CamelFolder *fold
void *data,
EThread *thread);
+void
+mail_get_messagex(CamelFolder *folder, const char *uid,
+ void (*done) (CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *data, CamelException *),
+ void *data, EThread *thread);
+
/* get several messages */
void mail_get_messages (CamelFolder *folder, GPtrArray *uids,
void (*done) (CamelFolder *folder, GPtrArray *uids, GPtrArray *msgs, void *data),
Index: mail/mail-send-recv.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-send-recv.c,v
retrieving revision 1.98
diff -u -p -r1.98 mail-send-recv.c
--- mail/mail-send-recv.c 23 Jun 2005 09:11:06 -0000 1.98
+++ mail/mail-send-recv.c 20 Jul 2005 09:33:15 -0000
@@ -683,10 +683,97 @@ receive_get_folder(CamelFilterDriver *d,
return folder;
}
+/* ********************************************************************** */
+
+struct _refresh_folders_msg {
+ struct _mail_msg msg;
+
+ struct _send_info *info;
+ GPtrArray *folders;
+ CamelStore *store;
+};
+
+static char *
+refresh_folders_desc (struct _mail_msg *mm, int done)
+{
+ return g_strdup_printf(_("Checking for new mail"));
+}
+
+static void
+refresh_folders_get (struct _mail_msg *mm)
+{
+ struct _refresh_folders_msg *m = (struct _refresh_folders_msg *)mm;
+ int i;
+ CamelFolder *folder;
+
+ for (i=0;i<m->folders->len;i++) {
+ folder = mail_tool_uri_to_folder(m->folders->pdata[i], 0, NULL);
+ if (folder) {
+ camel_folder_refresh_info(folder, NULL);
+ camel_object_unref(folder);
+ }
+ if (camel_operation_cancel_check(m->info->cancel))
+ break;
+ }
+}
+
+static void
+refresh_folders_got (struct _mail_msg *mm)
+{
+ struct _refresh_folders_msg *m = (struct _refresh_folders_msg *)mm;
+
+ receive_done("", m->info);
+}
+
static void
-receive_update_got_folderinfo (CamelStore *store, CamelFolderInfo *info, void *data)
+refresh_folders_free (struct _mail_msg *mm)
{
- receive_done ("", data);
+ struct _refresh_folders_msg *m = (struct _refresh_folders_msg *)mm;
+ int i;
+
+ for (i=0;i<m->folders->len;i++)
+ g_free(m->folders->pdata[i]);
+ g_ptr_array_free(m->folders, TRUE);
+ camel_object_unref(m->store);
+}
+
+static struct _mail_msg_op refresh_folders_op = {
+ refresh_folders_desc,
+ refresh_folders_get,
+ refresh_folders_got,
+ refresh_folders_free,
+};
+
+static void
+get_folders(GPtrArray *folders, CamelFolderInfo *info)
+{
+ while (info) {
+ g_ptr_array_add(folders, g_strdup(info->uri));
+ get_folders(folders, info->child);
+ info = info->next;
+ }
+}
+
+static void
+receive_update_got_folderinfo(CamelStore *store, CamelFolderInfo *info, void *data)
+{
+ if (info) {
+ GPtrArray *folders = g_ptr_array_new();
+ struct _refresh_folders_msg *m;
+ struct _send_info *sinfo = data;
+
+ get_folders(folders, info);
+
+ m = mail_msg_new(&refresh_folders_op, NULL, sizeof(*m));
+ m->store = store;
+ camel_object_ref(store);
+ m->folders = folders;
+ m->info = sinfo;
+
+ e_thread_put(mail_thread_new, (EMsg *)m);
+ } else {
+ receive_done ("", data);
+ }
}
static void
@@ -697,7 +784,7 @@ receive_update_got_store (char *uri, Cam
if (store) {
mail_note_store(store, info->cancel, receive_update_got_folderinfo, info);
} else {
- receive_done ("", info);
+ receive_done("", info);
}
}
@@ -849,6 +936,24 @@ auto_account_changed(EAccountList *eal,
auto_account_commit(info);
}
+static void
+auto_online(CamelObject *o, void *ed, void *d)
+{
+ EIterator *iter;
+ EAccountList *accounts;
+ struct _auto_data *info;
+
+ if (!GPOINTER_TO_INT(ed))
+ return;
+
+ accounts = mail_config_get_accounts ();
+ for (iter = e_list_get_iterator((EList *)accounts);e_iterator_is_valid(iter);e_iterator_next(iter)) {
+ info = g_object_get_data((GObject *)e_iterator_get(iter), "mail-autoreceive");
+ if (info && info->timeout_id)
+ auto_timeout(info);
+ }
+}
+
/* call to setup initial, and after changes are made to the config */
/* FIXME: Need a cleanup funciton for when object is deactivated */
void
@@ -869,6 +974,8 @@ mail_autoreceive_init(void)
for (iter = e_list_get_iterator((EList *)accounts);e_iterator_is_valid(iter);e_iterator_next(iter))
auto_account_added(accounts, (EAccount *)e_iterator_get(iter), NULL);
+
+ camel_object_hook_event(mail_component_peek_session(NULL), "online", auto_online, NULL);
}
/* we setup the download info's in a hashtable, if we later need to build the gui, we insert
Index: mail/mail-tools.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-tools.c,v
retrieving revision 1.137
diff -u -p -r1.137 mail-tools.c
--- mail/mail-tools.c 16 May 2005 07:53:53 -0000 1.137
+++ mail/mail-tools.c 20 Jul 2005 09:33:15 -0000
@@ -293,7 +293,7 @@ mail_tool_uri_to_folder (const char *uri
return NULL;
}
- store = camel_session_get_store (session, uri + offset, ex);
+ store = camel_session_get_service(session, uri+offset, CAMEL_PROVIDER_STORE, ex);
if (store) {
const char *name;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]