1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Authors: Jeffrey Stedfast <fejj@novell.com>
5 * Copyright 2005 Novell, Inc. (www.novell.com)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 #include <glib/gi18n-lib.h>
31 #include "camel-offline-folder.h"
32 #include "camel-operation.h"
33 #include "camel-service.h"
34 #include "camel-session.h"
36 #define CAMEL_OFFLINE_FOLDER_GET_CLASS(f) (CAMEL_OFFLINE_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS (f)))
38 static void camel_offline_folder_class_init (CamelOfflineFolderClass *klass);
39 static void camel_offline_folder_init (CamelOfflineFolder *folder, CamelOfflineFolderClass *klass);
40 static void camel_offline_folder_finalize (CamelObject *object);
42 static int offline_folder_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args);
43 static int offline_folder_setv (CamelObject *object, CamelException *ex, CamelArgV *args);
45 static void offline_folder_downsync (CamelOfflineFolder *offline, const char *expression, CamelException *ex);
47 static CamelFolderClass *parent_class = NULL;
49 static GSList *offline_folder_props = NULL;
51 static CamelProperty offline_prop_list[] = {
52 { CAMEL_OFFLINE_FOLDER_SYNC_OFFLINE, "sync_offline", N_("Copy folder content locally for offline operation") },
57 camel_offline_folder_get_type (void)
59 static CamelType type = 0;
62 type = camel_type_register (CAMEL_FOLDER_TYPE,
64 sizeof (CamelOfflineFolder),
65 sizeof (CamelOfflineFolderClass),
66 (CamelObjectClassInitFunc) camel_offline_folder_class_init,
68 (CamelObjectInitFunc) camel_offline_folder_init,
69 (CamelObjectFinalizeFunc) camel_offline_folder_finalize);
77 camel_offline_folder_class_init (CamelOfflineFolderClass *klass)
81 parent_class = (CamelFolderClass *) camel_type_get_global_classfuncs (CAMEL_FOLDER_TYPE);
83 if (offline_folder_props == NULL) {
84 for (i = 0; i < G_N_ELEMENTS (offline_prop_list); i++) {
85 offline_prop_list[i].description = _(offline_prop_list[i].description);
86 offline_folder_props = g_slist_prepend (offline_folder_props, &offline_prop_list[i]);
90 ((CamelObjectClass *) klass)->getv = offline_folder_getv;
91 ((CamelObjectClass *) klass)->setv = offline_folder_setv;
93 klass->downsync = offline_folder_downsync;
97 struct _offline_downsync_msg {
98 CamelSessionThreadMsg msg;
101 CamelFolderChangeInfo *changes;
105 offline_downsync_sync (CamelSession *session, CamelSessionThreadMsg *mm)
107 struct _offline_downsync_msg *m = (struct _offline_downsync_msg *) mm;
108 CamelMimeMessage *message;
111 camel_operation_start (NULL, _("Downloading new messages for offline mode"));
114 for (i = 0; i < m->changes->uid_added->len; i++) {
115 int pc = i * 100 / m->changes->uid_added->len;
117 camel_operation_progress (NULL, pc);
118 if ((message = camel_folder_get_message (m->folder, m->changes->uid_added->pdata[i], &mm->ex)))
119 camel_object_unref (message);
122 camel_offline_folder_downsync ((CamelOfflineFolder *) m->folder, "(match-all)", &mm->ex);
125 camel_operation_end (NULL);
129 offline_downsync_free (CamelSession *session, CamelSessionThreadMsg *mm)
131 struct _offline_downsync_msg *m = (struct _offline_downsync_msg *) mm;
134 camel_folder_change_info_free (m->changes);
136 camel_object_unref (m->folder);
139 static CamelSessionThreadOps offline_downsync_ops = {
140 offline_downsync_sync,
141 offline_downsync_free,
145 offline_folder_changed (CamelFolder *folder, CamelFolderChangeInfo *changes, void *dummy)
147 CamelOfflineFolder *offline = (CamelOfflineFolder *) folder;
148 CamelService *service = (CamelService *) folder->parent_store;
150 if (changes->uid_added->len > 0 && (offline->sync_offline || camel_url_get_param (service->url, "sync_offline"))) {
151 CamelSession *session = service->session;
152 struct _offline_downsync_msg *m;
154 m = camel_session_thread_msg_new (session, &offline_downsync_ops, sizeof (*m));
155 m->changes = camel_folder_change_info_new ();
156 camel_folder_change_info_cat (m->changes, changes);
157 camel_object_ref (folder);
160 camel_session_thread_queue (session, &m->msg, 0);
165 camel_offline_folder_init (CamelOfflineFolder *folder, CamelOfflineFolderClass *klass)
167 camel_object_hook_event (folder, "folder_changed", (CamelObjectEventHookFunc) offline_folder_changed, NULL);
171 camel_offline_folder_finalize (CamelObject *object)
177 offline_folder_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args)
183 for (i = 0; i < args->argc; i++) {
184 CamelArgGet *arg = &args->argv[i];
188 switch (tag & CAMEL_ARG_TAG) {
189 case CAMEL_OBJECT_ARG_PERSISTENT_PROPERTIES:
190 case CAMEL_FOLDER_ARG_PROPERTIES:
192 props.argv[0] = *arg;
193 ((CamelObjectClass *) parent_class)->getv (object, ex, &props);
194 *arg->ca_ptr = g_slist_concat (*arg->ca_ptr, g_slist_copy (offline_folder_props));
196 case CAMEL_OFFLINE_FOLDER_ARG_SYNC_OFFLINE:
197 *arg->ca_int = ((CamelOfflineFolder *) object)->sync_offline;
204 arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
208 return ((CamelObjectClass *) parent_class)->getv (object, ex, args);
214 offline_folder_setv (CamelObject *object, CamelException *ex, CamelArgV *args)
216 CamelOfflineFolder *folder = (CamelOfflineFolder *) object;
217 gboolean save = FALSE;
221 for (i = 0; i < args->argc; i++) {
222 CamelArg *arg = &args->argv[i];
226 switch (tag & CAMEL_ARG_TAG) {
227 case CAMEL_OFFLINE_FOLDER_ARG_SYNC_OFFLINE:
228 if (folder->sync_offline != arg->ca_int) {
229 folder->sync_offline = arg->ca_int;
237 arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
241 camel_object_state_write (object);
243 return ((CamelObjectClass *) parent_class)->setv (object, ex, args);
247 offline_folder_downsync (CamelOfflineFolder *offline, const char *expression, CamelException *ex)
249 CamelFolder *folder = (CamelFolder *) offline;
250 CamelMimeMessage *message;
254 camel_operation_start (NULL, _("Syncing messages in folder '%s' to disk"), folder->full_name);
257 uids = camel_folder_search_by_expression (folder, expression, ex);
259 uids = camel_folder_get_uids (folder);
262 camel_operation_end (NULL);
266 for (i = 0; i < uids->len; i++) {
267 int pc = i * 100 / uids->len;
269 message = camel_folder_get_message (folder, uids->pdata[i], ex);
270 camel_operation_progress (NULL, pc);
274 camel_object_unref (message);
278 camel_folder_search_free (folder, uids);
280 camel_folder_free_uids (folder, uids);
282 camel_operation_end (NULL);
287 * camel_offline_fodler_downsync:
288 * @offline: a #CamelOfflineFolder object
289 * @expression: search expression describing which set of messages to downsync (%NULL for all)
290 * @ex: a #CamelException
292 * Syncs messages in @offline described by the search @expression to
293 * the local machine for offline availability.
296 camel_offline_folder_downsync (CamelOfflineFolder *offline, const char *expression, CamelException *ex)
298 g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (offline));
300 CAMEL_OFFLINE_FOLDER_GET_CLASS (offline)->downsync (offline, expression, ex);