1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camel-folder.c: Abstract class for an email folder */
6 * Bertrand Guiheneuf <bertrand@helixcode.com>
8 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU Lesser General Public
12 * License as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
31 #include <glib/gi18n-lib.h>
34 #include "camel-debug.h"
35 #include "camel-filter-driver.h"
36 #include "camel-folder.h"
37 #include "camel-mempool.h"
38 #include "camel-mime-message.h"
39 #include "camel-operation.h"
40 #include "camel-session.h"
41 #include "camel-store.h"
42 #include "camel-vtrash-folder.h"
43 #include "camel-string-utils.h"
45 #define CAMEL_FOLDER_GET_PRIVATE(obj) \
46 (G_TYPE_INSTANCE_GET_PRIVATE \
47 ((obj), CAMEL_TYPE_FOLDER, CamelFolderPrivate))
52 typedef struct _AsyncContext AsyncContext;
53 typedef struct _SignalData SignalData;
54 typedef struct _FolderFilterData FolderFilterData;
56 struct _CamelFolderPrivate {
59 /* must require the 'change_lock' to access this */
61 CamelFolderChangeInfo *changed_frozen; /* queues changed events */
62 gboolean skip_folder_lock;
64 /* Changes to be emitted from an idle callback. */
65 CamelFolderChangeInfo *pending_changes;
67 gpointer parent_store; /* weak pointer */
74 struct _AsyncContext {
76 CamelMimeMessage *message; /* also a result */
77 CamelMessageInfo *info;
78 CamelFolder *destination;
79 GPtrArray *message_uids;
80 gchar *message_uid; /* also a result */
81 gboolean delete_originals;
83 CamelFetchType fetch_type;
89 GPtrArray *transferred_uids;
90 CamelFolderQuotaInfo *quota_info;
91 gboolean success; /* A result that mention that there are more messages in fetch_messages operation */
94 struct _CamelFolderChangeInfoPrivate {
95 GHashTable *uid_stored; /* what we have stored, which array they're in */
96 GHashTable *uid_source; /* used to create unique lists */
97 GPtrArray *uid_filter; /* uids to be filtered */
98 CamelMemPool *uid_pool; /* pool used to store copies of uid strings */
106 struct _FolderFilterData {
111 CamelFilterDriver *driver;
129 static guint signals[LAST_SIGNAL];
131 G_DEFINE_ABSTRACT_TYPE (CamelFolder, camel_folder, CAMEL_TYPE_OBJECT)
134 async_context_free (AsyncContext *async_context)
136 if (async_context->message != NULL)
137 g_object_unref (async_context->message);
139 /* XXX This is actually an unref. Good god, no wonder we
140 * have so many crashes involving CamelMessageInfos! */
141 if (async_context->info != NULL)
142 camel_message_info_free (async_context->info);
144 if (async_context->destination != NULL)
145 g_object_unref (async_context->destination);
147 if (async_context->message_uids != NULL) {
148 g_ptr_array_foreach (
149 async_context->message_uids, (GFunc) g_free, NULL);
150 g_ptr_array_free (async_context->message_uids, TRUE);
153 if (async_context->transferred_uids != NULL) {
154 g_ptr_array_foreach (
155 async_context->transferred_uids, (GFunc) g_free, NULL);
156 g_ptr_array_free (async_context->transferred_uids, TRUE);
159 if (async_context->quota_info != NULL)
160 camel_folder_quota_info_free (async_context->quota_info);
162 g_free (async_context->message_uid);
163 g_free (async_context->start_uid);
164 g_free (async_context->end_uid);
166 g_slice_free (AsyncContext, async_context);
170 signal_data_free (SignalData *signal_data)
172 if (signal_data->folder != NULL)
173 g_object_unref (signal_data->folder);
175 g_free (signal_data->folder_name);
177 g_slice_free (SignalData, signal_data);
181 folder_emit_changed_cb (gpointer user_data)
183 SignalData *signal_data = user_data;
184 CamelFolderChangeInfo *changes;
186 camel_folder_lock (signal_data->folder, CAMEL_FOLDER_CHANGE_LOCK);
187 changes = signal_data->folder->priv->pending_changes;
188 signal_data->folder->priv->pending_changes = NULL;
189 camel_folder_unlock (signal_data->folder, CAMEL_FOLDER_CHANGE_LOCK);
191 g_signal_emit (signal_data->folder, signals[CHANGED], 0, changes);
193 camel_folder_change_info_free (changes);
199 folder_emit_deleted_cb (gpointer user_data)
201 SignalData *signal_data = user_data;
203 g_signal_emit (signal_data->folder, signals[DELETED], 0);
209 folder_emit_renamed_cb (gpointer user_data)
211 SignalData *signal_data = user_data;
216 signal_data->folder_name);
222 folder_filter_data_free (FolderFilterData *data)
224 if (data->driver != NULL)
225 g_object_unref (data->driver);
226 if (data->recents != NULL)
227 camel_folder_free_deep (data->folder, data->recents);
228 if (data->junk != NULL)
229 camel_folder_free_deep (data->folder, data->junk);
230 if (data->notjunk != NULL)
231 camel_folder_free_deep (data->folder, data->notjunk);
233 /* XXX Too late to pass a GError here. */
234 camel_folder_summary_save_to_db (data->folder->summary, NULL);
236 camel_folder_thaw (data->folder);
237 g_object_unref (data->folder);
239 g_slice_free (FolderFilterData, data);
243 folder_filter (CamelSession *session,
244 GCancellable *cancellable,
245 FolderFilterData *data,
248 CamelMessageInfo *info;
249 CamelStore *parent_store;
251 CamelJunkFilter *junk_filter;
252 gboolean synchronize = FALSE;
253 const gchar *display_name;
255 display_name = camel_folder_get_display_name (data->folder);
256 parent_store = camel_folder_get_parent_store (data->folder);
257 junk_filter = camel_session_get_junk_filter (session);
259 /* Keep the junk filter alive until we're done. */
260 if (junk_filter != NULL)
261 g_object_ref (junk_filter);
264 gboolean success = TRUE;
266 /* Translators: The %s is replaced with the
267 * folder name where the operation is running. */
268 camel_operation_push_message (
269 cancellable, ngettext (
270 "Learning new spam message in '%s'",
271 "Learning new spam messages in '%s'",
272 data->junk->len), display_name);
274 for (i = 0; success && i < data->junk->len; i++) {
275 CamelMimeMessage *message;
276 gint pc = 100 * i / data->junk->len;
278 if (g_cancellable_set_error_if_cancelled (
282 message = camel_folder_get_message_sync (
283 data->folder, data->junk->pdata[i],
289 camel_operation_progress (cancellable, pc);
290 success = camel_junk_filter_learn_junk (
291 junk_filter, message, cancellable, error);
292 g_object_unref (message);
294 synchronize |= success;
297 camel_operation_pop_message (cancellable);
304 gboolean success = TRUE;
306 /* Translators: The %s is replaced with the
307 * folder name where the operation is running. */
308 camel_operation_push_message (
309 cancellable, ngettext (
310 "Learning new ham message in '%s'",
311 "Learning new ham messages in '%s'",
312 data->notjunk->len), display_name);
314 for (i = 0; success && i < data->notjunk->len; i++) {
315 CamelMimeMessage *message;
316 gint pc = 100 * i / data->notjunk->len;
318 if (g_cancellable_set_error_if_cancelled (
322 message = camel_folder_get_message_sync (
323 data->folder, data->notjunk->pdata[i],
329 camel_operation_progress (cancellable, pc);
330 success = camel_junk_filter_learn_not_junk (
331 junk_filter, message, cancellable, error);
332 g_object_unref (message);
334 synchronize |= success;
337 camel_operation_pop_message (cancellable);
344 camel_junk_filter_synchronize (
345 junk_filter, cancellable, error);
350 if (data->driver && data->recents) {
351 CamelService *service;
352 const gchar *store_uid;
354 /* Translators: The %s is replaced with the
355 * folder name where the operation is running. */
356 camel_operation_push_message (
357 cancellable, ngettext (
358 "Filtering new message in '%s'",
359 "Filtering new messages in '%s'",
360 data->recents->len), display_name);
362 service = CAMEL_SERVICE (parent_store);
363 store_uid = camel_service_get_uid (service);
365 for (i = 0; status == 0 && i < data->recents->len; i++) {
366 gchar *uid = data->recents->pdata[i];
367 gint pc = 100 * i / data->recents->len;
369 camel_operation_progress (cancellable, pc);
371 info = camel_folder_get_message_info (
375 "uid '%s' vanished from folder '%s'",
380 status = camel_filter_driver_filter_message (
381 data->driver, NULL, info, uid, data->folder,
382 store_uid, store_uid, cancellable, error);
384 camel_folder_free_message_info (data->folder, info);
387 camel_operation_pop_message (cancellable);
389 camel_filter_driver_flush (data->driver, error);
393 if (junk_filter != NULL)
394 g_object_unref (junk_filter);
398 cmp_array_uids (gconstpointer a,
402 const gchar *uid1 = *(const gchar **) a;
403 const gchar *uid2 = *(const gchar **) b;
404 CamelFolder *folder = user_data;
406 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
408 return camel_folder_cmp_uids (folder, uid1, uid2);
412 folder_transfer_message_to (CamelFolder *source,
415 gchar **transferred_uid,
416 gboolean delete_original,
417 GCancellable *cancellable,
420 CamelMimeMessage *msg;
421 CamelMessageInfo *minfo, *info;
422 GError *local_error = NULL;
424 /* Default implementation. */
426 msg = camel_folder_get_message_sync (source, uid, cancellable, error);
430 /* if its deleted we poke the flags, so we need to copy the messageinfo */
431 if ((source->folder_flags & CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY)
432 && (minfo = camel_folder_get_message_info (source, uid))) {
433 info = camel_message_info_clone (minfo);
434 camel_folder_free_message_info (source, minfo);
436 info = camel_message_info_new_from_header (NULL, ((CamelMimePart *) msg)->headers);
438 /* unset deleted flag when transferring from trash folder */
439 if ((source->folder_flags & CAMEL_FOLDER_IS_TRASH) != 0)
440 camel_message_info_set_flags (info, CAMEL_MESSAGE_DELETED, 0);
441 /* unset junk flag when transferring from junk folder */
442 if ((source->folder_flags & CAMEL_FOLDER_IS_JUNK) != 0)
443 camel_message_info_set_flags (info, CAMEL_MESSAGE_JUNK, 0);
445 camel_folder_append_message_sync (
446 dest, msg, info, transferred_uid,
447 cancellable, &local_error);
448 g_object_unref (msg);
450 if (local_error != NULL)
451 g_propagate_error (error, local_error);
452 else if (delete_original)
453 camel_folder_set_message_flags (
454 source, uid, CAMEL_MESSAGE_DELETED |
455 CAMEL_MESSAGE_SEEN, ~0);
457 camel_message_info_free (info);
461 folder_set_parent_store (CamelFolder *folder,
462 CamelStore *parent_store)
464 g_return_if_fail (CAMEL_IS_STORE (parent_store));
465 g_return_if_fail (folder->priv->parent_store == NULL);
467 folder->priv->parent_store = parent_store;
469 g_object_add_weak_pointer (
470 G_OBJECT (parent_store), &folder->priv->parent_store);
474 folder_set_property (GObject *object,
479 switch (property_id) {
480 case PROP_DESCRIPTION:
481 camel_folder_set_description (
482 CAMEL_FOLDER (object),
483 g_value_get_string (value));
486 case PROP_DISPLAY_NAME:
487 camel_folder_set_display_name (
488 CAMEL_FOLDER (object),
489 g_value_get_string (value));
493 camel_folder_set_full_name (
494 CAMEL_FOLDER (object),
495 g_value_get_string (value));
498 case PROP_PARENT_STORE:
499 folder_set_parent_store (
500 CAMEL_FOLDER (object),
501 g_value_get_object (value));
505 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
509 folder_get_property (GObject *object,
514 switch (property_id) {
515 case PROP_DESCRIPTION:
517 value, camel_folder_get_description (
518 CAMEL_FOLDER (object)));
521 case PROP_DISPLAY_NAME:
523 value, camel_folder_get_display_name (
524 CAMEL_FOLDER (object)));
529 value, camel_folder_get_full_name (
530 CAMEL_FOLDER (object)));
533 case PROP_PARENT_STORE:
535 value, camel_folder_get_parent_store (
536 CAMEL_FOLDER (object)));
540 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
544 folder_dispose (GObject *object)
548 folder = CAMEL_FOLDER (object);
550 if (folder->priv->parent_store != NULL) {
551 g_object_remove_weak_pointer (
552 G_OBJECT (folder->priv->parent_store),
553 &folder->priv->parent_store);
554 folder->priv->parent_store = NULL;
557 if (folder->summary) {
558 g_object_unref (folder->summary);
559 folder->summary = NULL;
562 /* Chain up to parent's dispose () method. */
563 G_OBJECT_CLASS (camel_folder_parent_class)->dispose (object);
567 folder_finalize (GObject *object)
569 CamelFolderPrivate *priv;
571 priv = CAMEL_FOLDER_GET_PRIVATE (object);
573 g_free (priv->full_name);
574 g_free (priv->display_name);
575 g_free (priv->description);
577 camel_folder_change_info_free (priv->changed_frozen);
579 if (priv->pending_changes != NULL)
580 camel_folder_change_info_free (priv->pending_changes);
582 g_rec_mutex_clear (&priv->lock);
583 g_mutex_clear (&priv->change_lock);
585 /* Chain up to parent's finalize () method. */
586 G_OBJECT_CLASS (camel_folder_parent_class)->finalize (object);
590 folder_get_message_count (CamelFolder *folder)
592 g_return_val_if_fail (folder->summary != NULL, -1);
594 return camel_folder_summary_count (folder->summary);
597 static CamelMessageFlags
598 folder_get_permanent_flags (CamelFolder *folder)
600 return folder->permanent_flags;
603 static CamelMessageFlags
604 folder_get_message_flags (CamelFolder *folder,
607 CamelMessageInfo *info;
608 CamelMessageFlags flags;
610 g_return_val_if_fail (folder->summary != NULL, 0);
612 info = camel_folder_summary_get (folder->summary, uid);
616 flags = camel_message_info_flags (info);
617 camel_message_info_free (info);
623 folder_set_message_flags (CamelFolder *folder,
625 CamelMessageFlags flags,
626 CamelMessageFlags set)
628 CamelMessageInfo *info;
631 g_return_val_if_fail (folder->summary != NULL, FALSE);
633 info = camel_folder_summary_get (folder->summary, uid);
637 res = camel_message_info_set_flags (info, flags, set);
638 camel_message_info_free (info);
644 folder_get_message_user_flag (CamelFolder *folder,
648 CamelMessageInfo *info;
651 g_return_val_if_fail (folder->summary != NULL, FALSE);
653 info = camel_folder_summary_get (folder->summary, uid);
657 ret = camel_message_info_user_flag (info, name);
658 camel_message_info_free (info);
664 folder_set_message_user_flag (CamelFolder *folder,
669 CamelMessageInfo *info;
671 g_return_if_fail (folder->summary != NULL);
673 info = camel_folder_summary_get (folder->summary, uid);
677 camel_message_info_set_user_flag (info, name, value);
678 camel_message_info_free (info);
682 folder_get_message_user_tag (CamelFolder *folder,
686 CamelMessageInfo *info;
689 g_return_val_if_fail (folder->summary != NULL, NULL);
691 info = camel_folder_summary_get (folder->summary, uid);
695 ret = camel_message_info_user_tag (info, name);
696 camel_message_info_free (info);
702 folder_set_message_user_tag (CamelFolder *folder,
707 CamelMessageInfo *info;
709 g_return_if_fail (folder->summary != NULL);
711 info = camel_folder_summary_get (folder->summary, uid);
715 camel_message_info_set_user_tag (info, name, value);
716 camel_message_info_free (info);
720 folder_get_uids (CamelFolder *folder)
722 g_return_val_if_fail (folder->summary != NULL, NULL);
724 return camel_folder_summary_get_array (folder->summary);
728 folder_get_uncached_uids (CamelFolder *folder,
735 result = g_ptr_array_new ();
737 g_ptr_array_set_size (result, uids->len);
738 for (i = 0; i < uids->len; i++)
740 (gpointer) camel_pstring_strdup (uids->pdata[i]);
746 folder_free_uids (CamelFolder *folder,
749 camel_folder_summary_free_array (array);
753 folder_cmp_uids (CamelFolder *folder,
757 g_return_val_if_fail (uid1 != NULL, 0);
758 g_return_val_if_fail (uid2 != NULL, 0);
760 return strtoul (uid1, NULL, 10) - strtoul (uid2, NULL, 10);
764 folder_sort_uids (CamelFolder *folder,
768 uids->pdata, uids->len,
769 sizeof (gpointer), cmp_array_uids, folder);
773 folder_get_summary (CamelFolder *folder)
775 g_return_val_if_fail (folder->summary != NULL, NULL);
777 return camel_folder_summary_get_array (folder->summary);
781 folder_free_summary (CamelFolder *folder,
784 camel_folder_summary_free_array (array);
788 folder_search_free (CamelFolder *folder,
793 for (i = 0; i < result->len; i++)
794 camel_pstring_free (g_ptr_array_index (result, i));
795 g_ptr_array_free (result, TRUE);
798 static CamelMessageInfo *
799 folder_get_message_info (CamelFolder *folder,
802 g_return_val_if_fail (folder->summary != NULL, NULL);
804 return camel_folder_summary_get (folder->summary, uid);
808 folder_ref_message_info (CamelFolder *folder,
809 CamelMessageInfo *info)
811 g_return_if_fail (folder->summary != NULL);
813 camel_message_info_ref (info);
817 folder_free_message_info (CamelFolder *folder,
818 CamelMessageInfo *info)
820 g_return_if_fail (folder->summary != NULL);
822 camel_message_info_free (info);
826 folder_delete (CamelFolder *folder)
829 camel_folder_summary_clear (folder->summary, NULL);
833 folder_rename (CamelFolder *folder,
838 d (printf ("CamelFolder:rename ('%s')\n", new));
840 camel_folder_set_full_name (folder, new);
842 tmp = strrchr (new, '/');
843 camel_folder_set_display_name (folder, (tmp != NULL) ? tmp + 1 : new);
847 folder_freeze (CamelFolder *folder)
849 g_return_if_fail (folder->priv->frozen >= 0);
851 camel_folder_lock (folder, CAMEL_FOLDER_CHANGE_LOCK);
853 folder->priv->frozen++;
855 g_object_freeze_notify (G_OBJECT (folder->summary));
857 d (printf ("freeze (%p '%s') = %d\n", folder, folder->full_name, folder->priv->frozen));
858 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
862 folder_thaw (CamelFolder *folder)
864 CamelFolderChangeInfo *info = NULL;
866 g_return_if_fail (folder->priv->frozen > 0);
868 camel_folder_lock (folder, CAMEL_FOLDER_CHANGE_LOCK);
870 folder->priv->frozen--;
872 g_object_thaw_notify (G_OBJECT (folder->summary));
874 d (printf ("thaw (%p '%s') = %d\n", folder, folder->full_name, folder->priv->frozen));
876 if (folder->priv->frozen == 0
877 && camel_folder_change_info_changed (folder->priv->changed_frozen)) {
878 info = folder->priv->changed_frozen;
879 folder->priv->changed_frozen = camel_folder_change_info_new ();
882 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
885 camel_folder_changed (folder, info);
886 camel_folder_change_info_free (info);
891 folder_is_frozen (CamelFolder *folder)
893 return folder->priv->frozen != 0;
897 folder_refresh_info_sync (CamelFolder *folder,
898 GCancellable *cancellable,
905 folder_transfer_messages_to_sync (CamelFolder *source,
908 gboolean delete_originals,
909 GPtrArray **transferred_uids,
910 GCancellable *cancellable,
913 gchar **ret_uid = NULL;
915 GError *local_error = NULL;
916 GCancellable *local_cancellable = camel_operation_new ();
917 gulong handler_id = 0;
919 if (transferred_uids) {
920 *transferred_uids = g_ptr_array_new ();
921 g_ptr_array_set_size (*transferred_uids, uids->len);
924 /* to not propagate status messages from sub-functions into UI */
926 handler_id = g_signal_connect_swapped (cancellable, "cancelled", G_CALLBACK (g_cancellable_cancel), local_cancellable);
928 if (delete_originals)
929 camel_operation_push_message (
930 cancellable, _("Moving messages"));
932 camel_operation_push_message (
933 cancellable, _("Copying messages"));
936 camel_folder_freeze (dest);
937 if (delete_originals)
938 camel_folder_freeze (source);
941 for (i = 0; i < uids->len && local_error == NULL; i++) {
942 if (transferred_uids)
943 ret_uid = (gchar **) &((*transferred_uids)->pdata[i]);
944 folder_transfer_message_to (
945 source, uids->pdata[i], dest, ret_uid,
946 delete_originals, local_cancellable, &local_error);
947 camel_operation_progress (
948 cancellable, i * 100 / uids->len);
952 camel_folder_thaw (dest);
953 if (delete_originals)
954 camel_folder_thaw (source);
957 camel_operation_pop_message (cancellable);
959 if (local_error != NULL)
960 g_propagate_error (error, local_error);
961 g_object_unref (local_cancellable);
963 g_signal_handler_disconnect (cancellable, handler_id);
969 folder_append_message_thread (GSimpleAsyncResult *simple,
971 GCancellable *cancellable)
973 AsyncContext *async_context;
974 GError *error = NULL;
976 async_context = g_simple_async_result_get_op_res_gpointer (simple);
978 camel_folder_append_message_sync (
979 CAMEL_FOLDER (object), async_context->message,
980 async_context->info, &async_context->message_uid,
981 cancellable, &error);
984 g_simple_async_result_take_error (simple, error);
988 folder_append_message (CamelFolder *folder,
989 CamelMimeMessage *message,
990 CamelMessageInfo *info,
992 GCancellable *cancellable,
993 GAsyncReadyCallback callback,
996 GSimpleAsyncResult *simple;
997 AsyncContext *async_context;
999 async_context = g_slice_new0 (AsyncContext);
1000 async_context->message = g_object_ref (message);
1001 async_context->info = camel_message_info_ref (info);
1003 simple = g_simple_async_result_new (
1004 G_OBJECT (folder), callback,
1005 user_data, folder_append_message);
1007 g_simple_async_result_set_check_cancellable (simple, cancellable);
1009 g_simple_async_result_set_op_res_gpointer (
1010 simple, async_context, (GDestroyNotify) async_context_free);
1012 g_simple_async_result_run_in_thread (
1013 simple, folder_append_message_thread,
1014 io_priority, cancellable);
1016 g_object_unref (simple);
1020 folder_append_message_finish (CamelFolder *folder,
1021 GAsyncResult *result,
1022 gchar **appended_uid,
1025 GSimpleAsyncResult *simple;
1026 AsyncContext *async_context;
1028 g_return_val_if_fail (
1029 g_simple_async_result_is_valid (
1030 result, G_OBJECT (folder), folder_append_message), FALSE);
1032 simple = G_SIMPLE_ASYNC_RESULT (result);
1033 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1035 if (appended_uid != NULL) {
1036 *appended_uid = async_context->message_uid;
1037 async_context->message_uid = NULL;
1040 /* Assume success unless a GError is set. */
1041 return !g_simple_async_result_propagate_error (simple, error);
1045 folder_expunge_thread (GSimpleAsyncResult *simple,
1047 GCancellable *cancellable)
1049 GError *error = NULL;
1051 camel_folder_expunge_sync (
1052 CAMEL_FOLDER (object), cancellable, &error);
1055 g_simple_async_result_take_error (simple, error);
1059 folder_expunge (CamelFolder *folder,
1061 GCancellable *cancellable,
1062 GAsyncReadyCallback callback,
1065 GSimpleAsyncResult *simple;
1067 simple = g_simple_async_result_new (
1068 G_OBJECT (folder), callback, user_data, folder_expunge);
1070 g_simple_async_result_set_check_cancellable (simple, cancellable);
1072 g_simple_async_result_run_in_thread (
1073 simple, folder_expunge_thread, io_priority, cancellable);
1075 g_object_unref (simple);
1079 folder_expunge_finish (CamelFolder *folder,
1080 GAsyncResult *result,
1083 GSimpleAsyncResult *simple;
1085 g_return_val_if_fail (
1086 g_simple_async_result_is_valid (
1087 result, G_OBJECT (folder), folder_expunge), FALSE);
1089 simple = G_SIMPLE_ASYNC_RESULT (result);
1091 /* Assume success unless a GError is set. */
1092 return !g_simple_async_result_propagate_error (simple, error);
1096 fetch_messages_thread (GSimpleAsyncResult *simple,
1098 GCancellable *cancellable)
1100 AsyncContext *async_context;
1101 GError *error = NULL;
1103 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1105 async_context->success = camel_folder_fetch_messages_sync (
1106 CAMEL_FOLDER (object), async_context->fetch_type, async_context->limit, cancellable, &error);
1109 g_simple_async_result_take_error (simple, error);
1113 fetch_messages (CamelFolder *folder,
1114 CamelFetchType type,
1117 GCancellable *cancellable,
1118 GAsyncReadyCallback callback,
1121 GSimpleAsyncResult *simple;
1122 AsyncContext *async_context;
1124 async_context = g_slice_new0 (AsyncContext);
1125 async_context->fetch_type = type;
1126 async_context->limit = limit;
1128 simple = g_simple_async_result_new (
1129 G_OBJECT (folder), callback, user_data, fetch_messages);
1131 g_simple_async_result_set_check_cancellable (simple, cancellable);
1133 g_simple_async_result_set_op_res_gpointer (
1134 simple, async_context, (GDestroyNotify) async_context_free);
1136 g_simple_async_result_run_in_thread (
1137 simple, fetch_messages_thread, io_priority, cancellable);
1139 g_object_unref (simple);
1143 fetch_messages_finish (CamelFolder *folder,
1144 GAsyncResult *result,
1147 GSimpleAsyncResult *simple;
1148 AsyncContext *async_context;
1150 g_return_val_if_fail (
1151 g_simple_async_result_is_valid (
1152 result, G_OBJECT (folder), fetch_messages), FALSE);
1154 simple = G_SIMPLE_ASYNC_RESULT (result);
1155 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1157 /* Assume success unless a GError is set. */
1158 return !g_simple_async_result_propagate_error (simple, error)
1159 && async_context->success;
1163 folder_get_message_thread (GSimpleAsyncResult *simple,
1165 GCancellable *cancellable)
1167 AsyncContext *async_context;
1168 GError *error = NULL;
1170 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1172 async_context->message = camel_folder_get_message_sync (
1173 CAMEL_FOLDER (object), async_context->message_uid,
1174 cancellable, &error);
1177 g_simple_async_result_take_error (simple, error);
1181 folder_get_message (CamelFolder *folder,
1182 const gchar *message_uid,
1184 GCancellable *cancellable,
1185 GAsyncReadyCallback callback,
1188 GSimpleAsyncResult *simple;
1189 AsyncContext *async_context;
1191 async_context = g_slice_new0 (AsyncContext);
1192 async_context->message_uid = g_strdup (message_uid);
1194 simple = g_simple_async_result_new (
1195 G_OBJECT (folder), callback, user_data, folder_get_message);
1197 g_simple_async_result_set_check_cancellable (simple, cancellable);
1199 g_simple_async_result_set_op_res_gpointer (
1200 simple, async_context, (GDestroyNotify) async_context_free);
1202 g_simple_async_result_run_in_thread (
1203 simple, folder_get_message_thread, io_priority, cancellable);
1205 g_object_unref (simple);
1208 static CamelMimeMessage *
1209 folder_get_message_finish (CamelFolder *folder,
1210 GAsyncResult *result,
1213 GSimpleAsyncResult *simple;
1214 AsyncContext *async_context;
1216 g_return_val_if_fail (
1217 g_simple_async_result_is_valid (
1218 result, G_OBJECT (folder), folder_get_message), NULL);
1220 simple = G_SIMPLE_ASYNC_RESULT (result);
1221 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1223 if (g_simple_async_result_propagate_error (simple, error))
1226 return g_object_ref (async_context->message);
1230 folder_get_quota_info_thread (GSimpleAsyncResult *simple,
1232 GCancellable *cancellable)
1234 AsyncContext *async_context;
1235 GError *error = NULL;
1237 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1239 async_context->quota_info = camel_folder_get_quota_info_sync (
1240 CAMEL_FOLDER (object), cancellable, &error);
1243 g_simple_async_result_take_error (simple, error);
1246 static CamelFolderQuotaInfo *
1247 folder_get_quota_info_sync (CamelFolder *folder,
1248 GCancellable *cancellable,
1252 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1253 _("Quota information not supported for folder '%s'"),
1254 camel_folder_get_display_name (folder));
1260 folder_get_quota_info (CamelFolder *folder,
1262 GCancellable *cancellable,
1263 GAsyncReadyCallback callback,
1266 GSimpleAsyncResult *simple;
1267 AsyncContext *async_context;
1269 async_context = g_slice_new0 (AsyncContext);
1271 simple = g_simple_async_result_new (
1272 G_OBJECT (folder), callback,
1273 user_data, folder_get_quota_info);
1275 g_simple_async_result_set_check_cancellable (simple, cancellable);
1277 g_simple_async_result_set_op_res_gpointer (
1278 simple, async_context, (GDestroyNotify) async_context_free);
1280 g_simple_async_result_run_in_thread (
1281 simple, folder_get_quota_info_thread,
1282 io_priority, cancellable);
1284 g_object_unref (simple);
1287 static CamelFolderQuotaInfo *
1288 folder_get_quota_info_finish (CamelFolder *folder,
1289 GAsyncResult *result,
1292 GSimpleAsyncResult *simple;
1293 AsyncContext *async_context;
1294 CamelFolderQuotaInfo *quota_info;
1296 g_return_val_if_fail (
1297 g_simple_async_result_is_valid (
1298 result, G_OBJECT (folder), folder_get_quota_info), NULL);
1300 simple = G_SIMPLE_ASYNC_RESULT (result);
1301 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1303 if (g_simple_async_result_propagate_error (simple, error))
1306 quota_info = async_context->quota_info;
1307 async_context->quota_info = NULL;
1313 purge_message_cache_thread (GSimpleAsyncResult *simple,
1315 GCancellable *cancellable)
1317 AsyncContext *async_context;
1318 GError *error = NULL;
1320 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1322 async_context->success = camel_folder_purge_message_cache_sync (
1323 CAMEL_FOLDER (object), async_context->start_uid, async_context->end_uid, cancellable, &error);
1326 g_simple_async_result_take_error (simple, error);
1330 purge_message_cache (CamelFolder *folder,
1334 GCancellable *cancellable,
1335 GAsyncReadyCallback callback,
1338 GSimpleAsyncResult *simple;
1339 AsyncContext *async_context;
1341 async_context = g_slice_new0 (AsyncContext);
1342 async_context->start_uid = g_strdup (start_uid);
1343 async_context->end_uid = g_strdup (end_uid);
1345 simple = g_simple_async_result_new (
1346 G_OBJECT (folder), callback, user_data, purge_message_cache);
1348 g_simple_async_result_set_check_cancellable (simple, cancellable);
1350 g_simple_async_result_set_op_res_gpointer (
1351 simple, async_context, (GDestroyNotify) async_context_free);
1353 g_simple_async_result_run_in_thread (
1354 simple, purge_message_cache_thread, io_priority, cancellable);
1356 g_object_unref (simple);
1360 purge_message_cache_finish (CamelFolder *folder,
1361 GAsyncResult *result,
1364 GSimpleAsyncResult *simple;
1365 AsyncContext *async_context;
1367 g_return_val_if_fail (
1368 g_simple_async_result_is_valid (
1369 result, G_OBJECT (folder), purge_message_cache), FALSE);
1371 simple = G_SIMPLE_ASYNC_RESULT (result);
1372 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1374 /* Assume success unless a GError is set. */
1375 return !g_simple_async_result_propagate_error (simple, error)
1376 && async_context->success;
1380 folder_refresh_info_thread (GSimpleAsyncResult *simple,
1382 GCancellable *cancellable)
1384 GError *error = NULL;
1386 camel_folder_refresh_info_sync (
1387 CAMEL_FOLDER (object), cancellable, &error);
1390 g_simple_async_result_take_error (simple, error);
1394 folder_refresh_info (CamelFolder *folder,
1396 GCancellable *cancellable,
1397 GAsyncReadyCallback callback,
1400 GSimpleAsyncResult *simple;
1402 simple = g_simple_async_result_new (
1403 G_OBJECT (folder), callback, user_data, folder_refresh_info);
1405 g_simple_async_result_set_check_cancellable (simple, cancellable);
1407 g_simple_async_result_run_in_thread (
1408 simple, folder_refresh_info_thread, io_priority, cancellable);
1410 g_object_unref (simple);
1414 folder_refresh_info_finish (CamelFolder *folder,
1415 GAsyncResult *result,
1418 GSimpleAsyncResult *simple;
1420 g_return_val_if_fail (
1421 g_simple_async_result_is_valid (
1422 result, G_OBJECT (folder), folder_refresh_info), FALSE);
1424 simple = G_SIMPLE_ASYNC_RESULT (result);
1426 /* Assume success unless a GError is set. */
1427 return !g_simple_async_result_propagate_error (simple, error);
1431 folder_synchronize_thread (GSimpleAsyncResult *simple,
1433 GCancellable *cancellable)
1435 AsyncContext *async_context;
1436 GError *error = NULL;
1438 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1440 camel_folder_synchronize_sync (
1441 CAMEL_FOLDER (object), async_context->expunge,
1442 cancellable, &error);
1445 g_simple_async_result_take_error (simple, error);
1449 folder_synchronize (CamelFolder *folder,
1452 GCancellable *cancellable,
1453 GAsyncReadyCallback callback,
1456 GSimpleAsyncResult *simple;
1457 AsyncContext *async_context;
1459 async_context = g_slice_new0 (AsyncContext);
1460 async_context->expunge = expunge;
1462 simple = g_simple_async_result_new (
1463 G_OBJECT (folder), callback, user_data, folder_synchronize);
1465 g_simple_async_result_set_check_cancellable (simple, cancellable);
1467 g_simple_async_result_set_op_res_gpointer (
1468 simple, async_context, (GDestroyNotify) async_context_free);
1470 g_simple_async_result_run_in_thread (
1471 simple, folder_synchronize_thread, io_priority, cancellable);
1473 g_object_unref (simple);
1477 folder_synchronize_finish (CamelFolder *folder,
1478 GAsyncResult *result,
1481 GSimpleAsyncResult *simple;
1483 g_return_val_if_fail (
1484 g_simple_async_result_is_valid (
1485 result, G_OBJECT (folder), folder_synchronize), FALSE);
1487 simple = G_SIMPLE_ASYNC_RESULT (result);
1489 /* Assume success unless a GError is set. */
1490 return !g_simple_async_result_propagate_error (simple, error);
1494 folder_synchronize_message_thread (GSimpleAsyncResult *simple,
1496 GCancellable *cancellable)
1498 AsyncContext *async_context;
1499 GError *error = NULL;
1501 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1503 camel_folder_synchronize_message_sync (
1504 CAMEL_FOLDER (object), async_context->message_uid,
1505 cancellable, &error);
1508 g_simple_async_result_take_error (simple, error);
1512 folder_synchronize_message (CamelFolder *folder,
1513 const gchar *message_uid,
1515 GCancellable *cancellable,
1516 GAsyncReadyCallback callback,
1519 GSimpleAsyncResult *simple;
1520 AsyncContext *async_context;
1522 async_context = g_slice_new0 (AsyncContext);
1523 async_context->message_uid = g_strdup (message_uid);
1525 simple = g_simple_async_result_new (
1526 G_OBJECT (folder), callback,
1527 user_data, folder_synchronize_message);
1529 g_simple_async_result_set_check_cancellable (simple, cancellable);
1531 g_simple_async_result_set_op_res_gpointer (
1532 simple, async_context, (GDestroyNotify) async_context_free);
1534 g_simple_async_result_run_in_thread (
1535 simple, folder_synchronize_message_thread,
1536 io_priority, cancellable);
1538 g_object_unref (simple);
1542 folder_synchronize_message_finish (CamelFolder *folder,
1543 GAsyncResult *result,
1546 GSimpleAsyncResult *simple;
1548 g_return_val_if_fail (
1549 g_simple_async_result_is_valid (
1550 result, G_OBJECT (folder),
1551 folder_synchronize_message), FALSE);
1553 simple = G_SIMPLE_ASYNC_RESULT (result);
1555 /* Assume success unless a GError is set. */
1556 return !g_simple_async_result_propagate_error (simple, error);
1560 folder_transfer_messages_to_thread (GSimpleAsyncResult *simple,
1562 GCancellable *cancellable)
1564 AsyncContext *async_context;
1565 GError *error = NULL;
1567 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1569 camel_folder_transfer_messages_to_sync (
1570 CAMEL_FOLDER (object), async_context->message_uids,
1571 async_context->destination, async_context->delete_originals,
1572 &async_context->transferred_uids, cancellable, &error);
1575 g_simple_async_result_take_error (simple, error);
1579 folder_transfer_messages_to (CamelFolder *source,
1580 GPtrArray *message_uids,
1581 CamelFolder *destination,
1582 gboolean delete_originals,
1584 GCancellable *cancellable,
1585 GAsyncReadyCallback callback,
1588 GSimpleAsyncResult *simple;
1589 AsyncContext *async_context;
1592 async_context = g_slice_new0 (AsyncContext);
1593 async_context->message_uids = g_ptr_array_new ();
1594 async_context->destination = g_object_ref (destination);
1595 async_context->delete_originals = delete_originals;
1597 for (ii = 0; ii < message_uids->len; ii++)
1599 async_context->message_uids,
1600 g_strdup (message_uids->pdata[ii]));
1602 simple = g_simple_async_result_new (
1603 G_OBJECT (source), callback,
1604 user_data, folder_transfer_messages_to);
1606 g_simple_async_result_set_check_cancellable (simple, cancellable);
1608 g_simple_async_result_set_op_res_gpointer (
1609 simple, async_context, (GDestroyNotify) async_context_free);
1611 g_simple_async_result_run_in_thread (
1612 simple, folder_transfer_messages_to_thread,
1613 io_priority, cancellable);
1615 g_object_unref (simple);
1619 folder_transfer_messages_to_finish (CamelFolder *source,
1620 GAsyncResult *result,
1621 GPtrArray **transferred_uids,
1624 GSimpleAsyncResult *simple;
1625 AsyncContext *async_context;
1627 g_return_val_if_fail (
1628 g_simple_async_result_is_valid (
1629 result, G_OBJECT (source),
1630 folder_transfer_messages_to), FALSE);
1632 simple = G_SIMPLE_ASYNC_RESULT (result);
1633 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1635 if (transferred_uids != NULL) {
1636 *transferred_uids = async_context->transferred_uids;
1637 async_context->transferred_uids = NULL;
1640 /* Assume success unless a GError is set. */
1641 return !g_simple_async_result_propagate_error (simple, error);
1644 /* Signal callback that stops emission when folder is frozen. */
1646 folder_changed (CamelFolder *folder,
1647 CamelFolderChangeInfo *info)
1649 CamelStore *parent_store;
1650 struct _CamelFolderChangeInfoPrivate *p = info->priv;
1651 CamelSession *session;
1652 CamelFilterDriver *driver = NULL;
1653 CamelJunkFilter *junk_filter;
1654 GPtrArray *junk = NULL;
1655 GPtrArray *notjunk = NULL;
1656 GPtrArray *recents = NULL;
1659 g_return_if_fail (info != NULL);
1661 parent_store = camel_folder_get_parent_store (folder);
1662 session = camel_service_get_session (CAMEL_SERVICE (parent_store));
1663 junk_filter = camel_session_get_junk_filter (session);
1665 camel_folder_lock (folder, CAMEL_FOLDER_CHANGE_LOCK);
1666 if (folder->priv->frozen) {
1667 camel_folder_change_info_cat (folder->priv->changed_frozen, info);
1668 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
1669 g_signal_stop_emission (folder, signals[CHANGED], 0);
1672 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
1674 if (junk_filter != NULL && info->uid_changed->len) {
1675 CamelMessageFlags flags;
1677 for (i = 0; i < info->uid_changed->len; i++) {
1678 flags = camel_folder_get_message_flags (folder, info->uid_changed->pdata[i]);
1679 if (flags & CAMEL_MESSAGE_JUNK_LEARN) {
1680 if (flags & CAMEL_MESSAGE_JUNK) {
1682 junk = g_ptr_array_new ();
1683 g_ptr_array_add (junk, g_strdup (info->uid_changed->pdata[i]));
1686 notjunk = g_ptr_array_new ();
1687 g_ptr_array_add (notjunk, g_strdup (info->uid_changed->pdata[i]));
1689 /* reset junk learn flag so that we don't process it again*/
1690 camel_folder_set_message_flags (
1691 folder, info->uid_changed->pdata[i],
1692 CAMEL_MESSAGE_JUNK_LEARN, 0);
1697 if ((folder->folder_flags & (CAMEL_FOLDER_FILTER_RECENT | CAMEL_FOLDER_FILTER_JUNK))
1698 && p->uid_filter->len > 0)
1699 driver = camel_session_get_filter_driver (
1701 (folder->folder_flags & CAMEL_FOLDER_FILTER_RECENT)
1702 ? "incoming" : "junktest", NULL);
1705 recents = g_ptr_array_new ();
1706 for (i = 0; i < p->uid_filter->len; i++)
1707 g_ptr_array_add (recents, g_strdup (p->uid_filter->pdata[i]));
1709 g_ptr_array_set_size (p->uid_filter, 0);
1712 if (driver || junk || notjunk) {
1713 FolderFilterData *data;
1715 data = g_slice_new0 (FolderFilterData);
1716 data->recents = recents;
1718 data->notjunk = notjunk;
1719 data->folder = g_object_ref (folder);
1720 data->driver = driver;
1722 camel_folder_freeze (folder);
1724 /* Copy changes back to changed_frozen list to retain
1725 * them while we are filtering */
1726 camel_folder_lock (folder, CAMEL_FOLDER_CHANGE_LOCK);
1727 camel_folder_change_info_cat (
1728 folder->priv->changed_frozen, info);
1729 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
1731 camel_session_submit_job (
1732 session, (CamelSessionCallback) folder_filter,
1733 data, (GDestroyNotify) folder_filter_data_free);
1735 g_signal_stop_emission (folder, signals[CHANGED], 0);
1740 camel_folder_class_init (CamelFolderClass *class)
1742 GObjectClass *object_class;
1744 g_type_class_add_private (class, sizeof (CamelFolderPrivate));
1746 object_class = G_OBJECT_CLASS (class);
1747 object_class->set_property = folder_set_property;
1748 object_class->get_property = folder_get_property;
1749 object_class->dispose = folder_dispose;
1750 object_class->finalize = folder_finalize;
1752 class->get_message_count = folder_get_message_count;
1753 class->get_permanent_flags = folder_get_permanent_flags;
1754 class->get_message_flags = folder_get_message_flags;
1755 class->set_message_flags = folder_set_message_flags;
1756 class->get_message_user_flag = folder_get_message_user_flag;
1757 class->set_message_user_flag = folder_set_message_user_flag;
1758 class->get_message_user_tag = folder_get_message_user_tag;
1759 class->set_message_user_tag = folder_set_message_user_tag;
1760 class->get_uids = folder_get_uids;
1761 class->get_uncached_uids = folder_get_uncached_uids;
1762 class->free_uids = folder_free_uids;
1763 class->cmp_uids = folder_cmp_uids;
1764 class->sort_uids = folder_sort_uids;
1765 class->get_summary = folder_get_summary;
1766 class->free_summary = folder_free_summary;
1767 class->search_free = folder_search_free;
1768 class->get_message_info = folder_get_message_info;
1769 class->ref_message_info = folder_ref_message_info;
1770 class->free_message_info = folder_free_message_info;
1771 class->delete_ = folder_delete;
1772 class->rename = folder_rename;
1773 class->freeze = folder_freeze;
1774 class->thaw = folder_thaw;
1775 class->is_frozen = folder_is_frozen;
1776 class->get_quota_info_sync = folder_get_quota_info_sync;
1777 class->refresh_info_sync = folder_refresh_info_sync;
1778 class->transfer_messages_to_sync = folder_transfer_messages_to_sync;
1779 class->changed = folder_changed;
1781 class->append_message = folder_append_message;
1782 class->append_message_finish = folder_append_message_finish;
1783 class->expunge = folder_expunge;
1784 class->expunge_finish = folder_expunge_finish;
1785 class->fetch_messages= fetch_messages;
1786 class->fetch_messages_finish = fetch_messages_finish;
1787 class->get_message = folder_get_message;
1788 class->get_message_finish = folder_get_message_finish;
1789 class->get_quota_info = folder_get_quota_info;
1790 class->get_quota_info_finish = folder_get_quota_info_finish;
1791 class->purge_message_cache= purge_message_cache;
1792 class->purge_message_cache_finish = purge_message_cache_finish;
1793 class->refresh_info = folder_refresh_info;
1794 class->refresh_info_finish = folder_refresh_info_finish;
1795 class->synchronize = folder_synchronize;
1796 class->synchronize_finish = folder_synchronize_finish;
1797 class->synchronize_message = folder_synchronize_message;
1798 class->synchronize_message_finish = folder_synchronize_message_finish;
1799 class->transfer_messages_to = folder_transfer_messages_to;
1800 class->transfer_messages_to_finish = folder_transfer_messages_to_finish;
1803 * CamelFolder:description
1805 * The folder's description.
1807 g_object_class_install_property (
1810 g_param_spec_string (
1813 "The folder's description",
1816 G_PARAM_CONSTRUCT));
1819 * CamelFolder:display-name
1821 * The folder's display name.
1823 g_object_class_install_property (
1826 g_param_spec_string (
1829 "The folder's display name",
1832 G_PARAM_CONSTRUCT));
1835 * CamelFolder:full-name
1837 * The folder's fully qualified name.
1839 g_object_class_install_property (
1842 g_param_spec_string (
1845 "The folder's fully qualified name",
1848 G_PARAM_CONSTRUCT));
1851 * CamelFolder:parent-store
1853 * The #CamelStore to which the folder belongs.
1855 g_object_class_install_property (
1858 g_param_spec_object (
1861 "The store to which the folder belongs",
1864 G_PARAM_CONSTRUCT_ONLY));
1867 * CamelFolder::changed
1868 * @folder: the #CamelFolder which emitted the signal
1870 signals[CHANGED] = g_signal_new (
1872 G_OBJECT_CLASS_TYPE (class),
1874 G_STRUCT_OFFSET (CamelFolderClass, changed),
1876 g_cclosure_marshal_VOID__POINTER,
1881 * CamelFolder::deleted
1882 * @folder: the #CamelFolder which emitted the signal
1884 signals[DELETED] = g_signal_new (
1886 G_OBJECT_CLASS_TYPE (class),
1888 G_STRUCT_OFFSET (CamelFolderClass, deleted),
1890 g_cclosure_marshal_VOID__VOID,
1894 * CamelFolder::renamed
1895 * @folder: the #CamelFolder which emitted the signal
1896 * @old_name: the previous folder name
1898 signals[RENAMED] = g_signal_new (
1900 G_OBJECT_CLASS_TYPE (class),
1902 G_STRUCT_OFFSET (CamelFolderClass, renamed),
1904 g_cclosure_marshal_VOID__STRING,
1910 camel_folder_init (CamelFolder *folder)
1912 folder->priv = CAMEL_FOLDER_GET_PRIVATE (folder);
1913 folder->priv->frozen = 0;
1914 folder->priv->changed_frozen = camel_folder_change_info_new ();
1916 g_rec_mutex_init (&folder->priv->lock);
1917 g_mutex_init (&folder->priv->change_lock);
1921 camel_folder_error_quark (void)
1923 static GQuark quark = 0;
1925 if (G_UNLIKELY (quark == 0)) {
1926 const gchar *string = "camel-folder-error-quark";
1927 quark = g_quark_from_static_string (string);
1934 * camel_folder_set_lock_async:
1935 * @folder: a #CamelFolder
1936 * @skip_folder_lock:
1938 * FIXME Document me!
1943 camel_folder_set_lock_async (CamelFolder *folder,
1944 gboolean skip_folder_lock)
1946 g_return_if_fail (CAMEL_IS_FOLDER (folder));
1948 folder->priv->skip_folder_lock = skip_folder_lock;
1952 * camel_folder_get_filename:
1957 camel_folder_get_filename (CamelFolder *folder,
1961 CamelFolderClass *class;
1964 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
1965 g_return_val_if_fail (uid != NULL, NULL);
1967 class = CAMEL_FOLDER_GET_CLASS (folder);
1968 g_return_val_if_fail (class->get_filename != NULL, NULL);
1970 filename = class->get_filename (folder, uid, error);
1971 CAMEL_CHECK_GERROR (folder, get_filename, filename != NULL, error);
1977 * camel_folder_get_full_name:
1978 * @folder: a #CamelFolder
1980 * Returns the fully qualified name of the folder.
1982 * Returns: the fully qualified name of the folder
1985 camel_folder_get_full_name (CamelFolder *folder)
1987 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
1989 return folder->priv->full_name;
1993 * camel_folder_set_full_name:
1994 * @folder: a #CamelFolder
1995 * @full_name: a fully qualified name for the folder
1997 * Sets the fully qualified name of the folder.
2002 camel_folder_set_full_name (CamelFolder *folder,
2003 const gchar *full_name)
2005 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2007 if (g_strcmp0 (folder->priv->full_name, full_name) == 0)
2010 g_free (folder->priv->full_name);
2011 folder->priv->full_name = g_strdup (full_name);
2013 g_object_notify (G_OBJECT (folder), "full-name");
2017 * camel_folder_get_display_name:
2018 * @folder: a #CamelFolder
2020 * Returns the display name for the folder. The fully qualified name
2021 * can be obtained with camel_folder_get_full_name().
2023 * Returns: the display name of the folder
2028 camel_folder_get_display_name (CamelFolder *folder)
2030 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2032 return folder->priv->display_name;
2036 * camel_folder_set_display_name:
2037 * @folder: a #CamelFolder
2038 * @display_name: a display name for the folder
2040 * Sets the display name for the folder.
2045 camel_folder_set_display_name (CamelFolder *folder,
2046 const gchar *display_name)
2048 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2050 if (g_strcmp0 (folder->priv->display_name, display_name) == 0)
2053 g_free (folder->priv->display_name);
2054 folder->priv->display_name = g_strdup (display_name);
2056 g_object_notify (G_OBJECT (folder), "display-name");
2060 * camel_folder_get_description:
2061 * @folder: a #CamelFolder
2063 * Returns a description of the folder suitable for displaying to the user.
2065 * Returns: a description of the folder
2070 camel_folder_get_description (CamelFolder *folder)
2072 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2074 /* Default to full-name if there's no custom description. */
2075 if (folder->priv->description == NULL)
2076 return camel_folder_get_full_name (folder);
2078 return folder->priv->description;
2082 * camel_folder_set_description:
2083 * @folder: a #CamelFolder
2084 * @description: a description of the folder
2086 * Sets a description of the folder suitable for displaying to the user.
2091 camel_folder_set_description (CamelFolder *folder,
2092 const gchar *description)
2094 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2096 if (g_strcmp0 (folder->priv->description, description) == 0)
2099 g_free (folder->priv->description);
2100 folder->priv->description = g_strdup (description);
2102 g_object_notify (G_OBJECT (folder), "description");
2106 * camel_folder_get_parent_store:
2107 * @folder: a #CamelFolder
2109 * Returns: the parent #CamelStore of the folder
2112 camel_folder_get_parent_store (CamelFolder *folder)
2114 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2116 return CAMEL_STORE (folder->priv->parent_store);
2120 * camel_folder_get_message_count:
2121 * @folder: a #CamelFolder
2123 * Returns: the number of messages in the folder, or %-1 if unknown
2126 camel_folder_get_message_count (CamelFolder *folder)
2128 CamelFolderClass *class;
2130 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
2132 class = CAMEL_FOLDER_GET_CLASS (folder);
2133 g_return_val_if_fail (class->get_message_count != NULL, -1);
2135 return class->get_message_count (folder);
2139 * camel_folder_get_unread_message_count:
2140 * @folder: a #CamelFolder
2142 * DEPRECATED: use camel_object_get() instead.
2144 * Returns: the number of unread messages in the folder, or %-1 if
2148 camel_folder_get_unread_message_count (CamelFolder *folder)
2150 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
2151 g_return_val_if_fail (folder->summary != NULL, -1);
2153 return camel_folder_summary_get_unread_count (folder->summary);
2157 * camel_folder_get_deleted_message_count:
2158 * @folder: a #CamelFolder
2160 * Returns: the number of deleted messages in the folder, or %-1 if
2164 camel_folder_get_deleted_message_count (CamelFolder *folder)
2166 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
2167 g_return_val_if_fail (folder->summary != NULL, -1);
2169 return camel_folder_summary_get_deleted_count (folder->summary);
2173 * camel_folder_get_permanent_flags:
2174 * @folder: a #CamelFolder
2176 * Returns: the set of #CamelMessageFlags that can be permanently
2177 * stored on a message between sessions. If it includes
2178 * #CAMEL_FLAG_USER, then user-defined flags will be remembered.
2181 camel_folder_get_permanent_flags (CamelFolder *folder)
2183 CamelFolderClass *class;
2185 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
2187 class = CAMEL_FOLDER_GET_CLASS (folder);
2188 g_return_val_if_fail (class->get_permanent_flags != NULL, 0);
2190 return class->get_permanent_flags (folder);
2194 * camel_folder_get_message_flags:
2195 * @folder: a #CamelFolder
2196 * @uid: the UID of a message in @folder
2198 * Deprecated: Use camel_folder_get_message_info() instead.
2200 * Returns: the #CamelMessageFlags that are set on the indicated
2204 camel_folder_get_message_flags (CamelFolder *folder,
2207 CamelFolderClass *class;
2209 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
2210 g_return_val_if_fail (uid != NULL, 0);
2212 class = CAMEL_FOLDER_GET_CLASS (folder);
2213 g_return_val_if_fail (class->get_message_flags != NULL, 0);
2215 return class->get_message_flags (folder, uid);
2219 * camel_folder_set_message_flags:
2220 * @folder: a #CamelFolder
2221 * @uid: the UID of a message in @folder
2222 * @flags: a set of #CamelMessageFlag values to set
2223 * @set: the mask of values in @flags to use.
2225 * Sets those flags specified by @flags to the values specified by @set
2226 * on the indicated message. (This may or may not persist after the
2227 * folder or store is closed. See camel_folder_get_permanent_flags())
2229 * E.g. to set the deleted flag and clear the draft flag, use
2230 * camel_folder_set_message_flags (folder, uid, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_DRAFT, CAMEL_MESSAGE_DELETED);
2232 * DEPRECATED: Use camel_message_info_set_flags() on the message info directly
2235 * Returns: %TRUE if the flags were changed or %FALSE otherwise
2238 camel_folder_set_message_flags (CamelFolder *folder,
2240 CamelMessageFlags flags,
2241 CamelMessageFlags set)
2243 CamelFolderClass *class;
2245 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
2246 g_return_val_if_fail (uid != NULL, FALSE);
2248 class = CAMEL_FOLDER_GET_CLASS (folder);
2249 g_return_val_if_fail (class->set_message_flags != NULL, FALSE);
2251 if ((flags & (CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_JUNK_LEARN)) == CAMEL_MESSAGE_JUNK) {
2252 flags |= CAMEL_MESSAGE_JUNK_LEARN;
2253 set &= ~CAMEL_MESSAGE_JUNK_LEARN;
2256 return class->set_message_flags (folder, uid, flags, set);
2260 * camel_folder_get_message_user_flag:
2261 * @folder: a #CamelFolder
2262 * @uid: the UID of a message in @folder
2263 * @name: the name of a user flag
2265 * DEPRECATED: Use camel_message_info_get_user_flag() on the message
2268 * Returns: %TRUE if the given user flag is set on the message or
2272 camel_folder_get_message_user_flag (CamelFolder *folder,
2276 CamelFolderClass *class;
2278 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
2279 g_return_val_if_fail (uid != NULL, 0);
2280 g_return_val_if_fail (name != NULL, 0);
2282 class = CAMEL_FOLDER_GET_CLASS (folder);
2283 g_return_val_if_fail (class->get_message_user_flag != NULL, 0);
2285 return class->get_message_user_flag (folder, uid, name);
2289 * camel_folder_set_message_user_flag:
2290 * @folder: a #CamelFolder
2291 * @uid: the UID of a message in @folder
2292 * @name: the name of the user flag to set
2293 * @value: the value to set it to
2295 * DEPRECATED: Use camel_message_info_set_user_flag() on the
2296 * #CamelMessageInfo directly (when it works)
2298 * Sets the user flag specified by @name to the value specified by @value
2299 * on the indicated message. (This may or may not persist after the
2300 * folder or store is closed. See camel_folder_get_permanent_flags())
2303 camel_folder_set_message_user_flag (CamelFolder *folder,
2308 CamelFolderClass *class;
2310 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2311 g_return_if_fail (uid != NULL);
2312 g_return_if_fail (name != NULL);
2314 class = CAMEL_FOLDER_GET_CLASS (folder);
2315 g_return_if_fail (class->set_message_user_flag != NULL);
2317 class->set_message_user_flag (folder, uid, name, value);
2321 * camel_folder_get_message_user_tag:
2322 * @folder: a #CamelFolder
2323 * @uid: the UID of a message in @folder
2324 * @name: the name of a user tag
2326 * DEPRECATED: Use camel_message_info_get_user_tag() on the
2327 * #CamelMessageInfo directly.
2329 * Returns: the value of the user tag
2332 camel_folder_get_message_user_tag (CamelFolder *folder,
2336 CamelFolderClass *class;
2338 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2339 g_return_val_if_fail (uid != NULL, NULL);
2340 g_return_val_if_fail (name != NULL, NULL);
2342 class = CAMEL_FOLDER_GET_CLASS (folder);
2343 g_return_val_if_fail (class->get_message_user_tag != NULL, NULL);
2345 /* FIXME: should duplicate string */
2346 return class->get_message_user_tag (folder, uid, name);
2350 * camel_folder_set_message_user_tag:
2351 * @folder: a #CamelFolder
2352 * @uid: the UID of a message in @folder
2353 * @name: the name of the user tag to set
2354 * @value: the value to set it to
2356 * DEPRECATED: Use camel_message_info_set_user_tag() on the
2357 * #CamelMessageInfo directly (when it works).
2359 * Sets the user tag specified by @name to the value specified by @value
2360 * on the indicated message. (This may or may not persist after the
2361 * folder or store is closed. See camel_folder_get_permanent_flags())
2364 camel_folder_set_message_user_tag (CamelFolder *folder,
2369 CamelFolderClass *class;
2371 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2372 g_return_if_fail (uid != NULL);
2373 g_return_if_fail (name != NULL);
2375 class = CAMEL_FOLDER_GET_CLASS (folder);
2376 g_return_if_fail (class->set_message_user_tag != NULL);
2378 class->set_message_user_tag (folder, uid, name, value);
2382 * camel_folder_get_message_info:
2383 * @folder: a #CamelFolder
2384 * @uid: the uid of a message
2386 * Retrieve the #CamelMessageInfo for the specified @uid. This return
2387 * must be freed using camel_folder_free_message_info().
2389 * Returns: the summary information for the indicated message, or %NULL
2390 * if the uid does not exist
2393 camel_folder_get_message_info (CamelFolder *folder,
2396 CamelFolderClass *class;
2398 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2399 g_return_val_if_fail (uid != NULL, NULL);
2401 class = CAMEL_FOLDER_GET_CLASS (folder);
2402 g_return_val_if_fail (class->get_message_info != NULL, NULL);
2404 return class->get_message_info (folder, uid);
2408 * camel_folder_free_message_info:
2409 * @folder: a #CamelFolder
2410 * @info: a #CamelMessageInfo
2412 * Free (unref) a #CamelMessageInfo, previously obtained with
2413 * camel_folder_get_message_info().
2416 camel_folder_free_message_info (CamelFolder *folder,
2417 CamelMessageInfo *info)
2419 CamelFolderClass *class;
2421 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2422 g_return_if_fail (info != NULL);
2424 class = CAMEL_FOLDER_GET_CLASS (folder);
2425 g_return_if_fail (class->free_message_info != NULL);
2427 class->free_message_info (folder, info);
2431 * camel_folder_ref_message_info:
2432 * @folder: a #CamelFolder
2433 * @info: a #CamelMessageInfo
2435 * DEPRECATED: Use camel_message_info_ref() directly.
2437 * Ref a #CamelMessageInfo, previously obtained with
2438 * camel_folder_get_message_info().
2441 camel_folder_ref_message_info (CamelFolder *folder,
2442 CamelMessageInfo *info)
2444 CamelFolderClass *class;
2446 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2447 g_return_if_fail (info != NULL);
2449 class = CAMEL_FOLDER_GET_CLASS (folder);
2450 g_return_if_fail (class->ref_message_info != NULL);
2452 class->ref_message_info (folder, info);
2455 /* TODO: is this function required anyway? */
2457 * camel_folder_has_summary_capability:
2458 * @folder: a #CamelFolder
2460 * Get whether or not the folder has a summary.
2462 * Returns: %TRUE if a summary is available or %FALSE otherwise
2465 camel_folder_has_summary_capability (CamelFolder *folder)
2467 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
2469 return folder->folder_flags & CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY;
2475 * camel_folder_get_uids:
2476 * @folder: a #CamelFolder
2478 * Get the list of UIDs available in a folder. This routine is useful
2479 * for finding what messages are available when the folder does not
2480 * support summaries. The returned array should not be modified, and
2481 * must be freed by passing it to camel_folder_free_uids().
2483 * Returns: a GPtrArray of UIDs corresponding to the messages available
2487 camel_folder_get_uids (CamelFolder *folder)
2489 CamelFolderClass *class;
2491 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2493 class = CAMEL_FOLDER_GET_CLASS (folder);
2494 g_return_val_if_fail (class->get_uids != NULL, NULL);
2496 return class->get_uids (folder);
2500 * camel_folder_free_uids:
2501 * @folder: a #CamelFolder
2502 * @array: the array of uids to free
2504 * Frees the array of UIDs returned by camel_folder_get_uids().
2507 camel_folder_free_uids (CamelFolder *folder,
2510 CamelFolderClass *class;
2512 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2513 g_return_if_fail (array != NULL);
2515 class = CAMEL_FOLDER_GET_CLASS (folder);
2516 g_return_if_fail (class->free_uids != NULL);
2518 class->free_uids (folder, array);
2522 * camel_folder_get_uncached_uids:
2523 * @folder: a #CamelFolder
2524 * @uids: the array of uids to filter down to uncached ones.
2526 * Returns the known-uncached uids from a list of uids. It may return uids
2527 * which are locally cached but should never filter out a uid which is not
2528 * locally cached. Free the result by called camel_folder_free_uids().
2529 * Frees the array of UIDs returned by camel_folder_get_uids().
2534 camel_folder_get_uncached_uids (CamelFolder *folder,
2538 CamelFolderClass *class;
2539 GPtrArray *uncached_uids;
2541 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2542 g_return_val_if_fail (uids != NULL, NULL);
2544 class = CAMEL_FOLDER_GET_CLASS (folder);
2545 g_return_val_if_fail (class->get_uncached_uids != NULL, NULL);
2547 uncached_uids = class->get_uncached_uids (folder, uids, error);
2548 CAMEL_CHECK_GERROR (folder, get_uncached_uids, uncached_uids != NULL, error);
2550 return uncached_uids;
2554 * camel_folder_cmp_uids:
2555 * @folder: a #CamelFolder
2556 * @uid1: The first uid.
2557 * @uid2: the second uid.
2559 * Compares two uids. The return value meaning is the same as in any other compare function.
2561 * Note that the default compare function expects a decimal number at the beginning of a uid,
2562 * thus if provider uses different uid values, then it should subclass this function.
2567 camel_folder_cmp_uids (CamelFolder *folder,
2571 CamelFolderClass *class;
2573 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
2574 g_return_val_if_fail (uid1 != NULL, 0);
2575 g_return_val_if_fail (uid2 != NULL, 0);
2577 class = CAMEL_FOLDER_GET_CLASS (folder);
2578 g_return_val_if_fail (class->cmp_uids != NULL, 0);
2580 return class->cmp_uids (folder, uid1, uid2);
2584 * camel_folder_sort_uids:
2585 * @folder: a #CamelFolder
2586 * @uids: array of uids
2588 * Sorts the array of UIDs.
2593 camel_folder_sort_uids (CamelFolder *folder,
2596 CamelFolderClass *class;
2598 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2599 g_return_if_fail (uids != NULL);
2601 class = CAMEL_FOLDER_GET_CLASS (folder);
2602 g_return_if_fail (class->sort_uids != NULL);
2604 class->sort_uids (folder, uids);
2608 * camel_folder_get_summary:
2609 * @folder: a #CamelFolder
2611 * This returns the summary information for the folder. This array
2612 * should not be modified, and must be freed with
2613 * camel_folder_free_summary().
2615 * Returns: an array of #CamelMessageInfo
2618 camel_folder_get_summary (CamelFolder *folder)
2620 CamelFolderClass *class;
2622 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2624 class = CAMEL_FOLDER_GET_CLASS (folder);
2625 g_return_val_if_fail (class->get_summary != NULL, NULL);
2627 return class->get_summary (folder);
2631 * camel_folder_free_summary:
2632 * @folder: a #CamelFolder
2633 * @array: the summary array to free
2635 * Frees the summary array returned by camel_folder_get_summary().
2638 camel_folder_free_summary (CamelFolder *folder,
2641 CamelFolderClass *class;
2643 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2644 g_return_if_fail (array != NULL);
2646 class = CAMEL_FOLDER_GET_CLASS (folder);
2647 g_return_if_fail (class->free_summary != NULL);
2649 class->free_summary (folder, array);
2653 * camel_folder_search_by_expression:
2654 * @folder: a #CamelFolder
2655 * @expr: a search expression
2656 * @cancellable: a #GCancellable
2657 * @error: return location for a #GError, or %NULL
2659 * Searches the folder for messages matching the given search expression.
2661 * Returns: a #GPtrArray of uids of matching messages. The caller must
2662 * free the list and each of the elements when it is done.
2665 camel_folder_search_by_expression (CamelFolder *folder,
2666 const gchar *expression,
2667 GCancellable *cancellable,
2670 CamelFolderClass *class;
2673 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2675 class = CAMEL_FOLDER_GET_CLASS (folder);
2676 g_return_val_if_fail (class->search_by_expression != NULL, NULL);
2678 /* NOTE: that it is upto the callee to CAMEL_FOLDER_REC_LOCK */
2680 matches = class->search_by_expression (folder, expression, cancellable, error);
2681 CAMEL_CHECK_GERROR (folder, search_by_expression, matches != NULL, error);
2687 * camel_folder_count_by_expression:
2688 * @folder: a #CamelFolder
2689 * @expression: a search expression
2690 * @cancellable: a #GCancellable
2691 * @error: return location for a #GError, or %NULL
2693 * Searches the folder for count of messages matching the given search expression.
2695 * Returns: an interger
2700 camel_folder_count_by_expression (CamelFolder *folder,
2701 const gchar *expression,
2702 GCancellable *cancellable,
2705 CamelFolderClass *class;
2707 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
2709 class = CAMEL_FOLDER_GET_CLASS (folder);
2710 g_return_val_if_fail (class->count_by_expression != NULL, 0);
2712 /* NOTE: that it is upto the callee to CAMEL_FOLDER_REC_LOCK */
2714 return class->count_by_expression (folder, expression, cancellable, error);
2718 * camel_folder_search_by_uids:
2719 * @folder: a #CamelFolder
2720 * @expr: search expression
2721 * @uids: array of uid's to match against.
2722 * @cancellable: a #GCancellable
2723 * @error: return location for a #GError, or %NULL
2725 * Search a subset of uid's for an expression match.
2727 * Returns: a #GPtrArray of uids of matching messages. The caller must
2728 * free the list and each of the elements when it is done.
2731 camel_folder_search_by_uids (CamelFolder *folder,
2734 GCancellable *cancellable,
2737 CamelFolderClass *class;
2740 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2742 class = CAMEL_FOLDER_GET_CLASS (folder);
2743 g_return_val_if_fail (class->search_by_uids != NULL, NULL);
2745 /* NOTE: that it is upto the callee to CAMEL_FOLDER_REC_LOCK */
2747 matches = class->search_by_uids (folder, expr, uids, cancellable, error);
2748 CAMEL_CHECK_GERROR (folder, search_by_uids, matches != NULL, error);
2754 * camel_folder_search_free:
2755 * @folder: a #CamelFolder
2756 * @result: search results to free
2758 * Free the result of a search as gotten by camel_folder_search() or
2759 * camel_folder_search_by_uids().
2762 camel_folder_search_free (CamelFolder *folder,
2765 CamelFolderClass *class;
2767 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2768 g_return_if_fail (result != NULL);
2770 class = CAMEL_FOLDER_GET_CLASS (folder);
2771 g_return_if_fail (class->search_free != NULL);
2773 /* NOTE: upto the callee to CAMEL_FOLDER_REC_LOCK */
2775 class->search_free (folder, result);
2779 * camel_folder_delete:
2780 * @folder: a #CamelFolder
2782 * Marks @folder as deleted and performs any required cleanup.
2784 * This also emits the #CamelFolder::deleted signal from an idle source on
2785 * the main loop. The idle source's priority is #G_PRIORITY_DEFAULT_IDLE.
2788 camel_folder_delete (CamelFolder *folder)
2790 CamelFolderClass *class;
2791 CamelStore *parent_store;
2792 CamelService *service;
2793 CamelSession *session;
2794 SignalData *signal_data;
2795 const gchar *full_name;
2797 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2799 class = CAMEL_FOLDER_GET_CLASS (folder);
2800 g_return_if_fail (class->delete_ != NULL);
2802 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
2803 if (folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED) {
2804 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
2808 folder->folder_flags |= CAMEL_FOLDER_HAS_BEEN_DELETED;
2810 class->delete_ (folder);
2812 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
2814 /* Delete the references of the folder from the DB.*/
2815 full_name = camel_folder_get_full_name (folder);
2816 parent_store = camel_folder_get_parent_store (folder);
2817 camel_db_delete_folder (parent_store->cdb_w, full_name, NULL);
2819 service = CAMEL_SERVICE (parent_store);
2820 session = camel_service_get_session (service);
2822 signal_data = g_slice_new0 (SignalData);
2823 signal_data->folder = g_object_ref (folder);
2825 camel_session_idle_add (
2826 session, G_PRIORITY_DEFAULT_IDLE,
2827 folder_emit_deleted_cb,
2828 signal_data, (GDestroyNotify) signal_data_free);
2832 * camel_folder_rename:
2833 * @folder: a #CamelFolder
2834 * @new_name: new name for the folder
2836 * Marks @folder as renamed.
2838 * This also emits the #CamelFolder::renamed signal from an idle source on
2839 * the main loop. The idle source's priority is #G_PRIORITY_DEFAULT_IDLE.
2841 * NOTE: This is an internal function used by camel stores, no locking
2842 * is performed on the folder.
2845 camel_folder_rename (CamelFolder *folder,
2846 const gchar *new_name)
2848 CamelFolderClass *class;
2849 CamelStore *parent_store;
2850 CamelService *service;
2851 CamelSession *session;
2852 SignalData *signal_data;
2855 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2856 g_return_if_fail (new_name != NULL);
2858 class = CAMEL_FOLDER_GET_CLASS (folder);
2859 g_return_if_fail (class->rename != NULL);
2861 old_name = g_strdup (camel_folder_get_full_name (folder));
2863 class->rename (folder, new_name);
2865 parent_store = camel_folder_get_parent_store (folder);
2866 camel_db_rename_folder (parent_store->cdb_w, old_name, new_name, NULL);
2868 service = CAMEL_SERVICE (parent_store);
2869 session = camel_service_get_session (service);
2871 signal_data = g_slice_new0 (SignalData);
2872 signal_data->folder = g_object_ref (folder);
2873 signal_data->folder_name = old_name; /* transfer ownership */
2875 camel_session_idle_add (
2876 session, G_PRIORITY_DEFAULT_IDLE,
2877 folder_emit_renamed_cb,
2878 signal_data, (GDestroyNotify) signal_data_free);
2882 * camel_folder_changed:
2883 * @folder: a #CamelFolder
2884 * @changes: change information for @folder
2886 * Emits the #CamelFolder::changed signal from an idle source on the
2887 * main loop. The idle source's priority is #G_PRIORITY_LOW.
2892 camel_folder_changed (CamelFolder *folder,
2893 CamelFolderChangeInfo *changes)
2895 CamelFolderChangeInfo *pending_changes;
2897 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2898 g_return_if_fail (changes != NULL);
2900 if (camel_folder_is_frozen (folder)) {
2901 /* folder_changed() will catch this case and pile
2902 * the changes into folder->changed_frozen */
2903 g_signal_emit (folder, signals[CHANGED], 0, changes);
2907 /* If a "changed" signal has already been scheduled but not yet
2908 * emitted, just append our changes to the pending changes, and
2909 * skip scheduling our own "changed" signal. This helps to cut
2910 * down on the frequency of signal emissions so virtual folders
2911 * won't have to work so hard. */
2913 camel_folder_lock (folder, CAMEL_FOLDER_CHANGE_LOCK);
2915 pending_changes = folder->priv->pending_changes;
2917 if (pending_changes == NULL) {
2918 CamelStore *parent_store;
2919 CamelService *service;
2920 CamelSession *session;
2921 SignalData *signal_data;
2923 parent_store = camel_folder_get_parent_store (folder);
2925 service = CAMEL_SERVICE (parent_store);
2926 session = camel_service_get_session (service);
2928 pending_changes = camel_folder_change_info_new ();
2929 folder->priv->pending_changes = pending_changes;
2931 signal_data = g_slice_new0 (SignalData);
2932 signal_data->folder = g_object_ref (folder);
2934 camel_session_idle_add (
2935 session, G_PRIORITY_LOW,
2936 folder_emit_changed_cb,
2937 signal_data, (GDestroyNotify) signal_data_free);
2940 camel_folder_change_info_cat (pending_changes, changes);
2942 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
2946 * camel_folder_freeze:
2947 * @folder: a #CamelFolder
2949 * Freezes the folder so that a series of operation can be performed
2950 * without "folder_changed" signals being emitted. When the folder is
2951 * later thawed with camel_folder_thaw(), the suppressed signals will
2955 camel_folder_freeze (CamelFolder *folder)
2957 CamelFolderClass *class;
2959 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2961 class = CAMEL_FOLDER_GET_CLASS (folder);
2962 g_return_if_fail (class->freeze != NULL);
2964 class->freeze (folder);
2968 * camel_folder_thaw:
2969 * @folder: a #CamelFolder
2971 * Thaws the folder and emits any pending folder_changed
2975 camel_folder_thaw (CamelFolder *folder)
2977 CamelFolderClass *class;
2979 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2980 g_return_if_fail (folder->priv->frozen != 0);
2982 class = CAMEL_FOLDER_GET_CLASS (folder);
2983 g_return_if_fail (class->thaw != NULL);
2985 class->thaw (folder);
2989 * camel_folder_is_frozen:
2990 * @folder: a #CamelFolder
2992 * Returns: whether or not the folder is frozen
2995 camel_folder_is_frozen (CamelFolder *folder)
2997 CamelFolderClass *class;
2999 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3001 class = CAMEL_FOLDER_GET_CLASS (folder);
3002 g_return_val_if_fail (class->is_frozen != NULL, FALSE);
3004 return class->is_frozen (folder);
3008 * camel_folder_get_frozen_count:
3009 * @folder: a #CamelFolder
3014 camel_folder_get_frozen_count (CamelFolder *folder)
3016 /* FIXME This function shouldn't be needed,
3017 * but it's used in CamelVeeFolder */
3018 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
3020 return folder->priv->frozen;
3024 * camel_folder_quota_info_new:
3025 * @name: Name of the quota.
3026 * @used: Current usage of the quota.
3027 * @total: Total available size of the quota.
3029 * Returns: newly allocated #CamelFolderQuotaInfo structure with
3030 * initialized values based on the parameters, with next member set to NULL.
3034 CamelFolderQuotaInfo *
3035 camel_folder_quota_info_new (const gchar *name,
3039 CamelFolderQuotaInfo *info;
3041 info = g_malloc0 (sizeof (CamelFolderQuotaInfo));
3042 info->name = g_strdup (name);
3044 info->total = total;
3051 * camel_folder_quota_info_clone:
3052 * @info: a #CamelFolderQuotaInfo object to clone.
3054 * Makes a copy of the given info and all next-s.
3058 CamelFolderQuotaInfo *
3059 camel_folder_quota_info_clone (const CamelFolderQuotaInfo *info)
3061 CamelFolderQuotaInfo *clone = NULL, *last = NULL;
3062 const CamelFolderQuotaInfo *iter;
3064 for (iter = info; iter != NULL; iter = iter->next) {
3065 CamelFolderQuotaInfo *n = camel_folder_quota_info_new (iter->name, iter->used, iter->total);
3079 * camel_folder_quota_info_free:
3080 * @info: a #CamelFolderQuotaInfo object to free.
3082 * Frees this and all next objects.
3087 camel_folder_quota_info_free (CamelFolderQuotaInfo *info)
3089 CamelFolderQuotaInfo *next = info;
3095 g_free (info->name);
3101 * camel_folder_free_nop:
3102 * @folder: a #CamelFolder
3103 * @array: an array of uids or #CamelMessageInfo
3105 * "Frees" the provided array by doing nothing. Used by #CamelFolder
3106 * subclasses as an implementation for free_uids, or free_summary when
3107 * the returned array is "static" information and should not be freed.
3110 camel_folder_free_nop (CamelFolder *folder,
3117 * camel_folder_free_shallow:
3118 * @folder: a #CamelFolder
3119 * @array: an array of uids or #CamelMessageInfo
3121 * Frees the provided array but not its contents. Used by #CamelFolder
3122 * subclasses as an implementation for free_uids or free_summary when
3123 * the returned array needs to be freed but its contents come from
3124 * "static" information.
3127 camel_folder_free_shallow (CamelFolder *folder,
3130 g_ptr_array_free (array, TRUE);
3134 * camel_folder_free_deep:
3135 * @folder: a #CamelFolder
3136 * @array: an array of uids
3138 * Frees the provided array and its contents. Used by #CamelFolder
3139 * subclasses as an implementation for free_uids when the provided
3140 * information was created explicitly by the corresponding get_ call.
3143 camel_folder_free_deep (CamelFolder *folder,
3148 g_return_if_fail (array != NULL);
3150 for (i = 0; i < array->len; i++)
3151 g_free (array->pdata[i]);
3152 g_ptr_array_free (array, TRUE);
3156 * camel_folder_lock:
3157 * @folder: a #CamelFolder
3158 * @lock: lock type to lock
3160 * Locks @folder's @lock. Unlock it with camel_folder_unlock().
3165 camel_folder_lock (CamelFolder *folder,
3166 CamelFolderLock lock)
3168 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3171 case CAMEL_FOLDER_CHANGE_LOCK:
3172 g_mutex_lock (&folder->priv->change_lock);
3174 case CAMEL_FOLDER_REC_LOCK:
3175 if (folder->priv->skip_folder_lock == FALSE)
3176 g_rec_mutex_lock (&folder->priv->lock);
3179 g_return_if_reached ();
3184 * camel_folder_unlock:
3185 * @folder: a #CamelFolder
3186 * @lock: lock type to unlock
3188 * Unlocks @folder's @lock, previously locked with camel_folder_lock().
3193 camel_folder_unlock (CamelFolder *folder,
3194 CamelFolderLock lock)
3196 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3199 case CAMEL_FOLDER_CHANGE_LOCK:
3200 g_mutex_unlock (&folder->priv->change_lock);
3202 case CAMEL_FOLDER_REC_LOCK:
3203 if (folder->priv->skip_folder_lock == FALSE)
3204 g_rec_mutex_unlock (&folder->priv->lock);
3207 g_return_if_reached ();
3212 * camel_folder_append_message_sync:
3213 * @folder: a #CamelFolder
3214 * @message: a #CamelMimeMessage
3215 * @info: a #CamelMessageInfo with additional flags/etc to set on the
3216 * new message, or %NULL
3217 * @appended_uid: if non-%NULL, the UID of the appended message will
3218 * be returned here, if it is known
3219 * @cancellable: optional #GCancellable object, or %NULL
3220 * @error: return location for a #GError, or %NULL
3222 * Appends @message to @folder. Only the flag and tag data from @info
3223 * are used. If @info is %NULL, no flags or tags will be set.
3225 * Returns: %TRUE on success, %FALSE on error
3230 camel_folder_append_message_sync (CamelFolder *folder,
3231 CamelMimeMessage *message,
3232 CamelMessageInfo *info,
3233 gchar **appended_uid,
3234 GCancellable *cancellable,
3237 CamelFolderClass *class;
3240 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3241 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
3243 class = CAMEL_FOLDER_GET_CLASS (folder);
3244 g_return_val_if_fail (class->append_message_sync != NULL, FALSE);
3246 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
3248 /* Check for cancellation after locking. */
3249 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
3250 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3254 success = class->append_message_sync (
3255 folder, message, info, appended_uid, cancellable, error);
3256 CAMEL_CHECK_GERROR (folder, append_message_sync, success, error);
3258 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3264 * camel_folder_append_message:
3265 * @folder a #CamelFolder
3266 * @message: a #CamelMimeMessage
3267 * @info: a #CamelMessageInfo with additional flags/etc to set on the
3268 * new message, or %NULL
3269 * @io_priority: the I/O priority of the request
3270 * @cancellable: optional #GCancellable object, or %NULL
3271 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3272 * @user_data: data to pass to the callback function
3274 * Appends @message to @folder asynchronously. Only the flag and tag data
3275 * from @info are used. If @info is %NULL, no flags or tags will be set.
3277 * When the operation is finished, @callback will be called. You can
3278 * then call camel_folder_append_message_finish() to get the result of
3284 camel_folder_append_message (CamelFolder *folder,
3285 CamelMimeMessage *message,
3286 CamelMessageInfo *info,
3288 GCancellable *cancellable,
3289 GAsyncReadyCallback callback,
3292 CamelFolderClass *class;
3294 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3295 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
3297 class = CAMEL_FOLDER_GET_CLASS (folder);
3298 g_return_if_fail (class->append_message != NULL);
3300 class->append_message (
3301 folder, message, info, io_priority,
3302 cancellable, callback, user_data);
3306 * camel_folder_append_message_finish:
3307 * @folder: a #CamelFolder
3308 * @result: a #GAsyncResult
3309 * @appended_uid: if non-%NULL, the UID of the appended message will
3310 * be returned here, if it is known
3311 * @error: return location for a #GError, or %NULL
3313 * Finishes the operation started with camel_folder_append_message_finish().
3315 * Returns: %TRUE on success, %FALSE on error
3320 camel_folder_append_message_finish (CamelFolder *folder,
3321 GAsyncResult *result,
3322 gchar **appended_uid,
3325 CamelFolderClass *class;
3327 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3328 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
3330 class = CAMEL_FOLDER_GET_CLASS (folder);
3331 g_return_val_if_fail (class->append_message_finish != NULL, FALSE);
3333 return class->append_message_finish (
3334 folder, result, appended_uid, error);
3338 * camel_folder_expunge_sync:
3339 * @folder: a #CamelFolder
3340 * @cancellable: optional #GCancellable object, or %NULL
3341 * @error: return location for a #GError, or %NULL
3343 * Deletes messages which have been marked as "DELETED".
3345 * Returns: %TRUE on success, %FALSE on error
3350 camel_folder_expunge_sync (CamelFolder *folder,
3351 GCancellable *cancellable,
3354 CamelFolderClass *class;
3355 const gchar *display_name;
3356 const gchar *message;
3357 gboolean success = TRUE;
3359 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3361 class = CAMEL_FOLDER_GET_CLASS (folder);
3362 g_return_val_if_fail (class->expunge_sync != NULL, FALSE);
3364 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
3366 /* Check for cancellation after locking. */
3367 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
3368 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3372 message = _("Expunging folder '%s'");
3373 display_name = camel_folder_get_display_name (folder);
3374 camel_operation_push_message (cancellable, message, display_name);
3376 if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED)) {
3377 success = class->expunge_sync (folder, cancellable, error);
3378 CAMEL_CHECK_GERROR (folder, expunge_sync, success, error);
3381 camel_operation_pop_message (cancellable);
3383 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3389 * camel_folder_expunge:
3390 * @folder: a #CamelFolder
3391 * @io_priority: the I/O priority of the request
3392 * @cancellable: optional #GCancellable object, or %NULL
3393 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3394 * @user_data: data to pass to the callback function
3396 * Asynchronously deletes messages which have been marked as "DELETED".
3398 * When the operation is finished, @callback will be called. You can then
3399 * call camel_folder_expunge_finish() to get the result of the operation.
3404 camel_folder_expunge (CamelFolder *folder,
3406 GCancellable *cancellable,
3407 GAsyncReadyCallback callback,
3410 CamelFolderClass *class;
3412 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3414 class = CAMEL_FOLDER_GET_CLASS (folder);
3415 g_return_if_fail (class->expunge != NULL);
3417 class->expunge (folder, io_priority, cancellable, callback, user_data);
3421 * camel_folder_expunge_finish:
3422 * @folder: a #CamelFolder
3423 * @result: a #GAsyncResult
3424 * @error: return location for a #GError, or %NULL
3426 * Finishes the operation started with camel_folder_expunge().
3428 * Returns: %TRUE on success, %FALSE on error
3433 camel_folder_expunge_finish (CamelFolder *folder,
3434 GAsyncResult *result,
3437 CamelFolderClass *class;
3439 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3440 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
3442 class = CAMEL_FOLDER_GET_CLASS (folder);
3443 g_return_val_if_fail (class->expunge_finish != NULL, FALSE);
3445 return class->expunge_finish (folder, result, error);
3449 * camel_folder_fetch_messages_sync :
3450 * @folder: a #CamelFolder
3451 * @type: Type to specify fetch old or new messages.
3452 * #limit: Limit to specify the number of messages to download.
3453 * @cancellable: optional #GCancellable object, or %NULL
3454 * @error: return location for a #GError, or %NULL
3456 * Downloads old or new specified number of messages from the server. It is
3457 * optimized for mobile client usage. Desktop clients should keep away from
3458 * this api and use @camel_folder_refresh_info.
3460 * Returns: %TRUE if there are more messages to fetch,
3461 * %FALSE if there are no more messages
3466 camel_folder_fetch_messages_sync (CamelFolder *folder,
3467 CamelFetchType type,
3469 GCancellable *cancellable,
3472 CamelFolderClass *class;
3473 gboolean success = TRUE;
3475 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3477 class = CAMEL_FOLDER_GET_CLASS (folder);
3479 /* Some backends that wont support mobile
3480 * mode, won't have this method implemented. */
3481 if (class->fetch_messages_sync == NULL)
3484 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
3486 /* Check for cancellation after locking. */
3487 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
3488 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3492 success = class->fetch_messages_sync (
3493 folder, type, limit, cancellable, error);
3494 CAMEL_CHECK_GERROR (folder, fetch_messages_sync, success, error);
3496 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3502 * camel_folder_fetch_messages:
3503 * @folder: a #CamelFolder
3504 * @type: Type to specify fetch old or new messages.
3505 * #limit: Limit to specify the number of messages to download.
3506 * @io_priority: the I/O priority of the request
3507 * @cancellable: optional #GCancellable object, or %NULL
3508 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3509 * @user_data: data to pass to the callback function
3511 * Asynchronously download new or old messages from the server. It is assumes
3512 * that the client has only a window of interested messages of what server has.
3513 * And old/new type helps to expand that window.
3515 * type = CAMEL_FETCH_OLD_MESSAGES: Downloads messages older than what the
3516 * client already has.
3517 * type = CAMEL_FETCH_NEW_MESSAGES: Downloads messages newer than what the
3518 * client already has.
3520 * When the operation is finished, @callback will be called. You can then
3521 * call camel_folder_fetch_messages_finish() to get the result of the operation.
3526 camel_folder_fetch_messages (CamelFolder *folder,
3527 CamelFetchType type,
3530 GCancellable *cancellable,
3531 GAsyncReadyCallback callback,
3534 CamelFolderClass *class;
3536 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3538 class = CAMEL_FOLDER_GET_CLASS (folder);
3539 g_return_if_fail (class->fetch_messages != NULL);
3541 class->fetch_messages (
3542 folder, type, limit, io_priority,
3543 cancellable, callback, user_data);
3547 * camel_folder_fetch_messages_finish:
3548 * @folder: a #CamelFolder
3549 * @result: a #GAsyncResult
3550 * @error: return location for a #GError, or %NULL
3552 * Finishes the operation started with camel_folder_fetch_messages().
3554 * Returns: %TRUE if there are more messages to fetch,
3555 * %FALSE if there are no more messages
3560 camel_folder_fetch_messages_finish (CamelFolder *folder,
3561 GAsyncResult *result,
3564 CamelFolderClass *class;
3566 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3567 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
3569 class = CAMEL_FOLDER_GET_CLASS (folder);
3570 g_return_val_if_fail (class->fetch_messages_finish != NULL, FALSE);
3572 return class->fetch_messages_finish (folder, result, error);
3576 * camel_folder_get_message_sync:
3577 * @folder: a #CamelFolder
3578 * @message_uid: the message UID
3579 * @cancellable: optional #GCancellable object, or %NULL
3580 * @error: return location for a #GError, or %NULL
3582 * Gets the message corresponding to @message_uid from @folder.
3584 * Returns: a #CamelMimeMessage corresponding to the requested UID
3589 camel_folder_get_message_sync (CamelFolder *folder,
3590 const gchar *message_uid,
3591 GCancellable *cancellable,
3594 CamelFolderClass *class;
3595 CamelMimeMessage *message = NULL;
3597 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
3598 g_return_val_if_fail (message_uid != NULL, NULL);
3600 class = CAMEL_FOLDER_GET_CLASS (folder);
3601 g_return_val_if_fail (class->get_message_sync != NULL, NULL);
3603 camel_operation_push_message (
3604 cancellable, _("Retrieving message '%s' in %s"),
3605 message_uid, camel_folder_get_display_name (folder));
3607 if (class->get_message_cached) {
3608 /* Return cached message, if available locally; this should
3609 * not do any network I/O, only check if message is already
3610 * downloaded and return it quicker, not being blocked by
3611 * the folder's lock. Returning NULL is not considered as
3612 * an error, it just means that the message is still
3613 * to-be-downloaded. */
3614 message = class->get_message_cached (
3615 folder, message_uid, cancellable);
3619 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
3621 /* Check for cancellation after locking. */
3622 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
3623 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3624 camel_operation_pop_message (cancellable);
3628 message = class->get_message_sync (
3629 folder, message_uid, cancellable, error);
3630 CAMEL_CHECK_GERROR (
3631 folder, get_message_sync, message != NULL, error);
3633 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3636 if (message && camel_mime_message_get_source (message) == NULL) {
3640 store = camel_folder_get_parent_store (folder);
3641 uid = camel_service_get_uid (CAMEL_SERVICE (store));
3643 camel_mime_message_set_source (message, uid);
3646 camel_operation_pop_message (cancellable);
3648 if (message != NULL && camel_debug_start (":folder")) {
3650 "CamelFolder:get_message ('%s', '%s') =\n",
3651 camel_folder_get_full_name (folder), message_uid);
3652 camel_mime_message_dump (message, FALSE);
3660 * camel_folder_get_message:
3661 * @folder: a #CamelFolder
3662 * @message_uid: the message UID
3663 * @io_priority: the I/O priority of the request
3664 * @cancellable: optional #GCancellable object, or %NULL
3665 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3666 * @user_data: data to pass to the callback function
3668 * Asynchronously gets the message corresponding to @message_uid from @folder.
3670 * When the operation is finished, @callback will be called. You can then
3671 * call camel_folder_get_message_finish() to get the result of the operation.
3676 camel_folder_get_message (CamelFolder *folder,
3677 const gchar *message_uid,
3679 GCancellable *cancellable,
3680 GAsyncReadyCallback callback,
3683 CamelFolderClass *class;
3685 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3686 g_return_if_fail (message_uid != NULL);
3688 class = CAMEL_FOLDER_GET_CLASS (folder);
3689 g_return_if_fail (class->get_message != NULL);
3691 class->get_message (
3692 folder, message_uid, io_priority,
3693 cancellable, callback, user_data);
3697 * camel_folder_get_message_finish:
3698 * @folder: a #CamelFolder
3699 * @result: a #GAsyncResult
3700 * @error: return location for a #GError or %NULL
3702 * Finishes the operation started with camel_folder_get_message().
3704 * Returns: a #CamelMimeMessage corresponding to the requested UID
3709 camel_folder_get_message_finish (CamelFolder *folder,
3710 GAsyncResult *result,
3713 CamelFolderClass *class;
3715 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
3716 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
3718 class = CAMEL_FOLDER_GET_CLASS (folder);
3719 g_return_val_if_fail (class->get_message_finish != NULL, NULL);
3721 return class->get_message_finish (folder, result, error);
3725 * camel_folder_get_quota_info_sync:
3726 * @folder: a #CamelFolder
3727 * @cancellable: optional #GCancellable object, or %NULL
3728 * @error: return location for a #GError, or %NULL
3730 * Gets a list of known quotas for @folder. Free the returned
3731 * #CamelFolderQuotaInfo struct with camel_folder_quota_info_free().
3733 * If quotas are not supported for @folder, the function returns %NULL
3734 * and sets @error to #G_IO_ERROR_NOT_SUPPORTED.
3736 * Returns: a #CamelFolderQuotaInfo, or %NULL
3740 CamelFolderQuotaInfo *
3741 camel_folder_get_quota_info_sync (CamelFolder *folder,
3742 GCancellable *cancellable,
3745 CamelFolderClass *class;
3746 CamelFolderQuotaInfo *quota_info;
3747 const gchar *display_name;
3748 const gchar *message;
3750 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
3752 class = CAMEL_FOLDER_GET_CLASS (folder);
3753 g_return_val_if_fail (class->get_quota_info_sync != NULL, NULL);
3755 message = _("Retrieving quota information for '%s'");
3756 display_name = camel_folder_get_display_name (folder);
3757 camel_operation_push_message (cancellable, message, display_name);
3759 quota_info = class->get_quota_info_sync (folder, cancellable, error);
3760 CAMEL_CHECK_GERROR (
3761 folder, get_quota_info_sync, quota_info != NULL, error);
3763 camel_operation_pop_message (cancellable);
3769 * camel_folder_get_quota_info:
3770 * @folder: a #CamelFolder
3771 * @io_priority: the I/O priority of the request
3772 * @cancellable: optional #GCancellable object, or %NULL
3773 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3774 * @user_data: data to pass to the callback function
3776 * Asynchronously gets a list of known quotas for @folder.
3778 * When the operation is finished, @callback will be called. You can
3779 * then call camel_folder_get_quota_info_finish() to get the result of
3785 camel_folder_get_quota_info (CamelFolder *folder,
3787 GCancellable *cancellable,
3788 GAsyncReadyCallback callback,
3791 CamelFolderClass *class;
3793 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3795 class = CAMEL_FOLDER_GET_CLASS (folder);
3796 g_return_if_fail (class->get_quota_info != NULL);
3798 class->get_quota_info (
3799 folder, io_priority,
3800 cancellable, callback, user_data);
3804 * camel_folder_get_quota_info_finish:
3805 * @folder: a #CamelFolder
3806 * @result: a #GAsyncResult
3807 * @error: return location for a #GError or %NULL
3809 * Finishes the operation started with camel_folder_get_quota_info().
3810 * Free the returned #CamelFolderQuotaInfo struct with
3811 * camel_folder_quota_info_free().
3813 * If quotas are not supported for @folder, the function returns %NULL
3814 * and sets @error to #G_IO_ERROR_NOT_SUPPORTED.
3816 * Returns: a #CamelFolderQuotaInfo, or %NULL
3820 CamelFolderQuotaInfo *
3821 camel_folder_get_quota_info_finish (CamelFolder *folder,
3822 GAsyncResult *result,
3825 CamelFolderClass *class;
3827 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
3829 class = CAMEL_FOLDER_GET_CLASS (folder);
3830 g_return_val_if_fail (class->get_quota_info_finish != NULL, NULL);
3832 return class->get_quota_info_finish (folder, result, error);
3836 * camel_folder_purge_message_cache_sync :
3837 * @folder: a #CamelFolder
3838 * @start_uid: the start message UID
3839 * @end_uid: the end message UID
3840 * @cancellable: optional #GCancellable object, or %NULL
3841 * @error: return location for a #GError, or %NULL
3843 * Delete the local cache of all messages between these uids.
3845 * Returns: %TRUE if success, %FALSE if there are any errors.
3850 camel_folder_purge_message_cache_sync (CamelFolder *folder,
3853 GCancellable *cancellable,
3856 CamelFolderClass *class;
3857 gboolean success = TRUE;
3859 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3861 class = CAMEL_FOLDER_GET_CLASS (folder);
3863 /* Some backends that wont support mobile
3864 * mode, won't have this api implemented. */
3865 if (class->purge_message_cache_sync == NULL)
3868 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
3870 /* Check for cancellation after locking. */
3871 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
3872 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3876 success = class->purge_message_cache_sync (
3877 folder, start_uid, end_uid, cancellable, error);
3878 CAMEL_CHECK_GERROR (folder, purge_message_cache_sync, success, error);
3880 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3886 * camel_folder_purge_message_cache:
3887 * @folder: a #CamelFolder
3888 * @start_uid: the start message UID
3889 * @end_uid: the end message UID
3890 * @io_priority: the I/O priority of the request
3891 * @cancellable: optional #GCancellable object, or %NULL
3892 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3893 * @user_data: data to pass to the callback function
3895 * Delete the local cache of all messages between these uids.
3897 * When the operation is finished, @callback will be called. You can then
3898 * call camel_folder_purge_message_cache_finish() to get the result of the
3904 camel_folder_purge_message_cache (CamelFolder *folder,
3908 GCancellable *cancellable,
3909 GAsyncReadyCallback callback,
3912 CamelFolderClass *class;
3914 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3916 class = CAMEL_FOLDER_GET_CLASS (folder);
3917 g_return_if_fail (class->purge_message_cache != NULL);
3919 class->purge_message_cache (
3920 folder, start_uid, end_uid, io_priority,
3921 cancellable, callback, user_data);
3925 * camel_folder_purge_message_cache_finish:
3926 * @folder: a #CamelFolder
3927 * @result: a #GAsyncResult
3928 * @error: return location for a #GError, or %NULL
3930 * Finishes the operation started with camel_folder_purge_message_cache().
3932 * Returns: %TRUE if cache is deleted, %FALSE if there are any errors
3937 camel_folder_purge_message_cache_finish (CamelFolder *folder,
3938 GAsyncResult *result,
3941 CamelFolderClass *class;
3943 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3944 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
3946 class = CAMEL_FOLDER_GET_CLASS (folder);
3947 g_return_val_if_fail (class->purge_message_cache_finish != NULL, FALSE);
3949 return class->purge_message_cache_finish (folder, result, error);
3953 * camel_folder_refresh_info_sync:
3954 * @folder: a #CamelFolder
3955 * @cancellable: optional #GCancellable object, or %NULL
3956 * @error: return location for a #GError, or %NULL
3958 * Synchronizes a folder's summary with its backing store.
3960 * Returns: %TRUE on success, %FALSE on error
3965 camel_folder_refresh_info_sync (CamelFolder *folder,
3966 GCancellable *cancellable,
3969 CamelFolderClass *class;
3970 const gchar *display_name;
3971 const gchar *message;
3974 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3976 class = CAMEL_FOLDER_GET_CLASS (folder);
3977 g_return_val_if_fail (class->refresh_info_sync != NULL, FALSE);
3979 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
3981 /* Check for cancellation after locking. */
3982 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
3983 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3987 message = _("Refreshing folder '%s'");
3988 display_name = camel_folder_get_display_name (folder);
3989 camel_operation_push_message (cancellable, message, display_name);
3991 success = class->refresh_info_sync (folder, cancellable, error);
3992 CAMEL_CHECK_GERROR (folder, refresh_info_sync, success, error);
3994 camel_operation_pop_message (cancellable);
3996 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
4002 * camel_folder_refresh_info:
4003 * @folder: a #CamelFolder
4004 * @io_priority: the I/O priority of the request
4005 * @cancellable: optional #GCancellable object, or %NULL
4006 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
4007 * @user_data: data to pass to the callback function
4009 * Asynchronously synchronizes a folder's summary with its backing store.
4011 * When the operation is finished, @callback will be called. You can then
4012 * call camel_folder_refresh_info_finish() to get the result of the operation.
4017 camel_folder_refresh_info (CamelFolder *folder,
4019 GCancellable *cancellable,
4020 GAsyncReadyCallback callback,
4023 CamelFolderClass *class;
4025 g_return_if_fail (CAMEL_IS_FOLDER (folder));
4027 class = CAMEL_FOLDER_GET_CLASS (folder);
4028 g_return_if_fail (class->refresh_info != NULL);
4030 class->refresh_info (
4031 folder, io_priority, cancellable, callback, user_data);
4035 * camel_folder_refresh_info_finish:
4036 * @folder: a #CamelFolder
4037 * @result: a #GAsyncResult
4038 * @error: return location for a #GError, or %NULL
4040 * Finishes the operation started with camel_folder_refresh_info().
4042 * Returns: %TRUE on success, %FALSE on error
4047 camel_folder_refresh_info_finish (CamelFolder *folder,
4048 GAsyncResult *result,
4051 CamelFolderClass *class;
4053 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4054 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4056 class = CAMEL_FOLDER_GET_CLASS (folder);
4057 g_return_val_if_fail (class->refresh_info_finish != NULL, FALSE);
4059 return class->refresh_info_finish (folder, result, error);
4063 * camel_folder_synchronize_sync:
4064 * @folder: a #CamelFolder
4065 * @expunge: whether to expunge after synchronizing
4066 * @cancellable: optional #GCancellable object, or %NULL
4067 * @error: return location for a #GError, or %NULL
4069 * Synchronizes any changes that have been made to @folder to its
4070 * backing store, optionally expunging deleted messages as well.
4072 * Returns: %TRUE on success, %FALSE on error
4077 camel_folder_synchronize_sync (CamelFolder *folder,
4079 GCancellable *cancellable,
4082 CamelFolderClass *class;
4083 gboolean success = TRUE;
4085 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4087 class = CAMEL_FOLDER_GET_CLASS (folder);
4088 g_return_val_if_fail (class->synchronize_sync != NULL, FALSE);
4090 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
4092 /* Check for cancellation after locking. */
4093 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
4094 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
4098 if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED)) {
4099 success = class->synchronize_sync (
4100 folder, expunge, cancellable, error);
4101 CAMEL_CHECK_GERROR (folder, synchronize_sync, success, error);
4104 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
4110 * camel_folder_synchronize:
4111 * @folder: a #CamelFolder
4112 * @expunge: whether to expunge after synchronizing
4113 * @io_priority: the I/O priority of the request
4114 * @cancellable: optional #GCancellable object, or %NULL
4115 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
4116 * @user_data: data to pass to the callback function
4118 * Synchronizes any changes that have been made to @folder to its backing
4119 * store asynchronously, optionally expunging deleted messages as well.
4121 * When the operation is finished, @callback will be called. You can then
4122 * call camel_folder_synchronize_finish() to get the result of the operation.
4127 camel_folder_synchronize (CamelFolder *folder,
4130 GCancellable *cancellable,
4131 GAsyncReadyCallback callback,
4134 CamelFolderClass *class;
4136 g_return_if_fail (CAMEL_IS_FOLDER (folder));
4138 class = CAMEL_FOLDER_GET_CLASS (folder);
4139 g_return_if_fail (class->synchronize != NULL);
4141 class->synchronize (
4142 folder, expunge, io_priority,
4143 cancellable, callback, user_data);
4147 * camel_folder_synchronize_finish:
4148 * @folder: a #CamelFolder
4149 * @result: a #GAsyncResult
4150 * @error: return location for a #GError, or %NULL
4152 * Finishes the operation started with camel_folder_synchronize().
4154 * Returns: %TRUE on sucess, %FALSE on error
4159 camel_folder_synchronize_finish (CamelFolder *folder,
4160 GAsyncResult *result,
4163 CamelFolderClass *class;
4165 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4166 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4168 class = CAMEL_FOLDER_GET_CLASS (folder);
4169 g_return_val_if_fail (class->synchronize_finish != NULL, FALSE);
4171 return class->synchronize_finish (folder, result, error);
4175 * camel_folder_synchronize_message_sync:
4176 * @folder: a #CamelFolder
4177 * @message_uid: a message UID
4178 * @cancellable: optional #GCancellable object, or %NULL
4179 * @error: return location for a #GError, or %NULL
4181 * Ensure that a message identified by @message_uid has been synchronized in
4182 * @folder so that calling camel_folder_get_message() on it later will work
4185 * Returns: %TRUE on success, %FALSE on error
4190 camel_folder_synchronize_message_sync (CamelFolder *folder,
4191 const gchar *message_uid,
4192 GCancellable *cancellable,
4195 CamelFolderClass *class;
4196 gboolean success = FALSE;
4198 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4199 g_return_val_if_fail (message_uid != NULL, FALSE);
4201 class = CAMEL_FOLDER_GET_CLASS (folder);
4202 g_return_val_if_fail (class->get_message_sync != NULL, FALSE);
4204 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
4206 /* Check for cancellation after locking. */
4207 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
4208 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
4212 /* Use the sync_message method if the class implements it. */
4213 if (class->synchronize_message_sync != NULL) {
4214 success = class->synchronize_message_sync (
4215 folder, message_uid, cancellable, error);
4216 CAMEL_CHECK_GERROR (
4217 folder, synchronize_message_sync, success, error);
4219 CamelMimeMessage *message;
4221 message = class->get_message_sync (
4222 folder, message_uid, cancellable, error);
4223 CAMEL_CHECK_GERROR (
4224 folder, get_message_sync, message != NULL, error);
4226 if (message != NULL) {
4227 g_object_unref (message);
4232 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
4238 * camel_folder_synchronize_message;
4239 * @folder: a #CamelFolder
4240 * @message_uid: a message UID
4241 * @io_priority: the I/O priority of the request
4242 * @cancellable: optional #GCancellable object, or %NULL
4243 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
4244 * @user_data: data to pass to the callback function
4246 * Asynchronously ensure that a message identified by @message_uid has been
4247 * synchronized in @folder so that calling camel_folder_get_message() on it
4248 * later will work in offline mode.
4250 * When the operation is finished, @callback will be called. You can then
4251 * call camel_folder_synchronize_message_finish() to get the result of the
4257 camel_folder_synchronize_message (CamelFolder *folder,
4258 const gchar *message_uid,
4260 GCancellable *cancellable,
4261 GAsyncReadyCallback callback,
4264 CamelFolderClass *class;
4266 g_return_if_fail (CAMEL_IS_FOLDER (folder));
4267 g_return_if_fail (message_uid != NULL);
4269 class = CAMEL_FOLDER_GET_CLASS (folder);
4270 g_return_if_fail (class->synchronize_message != NULL);
4272 class->synchronize_message (
4273 folder, message_uid, io_priority,
4274 cancellable, callback, user_data);
4278 * camel_folder_synchronize_message_finish:
4279 * @folder: a #CamelFolder
4280 * @result: a #GAsyncResult
4281 * @error: return location for a #GError, or %NULL
4283 * Finishes the operation started with camel_folder_synchronize_message().
4285 * Returns: %TRUE on success, %FALSE on error
4290 camel_folder_synchronize_message_finish (CamelFolder *folder,
4291 GAsyncResult *result,
4294 CamelFolderClass *class;
4296 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4297 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4299 class = CAMEL_FOLDER_GET_CLASS (folder);
4300 g_return_val_if_fail (class->synchronize_message_finish != NULL, FALSE);
4302 return class->synchronize_message_finish (folder, result, error);
4306 * camel_folder_transfer_messages_to_sync:
4307 * @source: the source #CamelFolder
4308 * @message_uids: message UIDs in @source
4309 * @destination: the destination #CamelFolder
4310 * @delete_originals: whether or not to delete the original messages
4311 * @transferred_uids: if non-%NULL, the UIDs of the resulting messages
4312 * in @destination will be stored here, if known.
4313 * @cancellable: optional #GCancellable object, or %NULL
4314 * @error: return location for a #GError, or %NULL
4316 * Copies or moves messages from one folder to another. If the
4317 * @source and @destination folders have the same parent_store, this
4318 * may be more efficient than using camel_folder_append_message_sync().
4320 * Returns: %TRUE on success, %FALSE on failure
4325 camel_folder_transfer_messages_to_sync (CamelFolder *source,
4326 GPtrArray *message_uids,
4327 CamelFolder *destination,
4328 gboolean delete_originals,
4329 GPtrArray **transferred_uids,
4330 GCancellable *cancellable,
4333 CamelFolderClass *class;
4336 g_return_val_if_fail (CAMEL_IS_FOLDER (source), FALSE);
4337 g_return_val_if_fail (CAMEL_IS_FOLDER (destination), FALSE);
4338 g_return_val_if_fail (message_uids != NULL, FALSE);
4340 if (source == destination || message_uids->len == 0)
4343 if (source->priv->parent_store == destination->priv->parent_store) {
4344 /* If either folder is a vtrash, we need to use the
4345 * vtrash transfer method. */
4346 if (CAMEL_IS_VTRASH_FOLDER (destination))
4347 class = CAMEL_FOLDER_GET_CLASS (destination);
4349 class = CAMEL_FOLDER_GET_CLASS (source);
4350 success = class->transfer_messages_to_sync (
4351 source, message_uids, destination, delete_originals,
4352 transferred_uids, cancellable, error);
4354 success = folder_transfer_messages_to_sync (
4355 source, message_uids, destination, delete_originals,
4356 transferred_uids, cancellable, error);
4362 * camel_folder_transfer_messages_to:
4363 * @source: the source #CamelFolder
4364 * @message_uids: message UIDs in @source
4365 * @destination: the destination #CamelFolder
4366 * @delete_originals: whether or not to delete the original messages
4367 * @io_priority: the I/O priority of the request
4368 * @cancellable: optional #GCancellable object, or %NULL
4369 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
4370 * @user_data: data to pass to the callback function
4372 * Asynchronously copies or moves messages from one folder to another.
4373 * If the @source or @destination folders have the same parent store,
4374 * this may be more efficient than using camel_folder_append_message().
4376 * When the operation is finished, @callback will be called. You can then
4377 * call camel_folder_transfer_messages_to_finish() to get the result of the
4383 camel_folder_transfer_messages_to (CamelFolder *source,
4384 GPtrArray *message_uids,
4385 CamelFolder *destination,
4386 gboolean delete_originals,
4388 GCancellable *cancellable,
4389 GAsyncReadyCallback callback,
4392 CamelFolderClass *class;
4394 g_return_if_fail (CAMEL_IS_FOLDER (source));
4395 g_return_if_fail (CAMEL_IS_FOLDER (destination));
4396 g_return_if_fail (message_uids != NULL);
4398 class = CAMEL_FOLDER_GET_CLASS (source);
4399 g_return_if_fail (class->transfer_messages_to != NULL);
4401 class->transfer_messages_to (
4402 source, message_uids, destination, delete_originals,
4403 io_priority, cancellable, callback, user_data);
4407 * camel_folder_transfer_messages_to_finish:
4408 * @source: a #CamelFolder
4409 * @result: a #GAsyncResult
4410 * @transferred_uids: if non-%NULL, the UIDs of the resulting messages
4411 * in @destination will be stored here, if known.
4412 * @error: return location for a #GError, or %NULL
4414 * Finishes the operation started with camel_folder_transfer_messages_to().
4416 * Returns: %TRUE on success, %FALSE on error
4421 camel_folder_transfer_messages_to_finish (CamelFolder *source,
4422 GAsyncResult *result,
4423 GPtrArray **transferred_uids,
4426 CamelFolderClass *class;
4428 g_return_val_if_fail (CAMEL_IS_FOLDER (source), FALSE);
4429 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4431 class = CAMEL_FOLDER_GET_CLASS (source);
4432 g_return_val_if_fail (class->transfer_messages_to_finish != NULL, FALSE);
4434 return class->transfer_messages_to_finish (
4435 source, result, transferred_uids, error);
4439 * camel_folder_change_info_new:
4441 * Create a new folder change info structure.
4443 * Change info structures are not MT-SAFE and must be
4444 * locked for exclusive access externally.
4446 * Returns: a new #CamelFolderChangeInfo
4448 CamelFolderChangeInfo *
4449 camel_folder_change_info_new (void)
4451 CamelFolderChangeInfo *info;
4453 info = g_slice_new (CamelFolderChangeInfo);
4454 info->uid_added = g_ptr_array_new ();
4455 info->uid_removed = g_ptr_array_new ();
4456 info->uid_changed = g_ptr_array_new ();
4457 info->uid_recent = g_ptr_array_new ();
4458 info->priv = g_slice_new (struct _CamelFolderChangeInfoPrivate);
4459 info->priv->uid_stored = g_hash_table_new (g_str_hash, g_str_equal);
4460 info->priv->uid_source = NULL;
4461 info->priv->uid_filter = g_ptr_array_new ();
4462 info->priv->uid_pool = camel_mempool_new (512, 256, CAMEL_MEMPOOL_ALIGN_BYTE);
4468 * camel_folder_change_info_add_source:
4469 * @info: a #CamelFolderChangeInfo
4472 * Add a source uid for generating a changeset.
4475 camel_folder_change_info_add_source (CamelFolderChangeInfo *info,
4478 struct _CamelFolderChangeInfoPrivate *p;
4480 g_return_if_fail (info != NULL);
4481 g_return_if_fail (uid != NULL);
4485 if (p->uid_source == NULL)
4486 p->uid_source = g_hash_table_new (g_str_hash, g_str_equal);
4488 if (g_hash_table_lookup (p->uid_source, uid) == NULL)
4489 g_hash_table_insert (p->uid_source, camel_mempool_strdup (p->uid_pool, uid), GINT_TO_POINTER (1));
4493 * camel_folder_change_info_add_source_list:
4494 * @info: a #CamelFolderChangeInfo
4495 * @list: a list of uids
4497 * Add a list of source uid's for generating a changeset.
4500 camel_folder_change_info_add_source_list (CamelFolderChangeInfo *info,
4501 const GPtrArray *list)
4503 struct _CamelFolderChangeInfoPrivate *p;
4506 g_return_if_fail (info != NULL);
4507 g_return_if_fail (list != NULL);
4511 if (p->uid_source == NULL)
4512 p->uid_source = g_hash_table_new (g_str_hash, g_str_equal);
4514 for (i = 0; i < list->len; i++) {
4515 gchar *uid = list->pdata[i];
4517 if (g_hash_table_lookup (p->uid_source, uid) == NULL)
4518 g_hash_table_insert (p->uid_source, camel_mempool_strdup (p->uid_pool, uid), GINT_TO_POINTER (1));
4523 * camel_folder_change_info_add_update:
4524 * @info: a #CamelFolderChangeInfo
4527 * Add a uid from the updated list, used to generate a changeset diff.
4530 camel_folder_change_info_add_update (CamelFolderChangeInfo *info,
4533 struct _CamelFolderChangeInfoPrivate *p;
4537 g_return_if_fail (info != NULL);
4538 g_return_if_fail (uid != NULL);
4542 if (p->uid_source == NULL) {
4543 camel_folder_change_info_add_uid (info, uid);
4547 if (g_hash_table_lookup_extended (p->uid_source, uid, (gpointer) &key, (gpointer) &value)) {
4548 g_hash_table_remove (p->uid_source, key);
4550 camel_folder_change_info_add_uid (info, uid);
4555 * camel_folder_change_info_add_update_list:
4556 * @info: a #CamelFolderChangeInfo
4557 * @list: a list of uids
4559 * Add a list of uid's from the updated list.
4562 camel_folder_change_info_add_update_list (CamelFolderChangeInfo *info,
4563 const GPtrArray *list)
4567 g_return_if_fail (info != NULL);
4568 g_return_if_fail (list != NULL);
4570 for (i = 0; i < list->len; i++)
4571 camel_folder_change_info_add_update (info, list->pdata[i]);
4575 change_info_remove (gchar *key,
4577 CamelFolderChangeInfo *info)
4579 struct _CamelFolderChangeInfoPrivate *p = info->priv;
4583 if (g_hash_table_lookup_extended (p->uid_stored, key, (gpointer) &olduid, (gpointer) &olduids)) {
4584 /* if it was added/changed them removed, then remove it */
4585 if (olduids != info->uid_removed) {
4586 g_ptr_array_remove_fast (olduids, olduid);
4587 g_ptr_array_add (info->uid_removed, olduid);
4588 g_hash_table_insert (p->uid_stored, olduid, info->uid_removed);
4593 /* we dont need to copy this, as they've already been copied into our pool */
4594 g_ptr_array_add (info->uid_removed, key);
4595 g_hash_table_insert (p->uid_stored, key, info->uid_removed);
4599 * camel_folder_change_info_build_diff:
4600 * @info: a #CamelFolderChangeInfo
4602 * Compare the source uid set to the updated uid set and generate the
4603 * differences into the added and removed lists.
4606 camel_folder_change_info_build_diff (CamelFolderChangeInfo *info)
4608 struct _CamelFolderChangeInfoPrivate *p;
4610 g_return_if_fail (info != NULL);
4614 if (p->uid_source) {
4615 g_hash_table_foreach (p->uid_source, (GHFunc) change_info_remove, info);
4616 g_hash_table_destroy (p->uid_source);
4617 p->uid_source = NULL;
4622 change_info_recent_uid (CamelFolderChangeInfo *info,
4625 struct _CamelFolderChangeInfoPrivate *p;
4631 /* always add to recent, but dont let anyone else know */
4632 if (!g_hash_table_lookup_extended (p->uid_stored, uid, (gpointer *) &olduid, (gpointer *) &olduids)) {
4633 olduid = camel_mempool_strdup (p->uid_pool, uid);
4635 g_ptr_array_add (info->uid_recent, olduid);
4639 change_info_filter_uid (CamelFolderChangeInfo *info,
4642 struct _CamelFolderChangeInfoPrivate *p;
4648 /* always add to filter, but dont let anyone else know */
4649 if (!g_hash_table_lookup_extended (p->uid_stored, uid, (gpointer *) &olduid, (gpointer *) &olduids)) {
4650 olduid = camel_mempool_strdup (p->uid_pool, uid);
4652 g_ptr_array_add (p->uid_filter, olduid);
4656 change_info_cat (CamelFolderChangeInfo *info,
4658 void (*add)(CamelFolderChangeInfo *info,
4663 for (i = 0; i < source->len; i++)
4664 add (info, source->pdata[i]);
4668 * camel_folder_change_info_cat:
4669 * @info: a #CamelFolderChangeInfo to append to
4670 * @src: a #CamelFolderChangeInfo to append from
4672 * Concatenate one change info onto antoher. Can be used to copy them
4676 camel_folder_change_info_cat (CamelFolderChangeInfo *info,
4677 CamelFolderChangeInfo *source)
4679 g_return_if_fail (info != NULL);
4680 g_return_if_fail (source != NULL);
4682 change_info_cat (info, source->uid_added, camel_folder_change_info_add_uid);
4683 change_info_cat (info, source->uid_removed, camel_folder_change_info_remove_uid);
4684 change_info_cat (info, source->uid_changed, camel_folder_change_info_change_uid);
4685 change_info_cat (info, source->uid_recent, change_info_recent_uid);
4686 change_info_cat (info, source->priv->uid_filter, change_info_filter_uid);
4690 * camel_folder_change_info_add_uid:
4691 * @info: a #CamelFolderChangeInfo
4694 * Add a new uid to the changeinfo.
4697 camel_folder_change_info_add_uid (CamelFolderChangeInfo *info,
4700 struct _CamelFolderChangeInfoPrivate *p;
4704 g_return_if_fail (info != NULL);
4705 g_return_if_fail (uid != NULL);
4709 if (g_hash_table_lookup_extended (p->uid_stored, uid, (gpointer) &olduid, (gpointer) &olduids)) {
4710 /* if it was removed then added, promote it to a changed */
4711 /* if it was changed then added, leave as changed */
4712 if (olduids == info->uid_removed) {
4713 g_ptr_array_remove_fast (olduids, olduid);
4714 g_ptr_array_add (info->uid_changed, olduid);
4715 g_hash_table_insert (p->uid_stored, olduid, info->uid_changed);
4720 olduid = camel_mempool_strdup (p->uid_pool, uid);
4721 g_ptr_array_add (info->uid_added, olduid);
4722 g_hash_table_insert (p->uid_stored, olduid, info->uid_added);
4726 * camel_folder_change_info_remove_uid:
4727 * @info: a #CamelFolderChangeInfo
4730 * Add a uid to the removed uid list.
4733 camel_folder_change_info_remove_uid (CamelFolderChangeInfo *info,
4736 struct _CamelFolderChangeInfoPrivate *p;
4740 g_return_if_fail (info != NULL);
4741 g_return_if_fail (uid != NULL);
4745 if (g_hash_table_lookup_extended (p->uid_stored, uid, (gpointer) &olduid, (gpointer) &olduids)) {
4746 /* if it was added/changed them removed, then remove it */
4747 if (olduids != info->uid_removed) {
4748 g_ptr_array_remove_fast (olduids, olduid);
4749 g_ptr_array_add (info->uid_removed, olduid);
4750 g_hash_table_insert (p->uid_stored, olduid, info->uid_removed);
4755 olduid = camel_mempool_strdup (p->uid_pool, uid);
4756 g_ptr_array_add (info->uid_removed, olduid);
4757 g_hash_table_insert (p->uid_stored, olduid, info->uid_removed);
4761 * camel_folder_change_info_change_uid:
4762 * @info: a #CamelFolderChangeInfo
4765 * Add a uid to the changed uid list.
4768 camel_folder_change_info_change_uid (CamelFolderChangeInfo *info,
4771 struct _CamelFolderChangeInfoPrivate *p;
4775 g_return_if_fail (info != NULL);
4776 g_return_if_fail (uid != NULL);
4780 if (g_hash_table_lookup_extended (p->uid_stored, uid, (gpointer) &olduid, (gpointer) &olduids)) {
4781 /* if we have it already, leave it as that */
4785 olduid = camel_mempool_strdup (p->uid_pool, uid);
4786 g_ptr_array_add (info->uid_changed, olduid);
4787 g_hash_table_insert (p->uid_stored, olduid, info->uid_changed);
4791 * camel_folder_change_info_recent_uid:
4792 * @info: a #CamelFolderChangeInfo
4795 * Add a recent uid to the changedinfo.
4796 * This will also add the uid to the uid_filter array for potential
4800 camel_folder_change_info_recent_uid (CamelFolderChangeInfo *info,
4803 g_return_if_fail (info != NULL);
4804 g_return_if_fail (uid != NULL);
4806 change_info_recent_uid (info, uid);
4807 change_info_filter_uid (info, uid);
4811 * camel_folder_change_info_changed:
4812 * @info: a #CamelFolderChangeInfo
4814 * Gets whether or not there have been any changes.
4816 * Returns: %TRUE if the changeset contains any changes or %FALSE
4820 camel_folder_change_info_changed (CamelFolderChangeInfo *info)
4822 g_return_val_if_fail (info != NULL, FALSE);
4824 return (info->uid_added->len || info->uid_removed->len || info->uid_changed->len || info->uid_recent->len);
4828 * camel_folder_change_info_clear:
4829 * @info: a #CamelFolderChangeInfo
4831 * Empty out the change info; called after changes have been
4835 camel_folder_change_info_clear (CamelFolderChangeInfo *info)
4837 struct _CamelFolderChangeInfoPrivate *p;
4839 g_return_if_fail (info != NULL);
4843 g_ptr_array_set_size (info->uid_added, 0);
4844 g_ptr_array_set_size (info->uid_removed, 0);
4845 g_ptr_array_set_size (info->uid_changed, 0);
4846 g_ptr_array_set_size (info->uid_recent, 0);
4847 if (p->uid_source) {
4848 g_hash_table_destroy (p->uid_source);
4849 p->uid_source = NULL;
4851 g_hash_table_destroy (p->uid_stored);
4852 p->uid_stored = g_hash_table_new (g_str_hash, g_str_equal);
4853 g_ptr_array_set_size (p->uid_filter, 0);
4854 camel_mempool_flush (p->uid_pool, TRUE);
4858 * camel_folder_change_info_free:
4859 * @info: a #CamelFolderChangeInfo
4861 * Free memory associated with the folder change info lists.
4864 camel_folder_change_info_free (CamelFolderChangeInfo *info)
4866 struct _CamelFolderChangeInfoPrivate *p;
4868 g_return_if_fail (info != NULL);
4873 g_hash_table_destroy (p->uid_source);
4875 g_hash_table_destroy (p->uid_stored);
4876 g_ptr_array_free (p->uid_filter, TRUE);
4877 camel_mempool_destroy (p->uid_pool);
4878 g_slice_free (struct _CamelFolderChangeInfoPrivate, p);
4880 g_ptr_array_free (info->uid_added, TRUE);
4881 g_ptr_array_free (info->uid_removed, TRUE);
4882 g_ptr_array_free (info->uid_changed, TRUE);
4883 g_ptr_array_free (info->uid_recent, TRUE);
4884 g_slice_free (CamelFolderChangeInfo, info);