* Copyright (C) 2001 Ximian, Inc.
*
* 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.
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
#include "camel-disco-store.h"
#include "camel-exception.h"
+#include "camel-session.h"
+
#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS (o)))
#define CDF_CLASS(o) (CAMEL_DISCO_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS (o)))
static void disco_expunge (CamelFolder *folder, CamelException *ex);
static void disco_append_message (CamelFolder *folder, CamelMimeMessage *message,
- const CamelMessageInfo *info, CamelException *ex);
-static void disco_copy_messages_to (CamelFolder *source, GPtrArray *uids,
- CamelFolder *destination, CamelException *ex);
-static void disco_move_messages_to (CamelFolder *source, GPtrArray *uids,
- CamelFolder *destination, CamelException *ex);
-
+ const CamelMessageInfo *info, char **appended_uid, CamelException *ex);
+static void disco_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
+ CamelFolder *destination,
+ GPtrArray **transferred_uids,
+ gboolean delete_originals,
+ CamelException *ex);
+
+static void disco_cache_message (CamelDiscoFolder *disco_folder,
+ const char *uid, CamelException *ex);
+static void disco_prepare_for_offline (CamelDiscoFolder *disco_folder,
+ const char *expression,
+ CamelException *ex);
static void
camel_disco_folder_class_init (CamelDiscoFolderClass *camel_disco_folder_class)
parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_folder_get_type ()));
+ /* virtual method definition */
+ camel_disco_folder_class->cache_message = disco_cache_message;
+ camel_disco_folder_class->prepare_for_offline = disco_prepare_for_offline;
+
/* virtual method overload */
camel_folder_class->refresh_info = disco_refresh_info;
camel_folder_class->sync = disco_sync;
camel_folder_class->expunge = disco_expunge;
camel_folder_class->append_message = disco_append_message;
- camel_folder_class->copy_messages_to = disco_copy_messages_to;
- camel_folder_class->move_messages_to = disco_move_messages_to;
+ camel_folder_class->transfer_messages_to = disco_transfer_messages_to;
+}
+
+struct _cdf_sync_msg {
+ CamelSessionThreadMsg msg;
+
+ CamelFolder *folder;
+ CamelFolderChangeInfo *changes;
+};
+
+static void
+cdf_sync_offline(CamelSession *session, CamelSessionThreadMsg *mm)
+{
+ struct _cdf_sync_msg *m = (struct _cdf_sync_msg *)mm;
+ int i;
+
+ camel_operation_start(NULL, _("Downloading new messages for offline mode"));
+
+ if (m->changes) {
+ for (i=0;i<m->changes->uid_added->len;i++) {
+ int pc = i * 100 / m->changes->uid_added->len;
+
+ camel_operation_progress(NULL, pc);
+ camel_disco_folder_cache_message((CamelDiscoFolder *)m->folder,
+ m->changes->uid_added->pdata[i],
+ &mm->ex);
+ }
+ } else {
+ camel_disco_folder_prepare_for_offline((CamelDiscoFolder *)m->folder,
+ "(match-all)",
+ &mm->ex);
+ }
+
+ camel_operation_end(NULL);
+}
+
+static void
+cdf_sync_free(CamelSession *session, CamelSessionThreadMsg *mm)
+{
+ struct _cdf_sync_msg *m = (struct _cdf_sync_msg *)mm;
+
+ if (m->changes)
+ camel_folder_change_info_free(m->changes);
+ camel_object_unref(m->folder);
+}
+
+static CamelSessionThreadOps cdf_sync_ops = {
+ cdf_sync_offline,
+ cdf_sync_free,
+};
+
+static void
+cdf_folder_changed(CamelFolder *folder, CamelFolderChangeInfo *changes, void *dummy)
+{
+ if (changes->uid_added->len > 0
+ && camel_url_get_param(((CamelService *)folder->parent_store)->url, "offline_sync")) {
+ CamelSession *session = ((CamelService *)folder->parent_store)->session;
+ struct _cdf_sync_msg *m;
+
+ m = camel_session_thread_msg_new(session, &cdf_sync_ops, sizeof(*m));
+ m->changes = camel_folder_change_info_new();
+ camel_folder_change_info_cat(m->changes, changes);
+ m->folder = folder;
+ camel_object_ref(folder);
+ camel_session_thread_queue(session, &m->msg, 0);
+ }
+}
+
+static void
+camel_disco_folder_init(CamelDiscoFolder *folder)
+{
+ camel_object_hook_event(folder, "folder_changed", (CamelObjectEventHookFunc)cdf_folder_changed, NULL);
}
CamelType
CAMEL_FOLDER_TYPE, "CamelDiscoFolder",
sizeof (CamelDiscoFolder),
sizeof (CamelDiscoFolderClass),
- (CamelObjectClassInitFunc) camel_disco_folder_class_init,
- NULL, NULL, NULL);
+ (CamelObjectClassInitFunc)camel_disco_folder_class_init, NULL,
+ (CamelObjectInitFunc)camel_disco_folder_init, NULL);
}
return camel_disco_folder_type;
case CAMEL_DISCO_STORE_OFFLINE:
CDF_CLASS (folder)->sync_offline (folder, ex);
break;
+
+ case CAMEL_DISCO_STORE_RESYNCING:
+ CDF_CLASS (folder)->sync_resyncing (folder, ex);
+ break;
}
}
case CAMEL_DISCO_STORE_OFFLINE:
CDF_CLASS (folder)->expunge_uids_offline (folder, uids, ex);
-#ifdef NOTYET
- if (!camel_exception_is_set (ex))
- camel_disco_diary_log (disco->diary, CAMEL_DISCO_DIARY_FOLDER_EXPUNGE, folder, uids);
-#endif
+ break;
+
+ case CAMEL_DISCO_STORE_RESYNCING:
+ CDF_CLASS (folder)->expunge_uids_resyncing (folder, uids, ex);
break;
}
}
static void
disco_append_message (CamelFolder *folder, CamelMimeMessage *message,
- const CamelMessageInfo *info, CamelException *ex)
+ const CamelMessageInfo *info, char **appended_uid,
+ CamelException *ex)
{
CamelDiscoStore *disco = CAMEL_DISCO_STORE (folder->parent_store);
- char *uid;
switch (camel_disco_store_status (disco)) {
case CAMEL_DISCO_STORE_ONLINE:
- uid = CDF_CLASS (folder)->append_online (folder, message, info, ex);
+ CDF_CLASS (folder)->append_online (folder, message, info,
+ appended_uid, ex);
break;
case CAMEL_DISCO_STORE_OFFLINE:
- uid = CDF_CLASS (folder)->append_offline (folder, message, info, ex);
-#ifdef NOTYET
- if (uid)
- camel_disco_diary_log (disco->diary, CAMEL_DISCO_DIARY_FOLDER_APPEND, folder, uid);
-#endif
+ CDF_CLASS (folder)->append_offline (folder, message, info,
+ appended_uid, ex);
break;
- }
- g_free (uid);
-}
-
-static void
-disco_copy_messages_to (CamelFolder *source, GPtrArray *uids,
- CamelFolder *destination, CamelException *ex)
-{
- CamelDiscoStore *disco = CAMEL_DISCO_STORE (source->parent_store);
- switch (camel_disco_store_status (disco)) {
- case CAMEL_DISCO_STORE_ONLINE:
- CDF_CLASS (source)->copy_online (source, uids, destination, ex);
- break;
-
- case CAMEL_DISCO_STORE_OFFLINE:
- CDF_CLASS (source)->copy_offline (source, uids, destination, ex);
-#ifdef NOTYET
- if (!camel_exception_is_set (ex))
- camel_disco_diary_log (disco->diary, CAMEL_DISCO_DIARY_FOLDER_COPY, source, destination, uids);
-#endif
+ case CAMEL_DISCO_STORE_RESYNCING:
+ CDF_CLASS (folder)->append_resyncing (folder, message, info,
+ appended_uid, ex);
break;
}
}
static void
-disco_move_messages_to (CamelFolder *source, GPtrArray *uids,
- CamelFolder *destination, CamelException *ex)
+disco_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
+ CamelFolder *dest, GPtrArray **transferred_uids,
+ gboolean delete_originals, CamelException *ex)
{
CamelDiscoStore *disco = CAMEL_DISCO_STORE (source->parent_store);
switch (camel_disco_store_status (disco)) {
case CAMEL_DISCO_STORE_ONLINE:
- CDF_CLASS (source)->move_online (source, uids, destination, ex);
+ CDF_CLASS (source)->transfer_online (source, uids,
+ dest, transferred_uids,
+ delete_originals, ex);
break;
case CAMEL_DISCO_STORE_OFFLINE:
- CDF_CLASS (source)->move_offline (source, uids, destination, ex);
-#ifdef NOTYET
- if (!camel_exception_is_set (ex))
- camel_disco_diary_log (disco->diary, CAMEL_DISCO_DIARY_FOLDER_MOVE, source, destination, uids);
-#endif
+ CDF_CLASS (source)->transfer_offline (source, uids,
+ dest, transferred_uids,
+ delete_originals, ex);
+ break;
+
+ case CAMEL_DISCO_STORE_RESYNCING:
+ CDF_CLASS (source)->transfer_resyncing (source, uids,
+ dest, transferred_uids,
+ delete_originals, ex);
break;
}
}
{
disco_expunge_uids (folder, uids, ex);
}
+
+
+static void
+disco_cache_message (CamelDiscoFolder *disco_folder, const char *uid,
+ CamelException *ex)
+{
+ g_warning ("CamelDiscoFolder::cache_message not implemented for `%s'",
+ camel_type_to_name (CAMEL_OBJECT_GET_TYPE (disco_folder)));
+}
+
+/**
+ * camel_disco_folder_cache_message:
+ * @disco_folder: the folder
+ * @uid: the UID of the message to cache
+ * @ex: a CamelException
+ *
+ * Requests that @disco_folder cache message @uid to disk.
+ **/
+void
+camel_disco_folder_cache_message (CamelDiscoFolder *disco_folder,
+ const char *uid, CamelException *ex)
+{
+ CDF_CLASS (disco_folder)->cache_message (disco_folder, uid, ex);
+}
+
+
+static void
+disco_prepare_for_offline (CamelDiscoFolder *disco_folder,
+ const char *expression,
+ CamelException *ex)
+{
+ CamelFolder *folder = CAMEL_FOLDER (disco_folder);
+ GPtrArray *uids;
+ int i;
+
+ camel_operation_start(NULL, _("Preparing folder '%s' for offline"), folder->full_name);
+
+ if (expression)
+ uids = camel_folder_search_by_expression (folder, expression, ex);
+ else
+ uids = camel_folder_get_uids (folder);
+
+ if (!uids) {
+ camel_operation_end(NULL);
+ return;
+ }
+
+ for (i = 0; i < uids->len; i++) {
+ int pc = i * 100 / uids->len;
+
+ camel_disco_folder_cache_message (disco_folder, uids->pdata[i], ex);
+ camel_operation_progress(NULL, pc);
+ if (camel_exception_is_set (ex))
+ break;
+ }
+
+ if (expression)
+ camel_folder_search_free (folder, uids);
+ else
+ camel_folder_free_uids (folder, uids);
+
+ camel_operation_end(NULL);
+}
+
+/**
+ * camel_disco_folder_prepare_for_offline:
+ * @disco_folder: the folder
+ * @expression: an expression describing messages to synchronize, or %NULL
+ * if all messages should be sync'ed.
+ * @ex: a CamelException
+ *
+ * This prepares @disco_folder for offline operation, by downloading
+ * the bodies of all messages described by @expression (using the
+ * same syntax as camel_folder_search_by_expression() ).
+ **/
+void
+camel_disco_folder_prepare_for_offline (CamelDiscoFolder *disco_folder,
+ const char *expression,
+ CamelException *ex)
+{
+ g_return_if_fail (CAMEL_IS_DISCO_FOLDER (disco_folder));
+
+ CDF_CLASS (disco_folder)->prepare_for_offline (disco_folder, expression, ex);
+}