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 */
76 struct _AsyncContext {
78 CamelMimeMessage *message; /* also a result */
79 CamelMessageInfo *info;
80 CamelFolder *destination;
81 GPtrArray *message_uids;
82 gchar *message_uid; /* also a result */
83 gboolean delete_originals;
85 CamelFetchType fetch_type;
91 GPtrArray *transferred_uids;
92 CamelFolderQuotaInfo *quota_info;
93 gboolean success; /* A result that mention that there are more messages in fetch_messages operation */
96 struct _CamelFolderChangeInfoPrivate {
97 GHashTable *uid_stored; /* what we have stored, which array they're in */
98 GHashTable *uid_source; /* used to create unique lists */
99 GPtrArray *uid_filter; /* uids to be filtered */
100 CamelMemPool *uid_pool; /* pool used to store copies of uid strings */
108 struct _FolderFilterData {
113 CamelFilterDriver *driver;
131 static guint signals[LAST_SIGNAL];
133 G_DEFINE_ABSTRACT_TYPE (CamelFolder, camel_folder, CAMEL_TYPE_OBJECT)
136 async_context_free (AsyncContext *async_context)
138 if (async_context->message != NULL)
139 g_object_unref (async_context->message);
141 /* XXX This is actually an unref. Good god, no wonder we
142 * have so many crashes involving CamelMessageInfos! */
143 if (async_context->info != NULL)
144 camel_message_info_free (async_context->info);
146 if (async_context->destination != NULL)
147 g_object_unref (async_context->destination);
149 if (async_context->message_uids != NULL) {
150 g_ptr_array_foreach (
151 async_context->message_uids, (GFunc) g_free, NULL);
152 g_ptr_array_free (async_context->message_uids, TRUE);
155 if (async_context->transferred_uids != NULL) {
156 g_ptr_array_foreach (
157 async_context->transferred_uids, (GFunc) g_free, NULL);
158 g_ptr_array_free (async_context->transferred_uids, TRUE);
161 if (async_context->quota_info != NULL)
162 camel_folder_quota_info_free (async_context->quota_info);
164 g_free (async_context->message_uid);
165 g_free (async_context->start_uid);
166 g_free (async_context->end_uid);
168 g_slice_free (AsyncContext, async_context);
172 signal_data_free (SignalData *signal_data)
174 if (signal_data->folder != NULL)
175 g_object_unref (signal_data->folder);
177 g_free (signal_data->folder_name);
179 g_slice_free (SignalData, signal_data);
183 folder_emit_changed_cb (gpointer user_data)
185 SignalData *signal_data = user_data;
186 CamelFolderChangeInfo *changes;
188 camel_folder_lock (signal_data->folder, CAMEL_FOLDER_CHANGE_LOCK);
189 changes = signal_data->folder->priv->pending_changes;
190 signal_data->folder->priv->pending_changes = NULL;
191 camel_folder_unlock (signal_data->folder, CAMEL_FOLDER_CHANGE_LOCK);
193 g_signal_emit (signal_data->folder, signals[CHANGED], 0, changes);
195 camel_folder_change_info_free (changes);
201 folder_emit_deleted_cb (gpointer user_data)
203 SignalData *signal_data = user_data;
205 g_signal_emit (signal_data->folder, signals[DELETED], 0);
211 folder_emit_renamed_cb (gpointer user_data)
213 SignalData *signal_data = user_data;
218 signal_data->folder_name);
224 folder_filter_data_free (FolderFilterData *data)
226 if (data->driver != NULL)
227 g_object_unref (data->driver);
228 if (data->recents != NULL)
229 camel_folder_free_deep (data->folder, data->recents);
230 if (data->junk != NULL)
231 camel_folder_free_deep (data->folder, data->junk);
232 if (data->notjunk != NULL)
233 camel_folder_free_deep (data->folder, data->notjunk);
235 /* XXX Too late to pass a GError here. */
236 camel_folder_summary_save_to_db (data->folder->summary, NULL);
238 camel_folder_thaw (data->folder);
239 g_object_unref (data->folder);
241 g_slice_free (FolderFilterData, data);
245 folder_filter (CamelSession *session,
246 GCancellable *cancellable,
247 FolderFilterData *data,
250 CamelMessageInfo *info;
251 CamelStore *parent_store;
253 CamelJunkFilter *junk_filter;
254 gboolean synchronize = FALSE;
255 const gchar *display_name;
257 display_name = camel_folder_get_display_name (data->folder);
258 parent_store = camel_folder_get_parent_store (data->folder);
259 junk_filter = camel_session_get_junk_filter (session);
261 /* Keep the junk filter alive until we're done. */
262 if (junk_filter != NULL)
263 g_object_ref (junk_filter);
266 gboolean success = TRUE;
268 /* Translators: The %s is replaced with the
269 * folder name where the operation is running. */
270 camel_operation_push_message (
271 cancellable, ngettext (
272 "Learning new spam message in '%s'",
273 "Learning new spam messages in '%s'",
274 data->junk->len), display_name);
276 for (i = 0; success && i < data->junk->len; i++) {
277 CamelMimeMessage *message;
278 gint pc = 100 * i / data->junk->len;
280 if (g_cancellable_set_error_if_cancelled (
284 message = camel_folder_get_message_sync (
285 data->folder, data->junk->pdata[i],
291 camel_operation_progress (cancellable, pc);
292 success = camel_junk_filter_learn_junk (
293 junk_filter, message, cancellable, error);
294 g_object_unref (message);
296 synchronize |= success;
299 camel_operation_pop_message (cancellable);
306 gboolean success = TRUE;
308 /* Translators: The %s is replaced with the
309 * folder name where the operation is running. */
310 camel_operation_push_message (
311 cancellable, ngettext (
312 "Learning new ham message in '%s'",
313 "Learning new ham messages in '%s'",
314 data->notjunk->len), display_name);
316 for (i = 0; success && i < data->notjunk->len; i++) {
317 CamelMimeMessage *message;
318 gint pc = 100 * i / data->notjunk->len;
320 if (g_cancellable_set_error_if_cancelled (
324 message = camel_folder_get_message_sync (
325 data->folder, data->notjunk->pdata[i],
331 camel_operation_progress (cancellable, pc);
332 success = camel_junk_filter_learn_not_junk (
333 junk_filter, message, cancellable, error);
334 g_object_unref (message);
336 synchronize |= success;
339 camel_operation_pop_message (cancellable);
346 camel_junk_filter_synchronize (
347 junk_filter, cancellable, error);
352 if (data->driver && data->recents) {
353 CamelService *service;
354 const gchar *store_uid;
356 /* Translators: The %s is replaced with the
357 * folder name where the operation is running. */
358 camel_operation_push_message (
359 cancellable, ngettext (
360 "Filtering new message in '%s'",
361 "Filtering new messages in '%s'",
362 data->recents->len), display_name);
364 service = CAMEL_SERVICE (parent_store);
365 store_uid = camel_service_get_uid (service);
367 for (i = 0; status == 0 && i < data->recents->len; i++) {
368 gchar *uid = data->recents->pdata[i];
369 gint pc = 100 * i / data->recents->len;
371 camel_operation_progress (cancellable, pc);
373 info = camel_folder_get_message_info (
377 "uid '%s' vanished from folder '%s'",
382 status = camel_filter_driver_filter_message (
383 data->driver, NULL, info, uid, data->folder,
384 store_uid, store_uid, cancellable, error);
386 camel_folder_free_message_info (data->folder, info);
389 camel_operation_pop_message (cancellable);
391 camel_filter_driver_flush (data->driver, error);
395 if (junk_filter != NULL)
396 g_object_unref (junk_filter);
400 cmp_array_uids (gconstpointer a,
404 const gchar *uid1 = *(const gchar **) a;
405 const gchar *uid2 = *(const gchar **) b;
406 CamelFolder *folder = user_data;
408 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
410 return camel_folder_cmp_uids (folder, uid1, uid2);
414 folder_transfer_message_to (CamelFolder *source,
417 gchar **transferred_uid,
418 gboolean delete_original,
419 GCancellable *cancellable,
422 CamelMimeMessage *msg;
423 CamelMessageInfo *minfo, *info;
424 GError *local_error = NULL;
426 /* Default implementation. */
428 msg = camel_folder_get_message_sync (source, uid, cancellable, error);
432 /* if its deleted we poke the flags, so we need to copy the messageinfo */
433 if ((source->folder_flags & CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY)
434 && (minfo = camel_folder_get_message_info (source, uid))) {
435 info = camel_message_info_clone (minfo);
436 camel_folder_free_message_info (source, minfo);
438 info = camel_message_info_new_from_header (NULL, ((CamelMimePart *) msg)->headers);
440 /* unset deleted flag when transferring from trash folder */
441 if ((source->folder_flags & CAMEL_FOLDER_IS_TRASH) != 0)
442 camel_message_info_set_flags (info, CAMEL_MESSAGE_DELETED, 0);
443 /* unset junk flag when transferring from junk folder */
444 if ((source->folder_flags & CAMEL_FOLDER_IS_JUNK) != 0)
445 camel_message_info_set_flags (info, CAMEL_MESSAGE_JUNK, 0);
447 camel_folder_append_message_sync (
448 dest, msg, info, transferred_uid,
449 cancellable, &local_error);
450 g_object_unref (msg);
452 if (local_error != NULL)
453 g_propagate_error (error, local_error);
454 else if (delete_original)
455 camel_folder_set_message_flags (
456 source, uid, CAMEL_MESSAGE_DELETED |
457 CAMEL_MESSAGE_SEEN, ~0);
459 camel_message_info_free (info);
463 folder_set_parent_store (CamelFolder *folder,
464 CamelStore *parent_store)
466 g_return_if_fail (CAMEL_IS_STORE (parent_store));
467 g_return_if_fail (folder->priv->parent_store == NULL);
469 folder->priv->parent_store = parent_store;
471 g_object_add_weak_pointer (
472 G_OBJECT (parent_store), &folder->priv->parent_store);
476 folder_set_property (GObject *object,
481 switch (property_id) {
482 case PROP_DESCRIPTION:
483 camel_folder_set_description (
484 CAMEL_FOLDER (object),
485 g_value_get_string (value));
488 case PROP_DISPLAY_NAME:
489 camel_folder_set_display_name (
490 CAMEL_FOLDER (object),
491 g_value_get_string (value));
495 camel_folder_set_full_name (
496 CAMEL_FOLDER (object),
497 g_value_get_string (value));
500 case PROP_PARENT_STORE:
501 folder_set_parent_store (
502 CAMEL_FOLDER (object),
503 g_value_get_object (value));
507 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
511 folder_get_property (GObject *object,
516 switch (property_id) {
517 case PROP_DESCRIPTION:
518 g_value_take_string (
519 value, camel_folder_dup_description (
520 CAMEL_FOLDER (object)));
523 case PROP_DISPLAY_NAME:
524 g_value_take_string (
525 value, camel_folder_dup_display_name (
526 CAMEL_FOLDER (object)));
530 g_value_take_string (
531 value, camel_folder_dup_full_name (
532 CAMEL_FOLDER (object)));
535 case PROP_PARENT_STORE:
537 value, camel_folder_get_parent_store (
538 CAMEL_FOLDER (object)));
542 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
546 folder_dispose (GObject *object)
550 folder = CAMEL_FOLDER (object);
552 if (folder->priv->parent_store != NULL) {
553 g_object_remove_weak_pointer (
554 G_OBJECT (folder->priv->parent_store),
555 &folder->priv->parent_store);
556 folder->priv->parent_store = NULL;
559 if (folder->summary) {
560 g_object_unref (folder->summary);
561 folder->summary = NULL;
564 /* Chain up to parent's dispose () method. */
565 G_OBJECT_CLASS (camel_folder_parent_class)->dispose (object);
569 folder_finalize (GObject *object)
571 CamelFolderPrivate *priv;
573 priv = CAMEL_FOLDER_GET_PRIVATE (object);
575 g_mutex_clear (&priv->property_lock);
577 g_free (priv->full_name);
578 g_free (priv->display_name);
579 g_free (priv->description);
581 camel_folder_change_info_free (priv->changed_frozen);
583 if (priv->pending_changes != NULL)
584 camel_folder_change_info_free (priv->pending_changes);
586 g_rec_mutex_clear (&priv->lock);
587 g_mutex_clear (&priv->change_lock);
589 /* Chain up to parent's finalize () method. */
590 G_OBJECT_CLASS (camel_folder_parent_class)->finalize (object);
594 folder_get_message_count (CamelFolder *folder)
596 g_return_val_if_fail (folder->summary != NULL, -1);
598 return camel_folder_summary_count (folder->summary);
601 static CamelMessageFlags
602 folder_get_permanent_flags (CamelFolder *folder)
604 return folder->permanent_flags;
607 static CamelMessageFlags
608 folder_get_message_flags (CamelFolder *folder,
611 CamelMessageInfo *info;
612 CamelMessageFlags flags;
614 g_return_val_if_fail (folder->summary != NULL, 0);
616 info = camel_folder_summary_get (folder->summary, uid);
620 flags = camel_message_info_flags (info);
621 camel_message_info_free (info);
627 folder_set_message_flags (CamelFolder *folder,
629 CamelMessageFlags flags,
630 CamelMessageFlags set)
632 CamelMessageInfo *info;
635 g_return_val_if_fail (folder->summary != NULL, FALSE);
637 info = camel_folder_summary_get (folder->summary, uid);
641 res = camel_message_info_set_flags (info, flags, set);
642 camel_message_info_free (info);
648 folder_get_message_user_flag (CamelFolder *folder,
652 CamelMessageInfo *info;
655 g_return_val_if_fail (folder->summary != NULL, FALSE);
657 info = camel_folder_summary_get (folder->summary, uid);
661 ret = camel_message_info_user_flag (info, name);
662 camel_message_info_free (info);
668 folder_set_message_user_flag (CamelFolder *folder,
673 CamelMessageInfo *info;
675 g_return_if_fail (folder->summary != NULL);
677 info = camel_folder_summary_get (folder->summary, uid);
681 camel_message_info_set_user_flag (info, name, value);
682 camel_message_info_free (info);
686 folder_get_message_user_tag (CamelFolder *folder,
690 CamelMessageInfo *info;
693 g_return_val_if_fail (folder->summary != NULL, NULL);
695 info = camel_folder_summary_get (folder->summary, uid);
699 ret = camel_message_info_user_tag (info, name);
700 camel_message_info_free (info);
706 folder_set_message_user_tag (CamelFolder *folder,
711 CamelMessageInfo *info;
713 g_return_if_fail (folder->summary != NULL);
715 info = camel_folder_summary_get (folder->summary, uid);
719 camel_message_info_set_user_tag (info, name, value);
720 camel_message_info_free (info);
724 folder_get_uids (CamelFolder *folder)
726 g_return_val_if_fail (folder->summary != NULL, NULL);
728 return camel_folder_summary_get_array (folder->summary);
732 folder_get_uncached_uids (CamelFolder *folder,
739 result = g_ptr_array_new ();
741 g_ptr_array_set_size (result, uids->len);
742 for (i = 0; i < uids->len; i++)
744 (gpointer) camel_pstring_strdup (uids->pdata[i]);
750 folder_free_uids (CamelFolder *folder,
753 camel_folder_summary_free_array (array);
757 folder_cmp_uids (CamelFolder *folder,
761 g_return_val_if_fail (uid1 != NULL, 0);
762 g_return_val_if_fail (uid2 != NULL, 0);
764 return strtoul (uid1, NULL, 10) - strtoul (uid2, NULL, 10);
768 folder_sort_uids (CamelFolder *folder,
772 uids->pdata, uids->len,
773 sizeof (gpointer), cmp_array_uids, folder);
777 folder_get_summary (CamelFolder *folder)
779 g_return_val_if_fail (folder->summary != NULL, NULL);
781 return camel_folder_summary_get_array (folder->summary);
785 folder_free_summary (CamelFolder *folder,
788 camel_folder_summary_free_array (array);
792 folder_search_free (CamelFolder *folder,
797 for (i = 0; i < result->len; i++)
798 camel_pstring_free (g_ptr_array_index (result, i));
799 g_ptr_array_free (result, TRUE);
802 static CamelMessageInfo *
803 folder_get_message_info (CamelFolder *folder,
806 g_return_val_if_fail (folder->summary != NULL, NULL);
808 return camel_folder_summary_get (folder->summary, uid);
812 folder_ref_message_info (CamelFolder *folder,
813 CamelMessageInfo *info)
815 g_return_if_fail (folder->summary != NULL);
817 camel_message_info_ref (info);
821 folder_free_message_info (CamelFolder *folder,
822 CamelMessageInfo *info)
824 g_return_if_fail (folder->summary != NULL);
826 camel_message_info_free (info);
830 folder_delete (CamelFolder *folder)
833 camel_folder_summary_clear (folder->summary, NULL);
837 folder_rename (CamelFolder *folder,
842 d (printf ("CamelFolder:rename ('%s')\n", new));
844 camel_folder_set_full_name (folder, new);
846 tmp = strrchr (new, '/');
847 camel_folder_set_display_name (folder, (tmp != NULL) ? tmp + 1 : new);
851 folder_freeze (CamelFolder *folder)
853 g_return_if_fail (folder->priv->frozen >= 0);
855 camel_folder_lock (folder, CAMEL_FOLDER_CHANGE_LOCK);
857 folder->priv->frozen++;
859 g_object_freeze_notify (G_OBJECT (folder->summary));
861 d (printf ("freeze (%p '%s') = %d\n", folder, folder->full_name, folder->priv->frozen));
862 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
866 folder_thaw (CamelFolder *folder)
868 CamelFolderChangeInfo *info = NULL;
870 g_return_if_fail (folder->priv->frozen > 0);
872 camel_folder_lock (folder, CAMEL_FOLDER_CHANGE_LOCK);
874 folder->priv->frozen--;
876 g_object_thaw_notify (G_OBJECT (folder->summary));
878 d (printf ("thaw (%p '%s') = %d\n", folder, folder->full_name, folder->priv->frozen));
880 if (folder->priv->frozen == 0
881 && camel_folder_change_info_changed (folder->priv->changed_frozen)) {
882 info = folder->priv->changed_frozen;
883 folder->priv->changed_frozen = camel_folder_change_info_new ();
886 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
889 camel_folder_changed (folder, info);
890 camel_folder_change_info_free (info);
895 folder_is_frozen (CamelFolder *folder)
897 return folder->priv->frozen != 0;
901 folder_refresh_info_sync (CamelFolder *folder,
902 GCancellable *cancellable,
909 folder_transfer_messages_to_sync (CamelFolder *source,
912 gboolean delete_originals,
913 GPtrArray **transferred_uids,
914 GCancellable *cancellable,
917 gchar **ret_uid = NULL;
919 GError *local_error = NULL;
920 GCancellable *local_cancellable = camel_operation_new ();
921 gulong handler_id = 0;
923 if (transferred_uids) {
924 *transferred_uids = g_ptr_array_new ();
925 g_ptr_array_set_size (*transferred_uids, uids->len);
928 /* to not propagate status messages from sub-functions into UI */
930 handler_id = g_signal_connect_swapped (cancellable, "cancelled", G_CALLBACK (g_cancellable_cancel), local_cancellable);
932 if (delete_originals)
933 camel_operation_push_message (
934 cancellable, _("Moving messages"));
936 camel_operation_push_message (
937 cancellable, _("Copying messages"));
940 camel_folder_freeze (dest);
941 if (delete_originals)
942 camel_folder_freeze (source);
945 for (i = 0; i < uids->len && local_error == NULL; i++) {
946 if (transferred_uids)
947 ret_uid = (gchar **) &((*transferred_uids)->pdata[i]);
948 folder_transfer_message_to (
949 source, uids->pdata[i], dest, ret_uid,
950 delete_originals, local_cancellable, &local_error);
951 camel_operation_progress (
952 cancellable, i * 100 / uids->len);
956 camel_folder_thaw (dest);
957 if (delete_originals)
958 camel_folder_thaw (source);
961 camel_operation_pop_message (cancellable);
963 if (local_error != NULL)
964 g_propagate_error (error, local_error);
965 g_object_unref (local_cancellable);
967 g_signal_handler_disconnect (cancellable, handler_id);
973 folder_append_message_thread (GSimpleAsyncResult *simple,
975 GCancellable *cancellable)
977 AsyncContext *async_context;
978 GError *error = NULL;
980 async_context = g_simple_async_result_get_op_res_gpointer (simple);
982 camel_folder_append_message_sync (
983 CAMEL_FOLDER (object), async_context->message,
984 async_context->info, &async_context->message_uid,
985 cancellable, &error);
988 g_simple_async_result_take_error (simple, error);
992 folder_append_message (CamelFolder *folder,
993 CamelMimeMessage *message,
994 CamelMessageInfo *info,
996 GCancellable *cancellable,
997 GAsyncReadyCallback callback,
1000 GSimpleAsyncResult *simple;
1001 AsyncContext *async_context;
1003 async_context = g_slice_new0 (AsyncContext);
1004 async_context->message = g_object_ref (message);
1005 async_context->info = camel_message_info_ref (info);
1007 simple = g_simple_async_result_new (
1008 G_OBJECT (folder), callback,
1009 user_data, folder_append_message);
1011 g_simple_async_result_set_check_cancellable (simple, cancellable);
1013 g_simple_async_result_set_op_res_gpointer (
1014 simple, async_context, (GDestroyNotify) async_context_free);
1016 g_simple_async_result_run_in_thread (
1017 simple, folder_append_message_thread,
1018 io_priority, cancellable);
1020 g_object_unref (simple);
1024 folder_append_message_finish (CamelFolder *folder,
1025 GAsyncResult *result,
1026 gchar **appended_uid,
1029 GSimpleAsyncResult *simple;
1030 AsyncContext *async_context;
1032 g_return_val_if_fail (
1033 g_simple_async_result_is_valid (
1034 result, G_OBJECT (folder), folder_append_message), FALSE);
1036 simple = G_SIMPLE_ASYNC_RESULT (result);
1037 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1039 if (appended_uid != NULL) {
1040 *appended_uid = async_context->message_uid;
1041 async_context->message_uid = NULL;
1044 /* Assume success unless a GError is set. */
1045 return !g_simple_async_result_propagate_error (simple, error);
1049 folder_expunge_thread (GSimpleAsyncResult *simple,
1051 GCancellable *cancellable)
1053 GError *error = NULL;
1055 camel_folder_expunge_sync (
1056 CAMEL_FOLDER (object), cancellable, &error);
1059 g_simple_async_result_take_error (simple, error);
1063 folder_expunge (CamelFolder *folder,
1065 GCancellable *cancellable,
1066 GAsyncReadyCallback callback,
1069 GSimpleAsyncResult *simple;
1071 simple = g_simple_async_result_new (
1072 G_OBJECT (folder), callback, user_data, folder_expunge);
1074 g_simple_async_result_set_check_cancellable (simple, cancellable);
1076 g_simple_async_result_run_in_thread (
1077 simple, folder_expunge_thread, io_priority, cancellable);
1079 g_object_unref (simple);
1083 folder_expunge_finish (CamelFolder *folder,
1084 GAsyncResult *result,
1087 GSimpleAsyncResult *simple;
1089 g_return_val_if_fail (
1090 g_simple_async_result_is_valid (
1091 result, G_OBJECT (folder), folder_expunge), FALSE);
1093 simple = G_SIMPLE_ASYNC_RESULT (result);
1095 /* Assume success unless a GError is set. */
1096 return !g_simple_async_result_propagate_error (simple, error);
1100 fetch_messages_thread (GSimpleAsyncResult *simple,
1102 GCancellable *cancellable)
1104 AsyncContext *async_context;
1105 GError *error = NULL;
1107 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1109 async_context->success = camel_folder_fetch_messages_sync (
1110 CAMEL_FOLDER (object), async_context->fetch_type, async_context->limit, cancellable, &error);
1113 g_simple_async_result_take_error (simple, error);
1117 fetch_messages (CamelFolder *folder,
1118 CamelFetchType type,
1121 GCancellable *cancellable,
1122 GAsyncReadyCallback callback,
1125 GSimpleAsyncResult *simple;
1126 AsyncContext *async_context;
1128 async_context = g_slice_new0 (AsyncContext);
1129 async_context->fetch_type = type;
1130 async_context->limit = limit;
1132 simple = g_simple_async_result_new (
1133 G_OBJECT (folder), callback, user_data, fetch_messages);
1135 g_simple_async_result_set_check_cancellable (simple, cancellable);
1137 g_simple_async_result_set_op_res_gpointer (
1138 simple, async_context, (GDestroyNotify) async_context_free);
1140 g_simple_async_result_run_in_thread (
1141 simple, fetch_messages_thread, io_priority, cancellable);
1143 g_object_unref (simple);
1147 fetch_messages_finish (CamelFolder *folder,
1148 GAsyncResult *result,
1151 GSimpleAsyncResult *simple;
1152 AsyncContext *async_context;
1154 g_return_val_if_fail (
1155 g_simple_async_result_is_valid (
1156 result, G_OBJECT (folder), fetch_messages), FALSE);
1158 simple = G_SIMPLE_ASYNC_RESULT (result);
1159 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1161 /* Assume success unless a GError is set. */
1162 return !g_simple_async_result_propagate_error (simple, error)
1163 && async_context->success;
1167 folder_get_message_thread (GSimpleAsyncResult *simple,
1169 GCancellable *cancellable)
1171 AsyncContext *async_context;
1172 GError *error = NULL;
1174 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1176 async_context->message = camel_folder_get_message_sync (
1177 CAMEL_FOLDER (object), async_context->message_uid,
1178 cancellable, &error);
1181 g_simple_async_result_take_error (simple, error);
1185 folder_get_message (CamelFolder *folder,
1186 const gchar *message_uid,
1188 GCancellable *cancellable,
1189 GAsyncReadyCallback callback,
1192 GSimpleAsyncResult *simple;
1193 AsyncContext *async_context;
1195 async_context = g_slice_new0 (AsyncContext);
1196 async_context->message_uid = g_strdup (message_uid);
1198 simple = g_simple_async_result_new (
1199 G_OBJECT (folder), callback, user_data, folder_get_message);
1201 g_simple_async_result_set_check_cancellable (simple, cancellable);
1203 g_simple_async_result_set_op_res_gpointer (
1204 simple, async_context, (GDestroyNotify) async_context_free);
1206 g_simple_async_result_run_in_thread (
1207 simple, folder_get_message_thread, io_priority, cancellable);
1209 g_object_unref (simple);
1212 static CamelMimeMessage *
1213 folder_get_message_finish (CamelFolder *folder,
1214 GAsyncResult *result,
1217 GSimpleAsyncResult *simple;
1218 AsyncContext *async_context;
1220 g_return_val_if_fail (
1221 g_simple_async_result_is_valid (
1222 result, G_OBJECT (folder), folder_get_message), NULL);
1224 simple = G_SIMPLE_ASYNC_RESULT (result);
1225 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1227 if (g_simple_async_result_propagate_error (simple, error))
1230 return g_object_ref (async_context->message);
1234 folder_get_quota_info_thread (GSimpleAsyncResult *simple,
1236 GCancellable *cancellable)
1238 AsyncContext *async_context;
1239 GError *error = NULL;
1241 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1243 async_context->quota_info = camel_folder_get_quota_info_sync (
1244 CAMEL_FOLDER (object), cancellable, &error);
1247 g_simple_async_result_take_error (simple, error);
1250 static CamelFolderQuotaInfo *
1251 folder_get_quota_info_sync (CamelFolder *folder,
1252 GCancellable *cancellable,
1256 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
1257 _("Quota information not supported for folder '%s'"),
1258 camel_folder_get_display_name (folder));
1264 folder_get_quota_info (CamelFolder *folder,
1266 GCancellable *cancellable,
1267 GAsyncReadyCallback callback,
1270 GSimpleAsyncResult *simple;
1271 AsyncContext *async_context;
1273 async_context = g_slice_new0 (AsyncContext);
1275 simple = g_simple_async_result_new (
1276 G_OBJECT (folder), callback,
1277 user_data, folder_get_quota_info);
1279 g_simple_async_result_set_check_cancellable (simple, cancellable);
1281 g_simple_async_result_set_op_res_gpointer (
1282 simple, async_context, (GDestroyNotify) async_context_free);
1284 g_simple_async_result_run_in_thread (
1285 simple, folder_get_quota_info_thread,
1286 io_priority, cancellable);
1288 g_object_unref (simple);
1291 static CamelFolderQuotaInfo *
1292 folder_get_quota_info_finish (CamelFolder *folder,
1293 GAsyncResult *result,
1296 GSimpleAsyncResult *simple;
1297 AsyncContext *async_context;
1298 CamelFolderQuotaInfo *quota_info;
1300 g_return_val_if_fail (
1301 g_simple_async_result_is_valid (
1302 result, G_OBJECT (folder), folder_get_quota_info), NULL);
1304 simple = G_SIMPLE_ASYNC_RESULT (result);
1305 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1307 if (g_simple_async_result_propagate_error (simple, error))
1310 quota_info = async_context->quota_info;
1311 async_context->quota_info = NULL;
1317 purge_message_cache_thread (GSimpleAsyncResult *simple,
1319 GCancellable *cancellable)
1321 AsyncContext *async_context;
1322 GError *error = NULL;
1324 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1326 async_context->success = camel_folder_purge_message_cache_sync (
1327 CAMEL_FOLDER (object), async_context->start_uid, async_context->end_uid, cancellable, &error);
1330 g_simple_async_result_take_error (simple, error);
1334 purge_message_cache (CamelFolder *folder,
1338 GCancellable *cancellable,
1339 GAsyncReadyCallback callback,
1342 GSimpleAsyncResult *simple;
1343 AsyncContext *async_context;
1345 async_context = g_slice_new0 (AsyncContext);
1346 async_context->start_uid = g_strdup (start_uid);
1347 async_context->end_uid = g_strdup (end_uid);
1349 simple = g_simple_async_result_new (
1350 G_OBJECT (folder), callback, user_data, purge_message_cache);
1352 g_simple_async_result_set_check_cancellable (simple, cancellable);
1354 g_simple_async_result_set_op_res_gpointer (
1355 simple, async_context, (GDestroyNotify) async_context_free);
1357 g_simple_async_result_run_in_thread (
1358 simple, purge_message_cache_thread, io_priority, cancellable);
1360 g_object_unref (simple);
1364 purge_message_cache_finish (CamelFolder *folder,
1365 GAsyncResult *result,
1368 GSimpleAsyncResult *simple;
1369 AsyncContext *async_context;
1371 g_return_val_if_fail (
1372 g_simple_async_result_is_valid (
1373 result, G_OBJECT (folder), purge_message_cache), FALSE);
1375 simple = G_SIMPLE_ASYNC_RESULT (result);
1376 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1378 /* Assume success unless a GError is set. */
1379 return !g_simple_async_result_propagate_error (simple, error)
1380 && async_context->success;
1384 folder_refresh_info_thread (GSimpleAsyncResult *simple,
1386 GCancellable *cancellable)
1388 GError *error = NULL;
1390 camel_folder_refresh_info_sync (
1391 CAMEL_FOLDER (object), cancellable, &error);
1394 g_simple_async_result_take_error (simple, error);
1398 folder_refresh_info (CamelFolder *folder,
1400 GCancellable *cancellable,
1401 GAsyncReadyCallback callback,
1404 GSimpleAsyncResult *simple;
1406 simple = g_simple_async_result_new (
1407 G_OBJECT (folder), callback, user_data, folder_refresh_info);
1409 g_simple_async_result_set_check_cancellable (simple, cancellable);
1411 g_simple_async_result_run_in_thread (
1412 simple, folder_refresh_info_thread, io_priority, cancellable);
1414 g_object_unref (simple);
1418 folder_refresh_info_finish (CamelFolder *folder,
1419 GAsyncResult *result,
1422 GSimpleAsyncResult *simple;
1424 g_return_val_if_fail (
1425 g_simple_async_result_is_valid (
1426 result, G_OBJECT (folder), folder_refresh_info), FALSE);
1428 simple = G_SIMPLE_ASYNC_RESULT (result);
1430 /* Assume success unless a GError is set. */
1431 return !g_simple_async_result_propagate_error (simple, error);
1435 folder_synchronize_thread (GSimpleAsyncResult *simple,
1437 GCancellable *cancellable)
1439 AsyncContext *async_context;
1440 GError *error = NULL;
1442 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1444 camel_folder_synchronize_sync (
1445 CAMEL_FOLDER (object), async_context->expunge,
1446 cancellable, &error);
1449 g_simple_async_result_take_error (simple, error);
1453 folder_synchronize (CamelFolder *folder,
1456 GCancellable *cancellable,
1457 GAsyncReadyCallback callback,
1460 GSimpleAsyncResult *simple;
1461 AsyncContext *async_context;
1463 async_context = g_slice_new0 (AsyncContext);
1464 async_context->expunge = expunge;
1466 simple = g_simple_async_result_new (
1467 G_OBJECT (folder), callback, user_data, folder_synchronize);
1469 g_simple_async_result_set_check_cancellable (simple, cancellable);
1471 g_simple_async_result_set_op_res_gpointer (
1472 simple, async_context, (GDestroyNotify) async_context_free);
1474 g_simple_async_result_run_in_thread (
1475 simple, folder_synchronize_thread, io_priority, cancellable);
1477 g_object_unref (simple);
1481 folder_synchronize_finish (CamelFolder *folder,
1482 GAsyncResult *result,
1485 GSimpleAsyncResult *simple;
1487 g_return_val_if_fail (
1488 g_simple_async_result_is_valid (
1489 result, G_OBJECT (folder), folder_synchronize), FALSE);
1491 simple = G_SIMPLE_ASYNC_RESULT (result);
1493 /* Assume success unless a GError is set. */
1494 return !g_simple_async_result_propagate_error (simple, error);
1498 folder_synchronize_message_thread (GSimpleAsyncResult *simple,
1500 GCancellable *cancellable)
1502 AsyncContext *async_context;
1503 GError *error = NULL;
1505 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1507 camel_folder_synchronize_message_sync (
1508 CAMEL_FOLDER (object), async_context->message_uid,
1509 cancellable, &error);
1512 g_simple_async_result_take_error (simple, error);
1516 folder_synchronize_message (CamelFolder *folder,
1517 const gchar *message_uid,
1519 GCancellable *cancellable,
1520 GAsyncReadyCallback callback,
1523 GSimpleAsyncResult *simple;
1524 AsyncContext *async_context;
1526 async_context = g_slice_new0 (AsyncContext);
1527 async_context->message_uid = g_strdup (message_uid);
1529 simple = g_simple_async_result_new (
1530 G_OBJECT (folder), callback,
1531 user_data, folder_synchronize_message);
1533 g_simple_async_result_set_check_cancellable (simple, cancellable);
1535 g_simple_async_result_set_op_res_gpointer (
1536 simple, async_context, (GDestroyNotify) async_context_free);
1538 g_simple_async_result_run_in_thread (
1539 simple, folder_synchronize_message_thread,
1540 io_priority, cancellable);
1542 g_object_unref (simple);
1546 folder_synchronize_message_finish (CamelFolder *folder,
1547 GAsyncResult *result,
1550 GSimpleAsyncResult *simple;
1552 g_return_val_if_fail (
1553 g_simple_async_result_is_valid (
1554 result, G_OBJECT (folder),
1555 folder_synchronize_message), FALSE);
1557 simple = G_SIMPLE_ASYNC_RESULT (result);
1559 /* Assume success unless a GError is set. */
1560 return !g_simple_async_result_propagate_error (simple, error);
1564 folder_transfer_messages_to_thread (GSimpleAsyncResult *simple,
1566 GCancellable *cancellable)
1568 AsyncContext *async_context;
1569 GError *error = NULL;
1571 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1573 camel_folder_transfer_messages_to_sync (
1574 CAMEL_FOLDER (object), async_context->message_uids,
1575 async_context->destination, async_context->delete_originals,
1576 &async_context->transferred_uids, cancellable, &error);
1579 g_simple_async_result_take_error (simple, error);
1583 folder_transfer_messages_to (CamelFolder *source,
1584 GPtrArray *message_uids,
1585 CamelFolder *destination,
1586 gboolean delete_originals,
1588 GCancellable *cancellable,
1589 GAsyncReadyCallback callback,
1592 GSimpleAsyncResult *simple;
1593 AsyncContext *async_context;
1596 async_context = g_slice_new0 (AsyncContext);
1597 async_context->message_uids = g_ptr_array_new ();
1598 async_context->destination = g_object_ref (destination);
1599 async_context->delete_originals = delete_originals;
1601 for (ii = 0; ii < message_uids->len; ii++)
1603 async_context->message_uids,
1604 g_strdup (message_uids->pdata[ii]));
1606 simple = g_simple_async_result_new (
1607 G_OBJECT (source), callback,
1608 user_data, folder_transfer_messages_to);
1610 g_simple_async_result_set_check_cancellable (simple, cancellable);
1612 g_simple_async_result_set_op_res_gpointer (
1613 simple, async_context, (GDestroyNotify) async_context_free);
1615 g_simple_async_result_run_in_thread (
1616 simple, folder_transfer_messages_to_thread,
1617 io_priority, cancellable);
1619 g_object_unref (simple);
1623 folder_transfer_messages_to_finish (CamelFolder *source,
1624 GAsyncResult *result,
1625 GPtrArray **transferred_uids,
1628 GSimpleAsyncResult *simple;
1629 AsyncContext *async_context;
1631 g_return_val_if_fail (
1632 g_simple_async_result_is_valid (
1633 result, G_OBJECT (source),
1634 folder_transfer_messages_to), FALSE);
1636 simple = G_SIMPLE_ASYNC_RESULT (result);
1637 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1639 if (transferred_uids != NULL) {
1640 *transferred_uids = async_context->transferred_uids;
1641 async_context->transferred_uids = NULL;
1644 /* Assume success unless a GError is set. */
1645 return !g_simple_async_result_propagate_error (simple, error);
1648 /* Signal callback that stops emission when folder is frozen. */
1650 folder_changed (CamelFolder *folder,
1651 CamelFolderChangeInfo *info)
1653 CamelStore *parent_store;
1654 struct _CamelFolderChangeInfoPrivate *p = info->priv;
1655 CamelSession *session;
1656 CamelFilterDriver *driver = NULL;
1657 CamelJunkFilter *junk_filter;
1658 GPtrArray *junk = NULL;
1659 GPtrArray *notjunk = NULL;
1660 GPtrArray *recents = NULL;
1663 g_return_if_fail (info != NULL);
1665 parent_store = camel_folder_get_parent_store (folder);
1666 session = camel_service_get_session (CAMEL_SERVICE (parent_store));
1667 junk_filter = camel_session_get_junk_filter (session);
1669 camel_folder_lock (folder, CAMEL_FOLDER_CHANGE_LOCK);
1670 if (folder->priv->frozen) {
1671 camel_folder_change_info_cat (folder->priv->changed_frozen, info);
1672 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
1673 g_signal_stop_emission (folder, signals[CHANGED], 0);
1676 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
1678 if (junk_filter != NULL && info->uid_changed->len) {
1679 CamelMessageFlags flags;
1681 for (i = 0; i < info->uid_changed->len; i++) {
1682 flags = camel_folder_get_message_flags (folder, info->uid_changed->pdata[i]);
1683 if (flags & CAMEL_MESSAGE_JUNK_LEARN) {
1684 if (flags & CAMEL_MESSAGE_JUNK) {
1686 junk = g_ptr_array_new ();
1687 g_ptr_array_add (junk, g_strdup (info->uid_changed->pdata[i]));
1690 notjunk = g_ptr_array_new ();
1691 g_ptr_array_add (notjunk, g_strdup (info->uid_changed->pdata[i]));
1693 /* reset junk learn flag so that we don't process it again*/
1694 camel_folder_set_message_flags (
1695 folder, info->uid_changed->pdata[i],
1696 CAMEL_MESSAGE_JUNK_LEARN, 0);
1701 if ((folder->folder_flags & (CAMEL_FOLDER_FILTER_RECENT | CAMEL_FOLDER_FILTER_JUNK))
1702 && p->uid_filter->len > 0)
1703 driver = camel_session_get_filter_driver (
1705 (folder->folder_flags & CAMEL_FOLDER_FILTER_RECENT)
1706 ? "incoming" : "junktest", NULL);
1709 recents = g_ptr_array_new ();
1710 for (i = 0; i < p->uid_filter->len; i++)
1711 g_ptr_array_add (recents, g_strdup (p->uid_filter->pdata[i]));
1713 g_ptr_array_set_size (p->uid_filter, 0);
1716 if (driver || junk || notjunk) {
1717 FolderFilterData *data;
1719 data = g_slice_new0 (FolderFilterData);
1720 data->recents = recents;
1722 data->notjunk = notjunk;
1723 data->folder = g_object_ref (folder);
1724 data->driver = driver;
1726 camel_folder_freeze (folder);
1728 /* Copy changes back to changed_frozen list to retain
1729 * them while we are filtering */
1730 camel_folder_lock (folder, CAMEL_FOLDER_CHANGE_LOCK);
1731 camel_folder_change_info_cat (
1732 folder->priv->changed_frozen, info);
1733 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
1735 camel_session_submit_job (
1736 session, (CamelSessionCallback) folder_filter,
1737 data, (GDestroyNotify) folder_filter_data_free);
1739 g_signal_stop_emission (folder, signals[CHANGED], 0);
1744 camel_folder_class_init (CamelFolderClass *class)
1746 GObjectClass *object_class;
1748 g_type_class_add_private (class, sizeof (CamelFolderPrivate));
1750 object_class = G_OBJECT_CLASS (class);
1751 object_class->set_property = folder_set_property;
1752 object_class->get_property = folder_get_property;
1753 object_class->dispose = folder_dispose;
1754 object_class->finalize = folder_finalize;
1756 class->get_message_count = folder_get_message_count;
1757 class->get_permanent_flags = folder_get_permanent_flags;
1758 class->get_message_flags = folder_get_message_flags;
1759 class->set_message_flags = folder_set_message_flags;
1760 class->get_message_user_flag = folder_get_message_user_flag;
1761 class->set_message_user_flag = folder_set_message_user_flag;
1762 class->get_message_user_tag = folder_get_message_user_tag;
1763 class->set_message_user_tag = folder_set_message_user_tag;
1764 class->get_uids = folder_get_uids;
1765 class->get_uncached_uids = folder_get_uncached_uids;
1766 class->free_uids = folder_free_uids;
1767 class->cmp_uids = folder_cmp_uids;
1768 class->sort_uids = folder_sort_uids;
1769 class->get_summary = folder_get_summary;
1770 class->free_summary = folder_free_summary;
1771 class->search_free = folder_search_free;
1772 class->get_message_info = folder_get_message_info;
1773 class->ref_message_info = folder_ref_message_info;
1774 class->free_message_info = folder_free_message_info;
1775 class->delete_ = folder_delete;
1776 class->rename = folder_rename;
1777 class->freeze = folder_freeze;
1778 class->thaw = folder_thaw;
1779 class->is_frozen = folder_is_frozen;
1780 class->get_quota_info_sync = folder_get_quota_info_sync;
1781 class->refresh_info_sync = folder_refresh_info_sync;
1782 class->transfer_messages_to_sync = folder_transfer_messages_to_sync;
1783 class->changed = folder_changed;
1785 class->append_message = folder_append_message;
1786 class->append_message_finish = folder_append_message_finish;
1787 class->expunge = folder_expunge;
1788 class->expunge_finish = folder_expunge_finish;
1789 class->fetch_messages= fetch_messages;
1790 class->fetch_messages_finish = fetch_messages_finish;
1791 class->get_message = folder_get_message;
1792 class->get_message_finish = folder_get_message_finish;
1793 class->get_quota_info = folder_get_quota_info;
1794 class->get_quota_info_finish = folder_get_quota_info_finish;
1795 class->purge_message_cache= purge_message_cache;
1796 class->purge_message_cache_finish = purge_message_cache_finish;
1797 class->refresh_info = folder_refresh_info;
1798 class->refresh_info_finish = folder_refresh_info_finish;
1799 class->synchronize = folder_synchronize;
1800 class->synchronize_finish = folder_synchronize_finish;
1801 class->synchronize_message = folder_synchronize_message;
1802 class->synchronize_message_finish = folder_synchronize_message_finish;
1803 class->transfer_messages_to = folder_transfer_messages_to;
1804 class->transfer_messages_to_finish = folder_transfer_messages_to_finish;
1807 * CamelFolder:description
1809 * The folder's description.
1811 g_object_class_install_property (
1814 g_param_spec_string (
1817 "The folder's description",
1820 G_PARAM_CONSTRUCT));
1823 * CamelFolder:display-name
1825 * The folder's display name.
1827 g_object_class_install_property (
1830 g_param_spec_string (
1833 "The folder's display name",
1836 G_PARAM_CONSTRUCT));
1839 * CamelFolder:full-name
1841 * The folder's fully qualified name.
1843 g_object_class_install_property (
1846 g_param_spec_string (
1849 "The folder's fully qualified name",
1852 G_PARAM_CONSTRUCT));
1855 * CamelFolder:parent-store
1857 * The #CamelStore to which the folder belongs.
1859 g_object_class_install_property (
1862 g_param_spec_object (
1865 "The store to which the folder belongs",
1868 G_PARAM_CONSTRUCT_ONLY));
1871 * CamelFolder::changed
1872 * @folder: the #CamelFolder which emitted the signal
1874 signals[CHANGED] = g_signal_new (
1876 G_OBJECT_CLASS_TYPE (class),
1878 G_STRUCT_OFFSET (CamelFolderClass, changed),
1880 g_cclosure_marshal_VOID__POINTER,
1885 * CamelFolder::deleted
1886 * @folder: the #CamelFolder which emitted the signal
1888 signals[DELETED] = g_signal_new (
1890 G_OBJECT_CLASS_TYPE (class),
1892 G_STRUCT_OFFSET (CamelFolderClass, deleted),
1894 g_cclosure_marshal_VOID__VOID,
1898 * CamelFolder::renamed
1899 * @folder: the #CamelFolder which emitted the signal
1900 * @old_name: the previous folder name
1902 signals[RENAMED] = g_signal_new (
1904 G_OBJECT_CLASS_TYPE (class),
1906 G_STRUCT_OFFSET (CamelFolderClass, renamed),
1908 g_cclosure_marshal_VOID__STRING,
1914 camel_folder_init (CamelFolder *folder)
1916 folder->priv = CAMEL_FOLDER_GET_PRIVATE (folder);
1917 folder->priv->frozen = 0;
1918 folder->priv->changed_frozen = camel_folder_change_info_new ();
1920 g_rec_mutex_init (&folder->priv->lock);
1921 g_mutex_init (&folder->priv->change_lock);
1922 g_mutex_init (&folder->priv->property_lock);
1925 G_DEFINE_QUARK (camel-folder-error-quark, camel_folder_error)
1928 * camel_folder_set_lock_async:
1929 * @folder: a #CamelFolder
1930 * @skip_folder_lock:
1932 * FIXME Document me!
1937 camel_folder_set_lock_async (CamelFolder *folder,
1938 gboolean skip_folder_lock)
1940 g_return_if_fail (CAMEL_IS_FOLDER (folder));
1942 folder->priv->skip_folder_lock = skip_folder_lock;
1946 * camel_folder_get_filename:
1951 camel_folder_get_filename (CamelFolder *folder,
1955 CamelFolderClass *class;
1958 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
1959 g_return_val_if_fail (uid != NULL, NULL);
1961 class = CAMEL_FOLDER_GET_CLASS (folder);
1962 g_return_val_if_fail (class->get_filename != NULL, NULL);
1964 filename = class->get_filename (folder, uid, error);
1965 CAMEL_CHECK_GERROR (folder, get_filename, filename != NULL, error);
1971 * camel_folder_get_full_name:
1972 * @folder: a #CamelFolder
1974 * Returns the fully qualified name of the folder.
1976 * Returns: the fully qualified name of the folder
1979 camel_folder_get_full_name (CamelFolder *folder)
1981 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
1983 return folder->priv->full_name;
1987 * camel_folder_dup_full_name:
1988 * @folder: a #CamelFolder
1990 * Thread-safe variation of camel_folder_get_full_name().
1991 * Use this function when accessing @folder from multiple threads.
1993 * The returned string should be freed with g_free() when no longer needed.
1995 * Returns: a newly-allocated copy of #CamelFolder:full-name
2000 camel_folder_dup_full_name (CamelFolder *folder)
2002 const gchar *protected;
2005 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2007 g_mutex_lock (&folder->priv->property_lock);
2009 protected = camel_folder_get_full_name (folder);
2010 duplicate = g_strdup (protected);
2012 g_mutex_unlock (&folder->priv->property_lock);
2018 * camel_folder_set_full_name:
2019 * @folder: a #CamelFolder
2020 * @full_name: a fully qualified name for the folder
2022 * Sets the fully qualified name of the folder.
2027 camel_folder_set_full_name (CamelFolder *folder,
2028 const gchar *full_name)
2030 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2032 g_mutex_lock (&folder->priv->property_lock);
2034 if (g_strcmp0 (folder->priv->full_name, full_name) == 0) {
2035 g_mutex_unlock (&folder->priv->property_lock);
2039 g_free (folder->priv->full_name);
2040 folder->priv->full_name = g_strdup (full_name);
2042 g_mutex_unlock (&folder->priv->property_lock);
2044 g_object_notify (G_OBJECT (folder), "full-name");
2048 * camel_folder_get_display_name:
2049 * @folder: a #CamelFolder
2051 * Returns the display name for the folder. The fully qualified name
2052 * can be obtained with camel_folder_get_full_name().
2054 * Returns: the display name of the folder
2059 camel_folder_get_display_name (CamelFolder *folder)
2061 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2063 return folder->priv->display_name;
2067 * camel_folder_dup_display_name:
2068 * @folder: a #CamelFolder
2070 * Thread-safe variation of camel_folder_get_display_name().
2071 * Use this function when accessing @folder from multiple threads.
2073 * The returned string should be freed with g_free() when no longer needed.
2075 * Returns: a newly-allocated copy of #CamelFolder:display-name
2080 camel_folder_dup_display_name (CamelFolder *folder)
2082 const gchar *protected;
2085 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2087 g_mutex_lock (&folder->priv->property_lock);
2089 protected = camel_folder_get_display_name (folder);
2090 duplicate = g_strdup (protected);
2092 g_mutex_unlock (&folder->priv->property_lock);
2098 * camel_folder_set_display_name:
2099 * @folder: a #CamelFolder
2100 * @display_name: a display name for the folder
2102 * Sets the display name for the folder.
2107 camel_folder_set_display_name (CamelFolder *folder,
2108 const gchar *display_name)
2110 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2112 g_mutex_lock (&folder->priv->property_lock);
2114 if (g_strcmp0 (folder->priv->display_name, display_name) == 0) {
2115 g_mutex_unlock (&folder->priv->property_lock);
2119 g_free (folder->priv->display_name);
2120 folder->priv->display_name = g_strdup (display_name);
2122 g_mutex_unlock (&folder->priv->property_lock);
2124 g_object_notify (G_OBJECT (folder), "display-name");
2128 * camel_folder_get_description:
2129 * @folder: a #CamelFolder
2131 * Returns a description of the folder suitable for displaying to the user.
2133 * Returns: a description of the folder
2138 camel_folder_get_description (CamelFolder *folder)
2140 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2142 /* Default to full-name if there's no custom description. */
2143 if (folder->priv->description == NULL)
2144 return camel_folder_get_full_name (folder);
2146 return folder->priv->description;
2150 * camel_folder_dup_description:
2151 * @folder: a #CamelFolder
2153 * Thread-safe variation of camel_folder_get_description().
2154 * Use this function when accessing @folder from multiple threads.
2156 * The returned string should be freed with g_free() when no longer needed.
2158 * Returns: a newly-allocated copy of #CamelFolder:description
2163 camel_folder_dup_description (CamelFolder *folder)
2165 const gchar *protected;
2168 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2170 g_mutex_lock (&folder->priv->property_lock);
2172 protected = camel_folder_get_description (folder);
2173 duplicate = g_strdup (protected);
2175 g_mutex_unlock (&folder->priv->property_lock);
2181 * camel_folder_set_description:
2182 * @folder: a #CamelFolder
2183 * @description: a description of the folder
2185 * Sets a description of the folder suitable for displaying to the user.
2190 camel_folder_set_description (CamelFolder *folder,
2191 const gchar *description)
2193 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2195 g_mutex_lock (&folder->priv->property_lock);
2197 if (g_strcmp0 (folder->priv->description, description) == 0) {
2198 g_mutex_unlock (&folder->priv->property_lock);
2202 g_free (folder->priv->description);
2203 folder->priv->description = g_strdup (description);
2205 g_mutex_unlock (&folder->priv->property_lock);
2207 g_object_notify (G_OBJECT (folder), "description");
2211 * camel_folder_get_parent_store:
2212 * @folder: a #CamelFolder
2214 * Returns: the parent #CamelStore of the folder
2217 camel_folder_get_parent_store (CamelFolder *folder)
2219 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2221 return CAMEL_STORE (folder->priv->parent_store);
2225 * camel_folder_get_message_count:
2226 * @folder: a #CamelFolder
2228 * Returns: the number of messages in the folder, or %-1 if unknown
2231 camel_folder_get_message_count (CamelFolder *folder)
2233 CamelFolderClass *class;
2235 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
2237 class = CAMEL_FOLDER_GET_CLASS (folder);
2238 g_return_val_if_fail (class->get_message_count != NULL, -1);
2240 return class->get_message_count (folder);
2244 * camel_folder_get_unread_message_count:
2245 * @folder: a #CamelFolder
2247 * DEPRECATED: use camel_object_get() instead.
2249 * Returns: the number of unread messages in the folder, or %-1 if
2253 camel_folder_get_unread_message_count (CamelFolder *folder)
2255 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
2256 g_return_val_if_fail (folder->summary != NULL, -1);
2258 return camel_folder_summary_get_unread_count (folder->summary);
2262 * camel_folder_get_deleted_message_count:
2263 * @folder: a #CamelFolder
2265 * Returns: the number of deleted messages in the folder, or %-1 if
2269 camel_folder_get_deleted_message_count (CamelFolder *folder)
2271 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
2272 g_return_val_if_fail (folder->summary != NULL, -1);
2274 return camel_folder_summary_get_deleted_count (folder->summary);
2278 * camel_folder_get_permanent_flags:
2279 * @folder: a #CamelFolder
2281 * Returns: the set of #CamelMessageFlags that can be permanently
2282 * stored on a message between sessions. If it includes
2283 * #CAMEL_FLAG_USER, then user-defined flags will be remembered.
2286 camel_folder_get_permanent_flags (CamelFolder *folder)
2288 CamelFolderClass *class;
2290 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
2292 class = CAMEL_FOLDER_GET_CLASS (folder);
2293 g_return_val_if_fail (class->get_permanent_flags != NULL, 0);
2295 return class->get_permanent_flags (folder);
2299 * camel_folder_get_message_flags:
2300 * @folder: a #CamelFolder
2301 * @uid: the UID of a message in @folder
2303 * Deprecated: Use camel_folder_get_message_info() instead.
2305 * Returns: the #CamelMessageFlags that are set on the indicated
2309 camel_folder_get_message_flags (CamelFolder *folder,
2312 CamelFolderClass *class;
2314 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
2315 g_return_val_if_fail (uid != NULL, 0);
2317 class = CAMEL_FOLDER_GET_CLASS (folder);
2318 g_return_val_if_fail (class->get_message_flags != NULL, 0);
2320 return class->get_message_flags (folder, uid);
2324 * camel_folder_set_message_flags:
2325 * @folder: a #CamelFolder
2326 * @uid: the UID of a message in @folder
2327 * @flags: a set of #CamelMessageFlag values to set
2328 * @set: the mask of values in @flags to use.
2330 * Sets those flags specified by @flags to the values specified by @set
2331 * on the indicated message. (This may or may not persist after the
2332 * folder or store is closed. See camel_folder_get_permanent_flags())
2334 * E.g. to set the deleted flag and clear the draft flag, use
2335 * camel_folder_set_message_flags (folder, uid, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_DRAFT, CAMEL_MESSAGE_DELETED);
2337 * DEPRECATED: Use camel_message_info_set_flags() on the message info directly
2340 * Returns: %TRUE if the flags were changed or %FALSE otherwise
2343 camel_folder_set_message_flags (CamelFolder *folder,
2345 CamelMessageFlags flags,
2346 CamelMessageFlags set)
2348 CamelFolderClass *class;
2350 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
2351 g_return_val_if_fail (uid != NULL, FALSE);
2353 class = CAMEL_FOLDER_GET_CLASS (folder);
2354 g_return_val_if_fail (class->set_message_flags != NULL, FALSE);
2356 if ((flags & (CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_JUNK_LEARN)) == CAMEL_MESSAGE_JUNK) {
2357 flags |= CAMEL_MESSAGE_JUNK_LEARN;
2358 set &= ~CAMEL_MESSAGE_JUNK_LEARN;
2361 return class->set_message_flags (folder, uid, flags, set);
2365 * camel_folder_get_message_user_flag:
2366 * @folder: a #CamelFolder
2367 * @uid: the UID of a message in @folder
2368 * @name: the name of a user flag
2370 * DEPRECATED: Use camel_message_info_get_user_flag() on the message
2373 * Returns: %TRUE if the given user flag is set on the message or
2377 camel_folder_get_message_user_flag (CamelFolder *folder,
2381 CamelFolderClass *class;
2383 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
2384 g_return_val_if_fail (uid != NULL, 0);
2385 g_return_val_if_fail (name != NULL, 0);
2387 class = CAMEL_FOLDER_GET_CLASS (folder);
2388 g_return_val_if_fail (class->get_message_user_flag != NULL, 0);
2390 return class->get_message_user_flag (folder, uid, name);
2394 * camel_folder_set_message_user_flag:
2395 * @folder: a #CamelFolder
2396 * @uid: the UID of a message in @folder
2397 * @name: the name of the user flag to set
2398 * @value: the value to set it to
2400 * DEPRECATED: Use camel_message_info_set_user_flag() on the
2401 * #CamelMessageInfo directly (when it works)
2403 * Sets the user flag specified by @name to the value specified by @value
2404 * on the indicated message. (This may or may not persist after the
2405 * folder or store is closed. See camel_folder_get_permanent_flags())
2408 camel_folder_set_message_user_flag (CamelFolder *folder,
2413 CamelFolderClass *class;
2415 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2416 g_return_if_fail (uid != NULL);
2417 g_return_if_fail (name != NULL);
2419 class = CAMEL_FOLDER_GET_CLASS (folder);
2420 g_return_if_fail (class->set_message_user_flag != NULL);
2422 class->set_message_user_flag (folder, uid, name, value);
2426 * camel_folder_get_message_user_tag:
2427 * @folder: a #CamelFolder
2428 * @uid: the UID of a message in @folder
2429 * @name: the name of a user tag
2431 * DEPRECATED: Use camel_message_info_get_user_tag() on the
2432 * #CamelMessageInfo directly.
2434 * Returns: the value of the user tag
2437 camel_folder_get_message_user_tag (CamelFolder *folder,
2441 CamelFolderClass *class;
2443 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2444 g_return_val_if_fail (uid != NULL, NULL);
2445 g_return_val_if_fail (name != NULL, NULL);
2447 class = CAMEL_FOLDER_GET_CLASS (folder);
2448 g_return_val_if_fail (class->get_message_user_tag != NULL, NULL);
2450 /* FIXME: should duplicate string */
2451 return class->get_message_user_tag (folder, uid, name);
2455 * camel_folder_set_message_user_tag:
2456 * @folder: a #CamelFolder
2457 * @uid: the UID of a message in @folder
2458 * @name: the name of the user tag to set
2459 * @value: the value to set it to
2461 * DEPRECATED: Use camel_message_info_set_user_tag() on the
2462 * #CamelMessageInfo directly (when it works).
2464 * Sets the user tag specified by @name to the value specified by @value
2465 * on the indicated message. (This may or may not persist after the
2466 * folder or store is closed. See camel_folder_get_permanent_flags())
2469 camel_folder_set_message_user_tag (CamelFolder *folder,
2474 CamelFolderClass *class;
2476 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2477 g_return_if_fail (uid != NULL);
2478 g_return_if_fail (name != NULL);
2480 class = CAMEL_FOLDER_GET_CLASS (folder);
2481 g_return_if_fail (class->set_message_user_tag != NULL);
2483 class->set_message_user_tag (folder, uid, name, value);
2487 * camel_folder_get_message_info:
2488 * @folder: a #CamelFolder
2489 * @uid: the uid of a message
2491 * Retrieve the #CamelMessageInfo for the specified @uid. This return
2492 * must be freed using camel_folder_free_message_info().
2494 * Returns: the summary information for the indicated message, or %NULL
2495 * if the uid does not exist
2498 camel_folder_get_message_info (CamelFolder *folder,
2501 CamelFolderClass *class;
2503 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2504 g_return_val_if_fail (uid != NULL, NULL);
2506 class = CAMEL_FOLDER_GET_CLASS (folder);
2507 g_return_val_if_fail (class->get_message_info != NULL, NULL);
2509 return class->get_message_info (folder, uid);
2513 * camel_folder_free_message_info:
2514 * @folder: a #CamelFolder
2515 * @info: a #CamelMessageInfo
2517 * Free (unref) a #CamelMessageInfo, previously obtained with
2518 * camel_folder_get_message_info().
2521 camel_folder_free_message_info (CamelFolder *folder,
2522 CamelMessageInfo *info)
2524 CamelFolderClass *class;
2526 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2527 g_return_if_fail (info != NULL);
2529 class = CAMEL_FOLDER_GET_CLASS (folder);
2530 g_return_if_fail (class->free_message_info != NULL);
2532 class->free_message_info (folder, info);
2536 * camel_folder_ref_message_info:
2537 * @folder: a #CamelFolder
2538 * @info: a #CamelMessageInfo
2540 * DEPRECATED: Use camel_message_info_ref() directly.
2542 * Ref a #CamelMessageInfo, previously obtained with
2543 * camel_folder_get_message_info().
2546 camel_folder_ref_message_info (CamelFolder *folder,
2547 CamelMessageInfo *info)
2549 CamelFolderClass *class;
2551 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2552 g_return_if_fail (info != NULL);
2554 class = CAMEL_FOLDER_GET_CLASS (folder);
2555 g_return_if_fail (class->ref_message_info != NULL);
2557 class->ref_message_info (folder, info);
2560 /* TODO: is this function required anyway? */
2562 * camel_folder_has_summary_capability:
2563 * @folder: a #CamelFolder
2565 * Get whether or not the folder has a summary.
2567 * Returns: %TRUE if a summary is available or %FALSE otherwise
2570 camel_folder_has_summary_capability (CamelFolder *folder)
2572 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
2574 return folder->folder_flags & CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY;
2580 * camel_folder_get_uids:
2581 * @folder: a #CamelFolder
2583 * Get the list of UIDs available in a folder. This routine is useful
2584 * for finding what messages are available when the folder does not
2585 * support summaries. The returned array should not be modified, and
2586 * must be freed by passing it to camel_folder_free_uids().
2588 * Returns: a GPtrArray of UIDs corresponding to the messages available
2592 camel_folder_get_uids (CamelFolder *folder)
2594 CamelFolderClass *class;
2596 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2598 class = CAMEL_FOLDER_GET_CLASS (folder);
2599 g_return_val_if_fail (class->get_uids != NULL, NULL);
2601 return class->get_uids (folder);
2605 * camel_folder_free_uids:
2606 * @folder: a #CamelFolder
2607 * @array: the array of uids to free
2609 * Frees the array of UIDs returned by camel_folder_get_uids().
2612 camel_folder_free_uids (CamelFolder *folder,
2615 CamelFolderClass *class;
2617 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2618 g_return_if_fail (array != NULL);
2620 class = CAMEL_FOLDER_GET_CLASS (folder);
2621 g_return_if_fail (class->free_uids != NULL);
2623 class->free_uids (folder, array);
2627 * camel_folder_get_uncached_uids:
2628 * @folder: a #CamelFolder
2629 * @uids: the array of uids to filter down to uncached ones.
2631 * Returns the known-uncached uids from a list of uids. It may return uids
2632 * which are locally cached but should never filter out a uid which is not
2633 * locally cached. Free the result by called camel_folder_free_uids().
2634 * Frees the array of UIDs returned by camel_folder_get_uids().
2639 camel_folder_get_uncached_uids (CamelFolder *folder,
2643 CamelFolderClass *class;
2644 GPtrArray *uncached_uids;
2646 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2647 g_return_val_if_fail (uids != NULL, NULL);
2649 class = CAMEL_FOLDER_GET_CLASS (folder);
2650 g_return_val_if_fail (class->get_uncached_uids != NULL, NULL);
2652 uncached_uids = class->get_uncached_uids (folder, uids, error);
2653 CAMEL_CHECK_GERROR (folder, get_uncached_uids, uncached_uids != NULL, error);
2655 return uncached_uids;
2659 * camel_folder_cmp_uids:
2660 * @folder: a #CamelFolder
2661 * @uid1: The first uid.
2662 * @uid2: the second uid.
2664 * Compares two uids. The return value meaning is the same as in any other compare function.
2666 * Note that the default compare function expects a decimal number at the beginning of a uid,
2667 * thus if provider uses different uid values, then it should subclass this function.
2672 camel_folder_cmp_uids (CamelFolder *folder,
2676 CamelFolderClass *class;
2678 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
2679 g_return_val_if_fail (uid1 != NULL, 0);
2680 g_return_val_if_fail (uid2 != NULL, 0);
2682 class = CAMEL_FOLDER_GET_CLASS (folder);
2683 g_return_val_if_fail (class->cmp_uids != NULL, 0);
2685 return class->cmp_uids (folder, uid1, uid2);
2689 * camel_folder_sort_uids:
2690 * @folder: a #CamelFolder
2691 * @uids: array of uids
2693 * Sorts the array of UIDs.
2698 camel_folder_sort_uids (CamelFolder *folder,
2701 CamelFolderClass *class;
2703 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2704 g_return_if_fail (uids != NULL);
2706 class = CAMEL_FOLDER_GET_CLASS (folder);
2707 g_return_if_fail (class->sort_uids != NULL);
2709 class->sort_uids (folder, uids);
2713 * camel_folder_get_summary:
2714 * @folder: a #CamelFolder
2716 * This returns the summary information for the folder. This array
2717 * should not be modified, and must be freed with
2718 * camel_folder_free_summary().
2720 * Returns: an array of #CamelMessageInfo
2723 camel_folder_get_summary (CamelFolder *folder)
2725 CamelFolderClass *class;
2727 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2729 class = CAMEL_FOLDER_GET_CLASS (folder);
2730 g_return_val_if_fail (class->get_summary != NULL, NULL);
2732 return class->get_summary (folder);
2736 * camel_folder_free_summary:
2737 * @folder: a #CamelFolder
2738 * @array: the summary array to free
2740 * Frees the summary array returned by camel_folder_get_summary().
2743 camel_folder_free_summary (CamelFolder *folder,
2746 CamelFolderClass *class;
2748 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2749 g_return_if_fail (array != NULL);
2751 class = CAMEL_FOLDER_GET_CLASS (folder);
2752 g_return_if_fail (class->free_summary != NULL);
2754 class->free_summary (folder, array);
2758 * camel_folder_search_by_expression:
2759 * @folder: a #CamelFolder
2760 * @expr: a search expression
2761 * @cancellable: a #GCancellable
2762 * @error: return location for a #GError, or %NULL
2764 * Searches the folder for messages matching the given search expression.
2766 * Returns: a #GPtrArray of uids of matching messages. The caller must
2767 * free the list and each of the elements when it is done.
2770 camel_folder_search_by_expression (CamelFolder *folder,
2771 const gchar *expression,
2772 GCancellable *cancellable,
2775 CamelFolderClass *class;
2778 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2780 class = CAMEL_FOLDER_GET_CLASS (folder);
2781 g_return_val_if_fail (class->search_by_expression != NULL, NULL);
2783 /* NOTE: that it is upto the callee to CAMEL_FOLDER_REC_LOCK */
2785 matches = class->search_by_expression (folder, expression, cancellable, error);
2786 CAMEL_CHECK_GERROR (folder, search_by_expression, matches != NULL, error);
2792 * camel_folder_count_by_expression:
2793 * @folder: a #CamelFolder
2794 * @expression: a search expression
2795 * @cancellable: a #GCancellable
2796 * @error: return location for a #GError, or %NULL
2798 * Searches the folder for count of messages matching the given search expression.
2800 * Returns: an interger
2805 camel_folder_count_by_expression (CamelFolder *folder,
2806 const gchar *expression,
2807 GCancellable *cancellable,
2810 CamelFolderClass *class;
2812 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
2814 class = CAMEL_FOLDER_GET_CLASS (folder);
2815 g_return_val_if_fail (class->count_by_expression != NULL, 0);
2817 /* NOTE: that it is upto the callee to CAMEL_FOLDER_REC_LOCK */
2819 return class->count_by_expression (folder, expression, cancellable, error);
2823 * camel_folder_search_by_uids:
2824 * @folder: a #CamelFolder
2825 * @expr: search expression
2826 * @uids: array of uid's to match against.
2827 * @cancellable: a #GCancellable
2828 * @error: return location for a #GError, or %NULL
2830 * Search a subset of uid's for an expression match.
2832 * Returns: a #GPtrArray of uids of matching messages. The caller must
2833 * free the list and each of the elements when it is done.
2836 camel_folder_search_by_uids (CamelFolder *folder,
2839 GCancellable *cancellable,
2842 CamelFolderClass *class;
2845 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
2847 class = CAMEL_FOLDER_GET_CLASS (folder);
2848 g_return_val_if_fail (class->search_by_uids != NULL, NULL);
2850 /* NOTE: that it is upto the callee to CAMEL_FOLDER_REC_LOCK */
2852 matches = class->search_by_uids (folder, expr, uids, cancellable, error);
2853 CAMEL_CHECK_GERROR (folder, search_by_uids, matches != NULL, error);
2859 * camel_folder_search_free:
2860 * @folder: a #CamelFolder
2861 * @result: search results to free
2863 * Free the result of a search as gotten by camel_folder_search() or
2864 * camel_folder_search_by_uids().
2867 camel_folder_search_free (CamelFolder *folder,
2870 CamelFolderClass *class;
2872 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2873 g_return_if_fail (result != NULL);
2875 class = CAMEL_FOLDER_GET_CLASS (folder);
2876 g_return_if_fail (class->search_free != NULL);
2878 /* NOTE: upto the callee to CAMEL_FOLDER_REC_LOCK */
2880 class->search_free (folder, result);
2884 * camel_folder_delete:
2885 * @folder: a #CamelFolder
2887 * Marks @folder as deleted and performs any required cleanup.
2889 * This also emits the #CamelFolder::deleted signal from an idle source on
2890 * the main loop. The idle source's priority is #G_PRIORITY_DEFAULT_IDLE.
2893 camel_folder_delete (CamelFolder *folder)
2895 CamelFolderClass *class;
2896 CamelStore *parent_store;
2897 CamelService *service;
2898 CamelSession *session;
2899 SignalData *signal_data;
2900 const gchar *full_name;
2902 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2904 class = CAMEL_FOLDER_GET_CLASS (folder);
2905 g_return_if_fail (class->delete_ != NULL);
2907 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
2908 if (folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED) {
2909 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
2913 folder->folder_flags |= CAMEL_FOLDER_HAS_BEEN_DELETED;
2915 class->delete_ (folder);
2917 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
2919 /* Delete the references of the folder from the DB.*/
2920 full_name = camel_folder_get_full_name (folder);
2921 parent_store = camel_folder_get_parent_store (folder);
2922 camel_db_delete_folder (parent_store->cdb_w, full_name, NULL);
2924 service = CAMEL_SERVICE (parent_store);
2925 session = camel_service_get_session (service);
2927 signal_data = g_slice_new0 (SignalData);
2928 signal_data->folder = g_object_ref (folder);
2930 camel_session_idle_add (
2931 session, G_PRIORITY_DEFAULT_IDLE,
2932 folder_emit_deleted_cb,
2933 signal_data, (GDestroyNotify) signal_data_free);
2937 * camel_folder_rename:
2938 * @folder: a #CamelFolder
2939 * @new_name: new name for the folder
2941 * Marks @folder as renamed.
2943 * This also emits the #CamelFolder::renamed signal from an idle source on
2944 * the main loop. The idle source's priority is #G_PRIORITY_DEFAULT_IDLE.
2946 * NOTE: This is an internal function used by camel stores, no locking
2947 * is performed on the folder.
2950 camel_folder_rename (CamelFolder *folder,
2951 const gchar *new_name)
2953 CamelFolderClass *class;
2954 CamelStore *parent_store;
2955 CamelService *service;
2956 CamelSession *session;
2957 SignalData *signal_data;
2960 g_return_if_fail (CAMEL_IS_FOLDER (folder));
2961 g_return_if_fail (new_name != NULL);
2963 class = CAMEL_FOLDER_GET_CLASS (folder);
2964 g_return_if_fail (class->rename != NULL);
2966 old_name = g_strdup (camel_folder_get_full_name (folder));
2968 class->rename (folder, new_name);
2970 parent_store = camel_folder_get_parent_store (folder);
2971 camel_db_rename_folder (parent_store->cdb_w, old_name, new_name, NULL);
2973 service = CAMEL_SERVICE (parent_store);
2974 session = camel_service_get_session (service);
2976 signal_data = g_slice_new0 (SignalData);
2977 signal_data->folder = g_object_ref (folder);
2978 signal_data->folder_name = old_name; /* transfer ownership */
2980 camel_session_idle_add (
2981 session, G_PRIORITY_DEFAULT_IDLE,
2982 folder_emit_renamed_cb,
2983 signal_data, (GDestroyNotify) signal_data_free);
2987 * camel_folder_changed:
2988 * @folder: a #CamelFolder
2989 * @changes: change information for @folder
2991 * Emits the #CamelFolder::changed signal from an idle source on the
2992 * main loop. The idle source's priority is #G_PRIORITY_LOW.
2997 camel_folder_changed (CamelFolder *folder,
2998 CamelFolderChangeInfo *changes)
3000 CamelFolderChangeInfo *pending_changes;
3002 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3003 g_return_if_fail (changes != NULL);
3005 if (camel_folder_is_frozen (folder)) {
3006 /* folder_changed() will catch this case and pile
3007 * the changes into folder->changed_frozen */
3008 g_signal_emit (folder, signals[CHANGED], 0, changes);
3012 /* If a "changed" signal has already been scheduled but not yet
3013 * emitted, just append our changes to the pending changes, and
3014 * skip scheduling our own "changed" signal. This helps to cut
3015 * down on the frequency of signal emissions so virtual folders
3016 * won't have to work so hard. */
3018 camel_folder_lock (folder, CAMEL_FOLDER_CHANGE_LOCK);
3020 pending_changes = folder->priv->pending_changes;
3022 if (pending_changes == NULL) {
3023 CamelStore *parent_store;
3024 CamelService *service;
3025 CamelSession *session;
3026 SignalData *signal_data;
3028 parent_store = camel_folder_get_parent_store (folder);
3030 service = CAMEL_SERVICE (parent_store);
3031 session = camel_service_get_session (service);
3033 pending_changes = camel_folder_change_info_new ();
3034 folder->priv->pending_changes = pending_changes;
3036 signal_data = g_slice_new0 (SignalData);
3037 signal_data->folder = g_object_ref (folder);
3039 camel_session_idle_add (
3040 session, G_PRIORITY_LOW,
3041 folder_emit_changed_cb,
3042 signal_data, (GDestroyNotify) signal_data_free);
3045 camel_folder_change_info_cat (pending_changes, changes);
3047 camel_folder_unlock (folder, CAMEL_FOLDER_CHANGE_LOCK);
3051 * camel_folder_freeze:
3052 * @folder: a #CamelFolder
3054 * Freezes the folder so that a series of operation can be performed
3055 * without "folder_changed" signals being emitted. When the folder is
3056 * later thawed with camel_folder_thaw(), the suppressed signals will
3060 camel_folder_freeze (CamelFolder *folder)
3062 CamelFolderClass *class;
3064 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3066 class = CAMEL_FOLDER_GET_CLASS (folder);
3067 g_return_if_fail (class->freeze != NULL);
3069 class->freeze (folder);
3073 * camel_folder_thaw:
3074 * @folder: a #CamelFolder
3076 * Thaws the folder and emits any pending folder_changed
3080 camel_folder_thaw (CamelFolder *folder)
3082 CamelFolderClass *class;
3084 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3085 g_return_if_fail (folder->priv->frozen != 0);
3087 class = CAMEL_FOLDER_GET_CLASS (folder);
3088 g_return_if_fail (class->thaw != NULL);
3090 class->thaw (folder);
3094 * camel_folder_is_frozen:
3095 * @folder: a #CamelFolder
3097 * Returns: whether or not the folder is frozen
3100 camel_folder_is_frozen (CamelFolder *folder)
3102 CamelFolderClass *class;
3104 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3106 class = CAMEL_FOLDER_GET_CLASS (folder);
3107 g_return_val_if_fail (class->is_frozen != NULL, FALSE);
3109 return class->is_frozen (folder);
3113 * camel_folder_get_frozen_count:
3114 * @folder: a #CamelFolder
3119 camel_folder_get_frozen_count (CamelFolder *folder)
3121 /* FIXME This function shouldn't be needed,
3122 * but it's used in CamelVeeFolder */
3123 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), 0);
3125 return folder->priv->frozen;
3129 * camel_folder_quota_info_new:
3130 * @name: Name of the quota.
3131 * @used: Current usage of the quota.
3132 * @total: Total available size of the quota.
3134 * Returns: newly allocated #CamelFolderQuotaInfo structure with
3135 * initialized values based on the parameters, with next member set to NULL.
3139 CamelFolderQuotaInfo *
3140 camel_folder_quota_info_new (const gchar *name,
3144 CamelFolderQuotaInfo *info;
3146 info = g_malloc0 (sizeof (CamelFolderQuotaInfo));
3147 info->name = g_strdup (name);
3149 info->total = total;
3156 * camel_folder_quota_info_clone:
3157 * @info: a #CamelFolderQuotaInfo object to clone.
3159 * Makes a copy of the given info and all next-s.
3163 CamelFolderQuotaInfo *
3164 camel_folder_quota_info_clone (const CamelFolderQuotaInfo *info)
3166 CamelFolderQuotaInfo *clone = NULL, *last = NULL;
3167 const CamelFolderQuotaInfo *iter;
3169 for (iter = info; iter != NULL; iter = iter->next) {
3170 CamelFolderQuotaInfo *n = camel_folder_quota_info_new (iter->name, iter->used, iter->total);
3184 * camel_folder_quota_info_free:
3185 * @info: a #CamelFolderQuotaInfo object to free.
3187 * Frees this and all next objects.
3192 camel_folder_quota_info_free (CamelFolderQuotaInfo *info)
3194 CamelFolderQuotaInfo *next = info;
3200 g_free (info->name);
3206 * camel_folder_free_nop:
3207 * @folder: a #CamelFolder
3208 * @array: an array of uids or #CamelMessageInfo
3210 * "Frees" the provided array by doing nothing. Used by #CamelFolder
3211 * subclasses as an implementation for free_uids, or free_summary when
3212 * the returned array is "static" information and should not be freed.
3215 camel_folder_free_nop (CamelFolder *folder,
3222 * camel_folder_free_shallow:
3223 * @folder: a #CamelFolder
3224 * @array: an array of uids or #CamelMessageInfo
3226 * Frees the provided array but not its contents. Used by #CamelFolder
3227 * subclasses as an implementation for free_uids or free_summary when
3228 * the returned array needs to be freed but its contents come from
3229 * "static" information.
3232 camel_folder_free_shallow (CamelFolder *folder,
3235 g_ptr_array_free (array, TRUE);
3239 * camel_folder_free_deep:
3240 * @folder: a #CamelFolder
3241 * @array: an array of uids
3243 * Frees the provided array and its contents. Used by #CamelFolder
3244 * subclasses as an implementation for free_uids when the provided
3245 * information was created explicitly by the corresponding get_ call.
3248 camel_folder_free_deep (CamelFolder *folder,
3253 g_return_if_fail (array != NULL);
3255 for (i = 0; i < array->len; i++)
3256 g_free (array->pdata[i]);
3257 g_ptr_array_free (array, TRUE);
3261 * camel_folder_lock:
3262 * @folder: a #CamelFolder
3263 * @lock: lock type to lock
3265 * Locks @folder's @lock. Unlock it with camel_folder_unlock().
3270 camel_folder_lock (CamelFolder *folder,
3271 CamelFolderLock lock)
3273 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3276 case CAMEL_FOLDER_CHANGE_LOCK:
3277 g_mutex_lock (&folder->priv->change_lock);
3279 case CAMEL_FOLDER_REC_LOCK:
3280 if (folder->priv->skip_folder_lock == FALSE)
3281 g_rec_mutex_lock (&folder->priv->lock);
3284 g_return_if_reached ();
3289 * camel_folder_unlock:
3290 * @folder: a #CamelFolder
3291 * @lock: lock type to unlock
3293 * Unlocks @folder's @lock, previously locked with camel_folder_lock().
3298 camel_folder_unlock (CamelFolder *folder,
3299 CamelFolderLock lock)
3301 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3304 case CAMEL_FOLDER_CHANGE_LOCK:
3305 g_mutex_unlock (&folder->priv->change_lock);
3307 case CAMEL_FOLDER_REC_LOCK:
3308 if (folder->priv->skip_folder_lock == FALSE)
3309 g_rec_mutex_unlock (&folder->priv->lock);
3312 g_return_if_reached ();
3317 * camel_folder_append_message_sync:
3318 * @folder: a #CamelFolder
3319 * @message: a #CamelMimeMessage
3320 * @info: a #CamelMessageInfo with additional flags/etc to set on the
3321 * new message, or %NULL
3322 * @appended_uid: if non-%NULL, the UID of the appended message will
3323 * be returned here, if it is known
3324 * @cancellable: optional #GCancellable object, or %NULL
3325 * @error: return location for a #GError, or %NULL
3327 * Appends @message to @folder. Only the flag and tag data from @info
3328 * are used. If @info is %NULL, no flags or tags will be set.
3330 * Returns: %TRUE on success, %FALSE on error
3335 camel_folder_append_message_sync (CamelFolder *folder,
3336 CamelMimeMessage *message,
3337 CamelMessageInfo *info,
3338 gchar **appended_uid,
3339 GCancellable *cancellable,
3342 CamelFolderClass *class;
3345 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3346 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
3348 class = CAMEL_FOLDER_GET_CLASS (folder);
3349 g_return_val_if_fail (class->append_message_sync != NULL, FALSE);
3351 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
3353 /* Check for cancellation after locking. */
3354 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
3355 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3359 success = class->append_message_sync (
3360 folder, message, info, appended_uid, cancellable, error);
3361 CAMEL_CHECK_GERROR (folder, append_message_sync, success, error);
3363 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3369 * camel_folder_append_message:
3370 * @folder a #CamelFolder
3371 * @message: a #CamelMimeMessage
3372 * @info: a #CamelMessageInfo with additional flags/etc to set on the
3373 * new message, or %NULL
3374 * @io_priority: the I/O priority of the request
3375 * @cancellable: optional #GCancellable object, or %NULL
3376 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3377 * @user_data: data to pass to the callback function
3379 * Appends @message to @folder asynchronously. Only the flag and tag data
3380 * from @info are used. If @info is %NULL, no flags or tags will be set.
3382 * When the operation is finished, @callback will be called. You can
3383 * then call camel_folder_append_message_finish() to get the result of
3389 camel_folder_append_message (CamelFolder *folder,
3390 CamelMimeMessage *message,
3391 CamelMessageInfo *info,
3393 GCancellable *cancellable,
3394 GAsyncReadyCallback callback,
3397 CamelFolderClass *class;
3399 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3400 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
3402 class = CAMEL_FOLDER_GET_CLASS (folder);
3403 g_return_if_fail (class->append_message != NULL);
3405 class->append_message (
3406 folder, message, info, io_priority,
3407 cancellable, callback, user_data);
3411 * camel_folder_append_message_finish:
3412 * @folder: a #CamelFolder
3413 * @result: a #GAsyncResult
3414 * @appended_uid: if non-%NULL, the UID of the appended message will
3415 * be returned here, if it is known
3416 * @error: return location for a #GError, or %NULL
3418 * Finishes the operation started with camel_folder_append_message_finish().
3420 * Returns: %TRUE on success, %FALSE on error
3425 camel_folder_append_message_finish (CamelFolder *folder,
3426 GAsyncResult *result,
3427 gchar **appended_uid,
3430 CamelFolderClass *class;
3432 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3433 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
3435 class = CAMEL_FOLDER_GET_CLASS (folder);
3436 g_return_val_if_fail (class->append_message_finish != NULL, FALSE);
3438 return class->append_message_finish (
3439 folder, result, appended_uid, error);
3443 * camel_folder_expunge_sync:
3444 * @folder: a #CamelFolder
3445 * @cancellable: optional #GCancellable object, or %NULL
3446 * @error: return location for a #GError, or %NULL
3448 * Deletes messages which have been marked as "DELETED".
3450 * Returns: %TRUE on success, %FALSE on error
3455 camel_folder_expunge_sync (CamelFolder *folder,
3456 GCancellable *cancellable,
3459 CamelFolderClass *class;
3460 const gchar *display_name;
3461 const gchar *message;
3462 gboolean success = TRUE;
3464 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3466 class = CAMEL_FOLDER_GET_CLASS (folder);
3467 g_return_val_if_fail (class->expunge_sync != NULL, FALSE);
3469 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
3471 /* Check for cancellation after locking. */
3472 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
3473 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3477 message = _("Expunging folder '%s'");
3478 display_name = camel_folder_get_display_name (folder);
3479 camel_operation_push_message (cancellable, message, display_name);
3481 if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED)) {
3482 success = class->expunge_sync (folder, cancellable, error);
3483 CAMEL_CHECK_GERROR (folder, expunge_sync, success, error);
3486 camel_operation_pop_message (cancellable);
3488 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3494 * camel_folder_expunge:
3495 * @folder: a #CamelFolder
3496 * @io_priority: the I/O priority of the request
3497 * @cancellable: optional #GCancellable object, or %NULL
3498 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3499 * @user_data: data to pass to the callback function
3501 * Asynchronously deletes messages which have been marked as "DELETED".
3503 * When the operation is finished, @callback will be called. You can then
3504 * call camel_folder_expunge_finish() to get the result of the operation.
3509 camel_folder_expunge (CamelFolder *folder,
3511 GCancellable *cancellable,
3512 GAsyncReadyCallback callback,
3515 CamelFolderClass *class;
3517 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3519 class = CAMEL_FOLDER_GET_CLASS (folder);
3520 g_return_if_fail (class->expunge != NULL);
3522 class->expunge (folder, io_priority, cancellable, callback, user_data);
3526 * camel_folder_expunge_finish:
3527 * @folder: a #CamelFolder
3528 * @result: a #GAsyncResult
3529 * @error: return location for a #GError, or %NULL
3531 * Finishes the operation started with camel_folder_expunge().
3533 * Returns: %TRUE on success, %FALSE on error
3538 camel_folder_expunge_finish (CamelFolder *folder,
3539 GAsyncResult *result,
3542 CamelFolderClass *class;
3544 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3545 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
3547 class = CAMEL_FOLDER_GET_CLASS (folder);
3548 g_return_val_if_fail (class->expunge_finish != NULL, FALSE);
3550 return class->expunge_finish (folder, result, error);
3554 * camel_folder_fetch_messages_sync :
3555 * @folder: a #CamelFolder
3556 * @type: Type to specify fetch old or new messages.
3557 * #limit: Limit to specify the number of messages to download.
3558 * @cancellable: optional #GCancellable object, or %NULL
3559 * @error: return location for a #GError, or %NULL
3561 * Downloads old or new specified number of messages from the server. It is
3562 * optimized for mobile client usage. Desktop clients should keep away from
3563 * this api and use @camel_folder_refresh_info.
3565 * Returns: %TRUE if there are more messages to fetch,
3566 * %FALSE if there are no more messages
3571 camel_folder_fetch_messages_sync (CamelFolder *folder,
3572 CamelFetchType type,
3574 GCancellable *cancellable,
3577 CamelFolderClass *class;
3578 gboolean success = TRUE;
3580 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3582 class = CAMEL_FOLDER_GET_CLASS (folder);
3584 /* Some backends that wont support mobile
3585 * mode, won't have this method implemented. */
3586 if (class->fetch_messages_sync == NULL)
3589 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
3591 /* Check for cancellation after locking. */
3592 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
3593 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3597 success = class->fetch_messages_sync (
3598 folder, type, limit, cancellable, error);
3599 CAMEL_CHECK_GERROR (folder, fetch_messages_sync, success, error);
3601 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3607 * camel_folder_fetch_messages:
3608 * @folder: a #CamelFolder
3609 * @type: Type to specify fetch old or new messages.
3610 * #limit: Limit to specify the number of messages to download.
3611 * @io_priority: the I/O priority of the request
3612 * @cancellable: optional #GCancellable object, or %NULL
3613 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3614 * @user_data: data to pass to the callback function
3616 * Asynchronously download new or old messages from the server. It is assumes
3617 * that the client has only a window of interested messages of what server has.
3618 * And old/new type helps to expand that window.
3620 * type = CAMEL_FETCH_OLD_MESSAGES: Downloads messages older than what the
3621 * client already has.
3622 * type = CAMEL_FETCH_NEW_MESSAGES: Downloads messages newer than what the
3623 * client already has.
3625 * When the operation is finished, @callback will be called. You can then
3626 * call camel_folder_fetch_messages_finish() to get the result of the operation.
3631 camel_folder_fetch_messages (CamelFolder *folder,
3632 CamelFetchType type,
3635 GCancellable *cancellable,
3636 GAsyncReadyCallback callback,
3639 CamelFolderClass *class;
3641 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3643 class = CAMEL_FOLDER_GET_CLASS (folder);
3644 g_return_if_fail (class->fetch_messages != NULL);
3646 class->fetch_messages (
3647 folder, type, limit, io_priority,
3648 cancellable, callback, user_data);
3652 * camel_folder_fetch_messages_finish:
3653 * @folder: a #CamelFolder
3654 * @result: a #GAsyncResult
3655 * @error: return location for a #GError, or %NULL
3657 * Finishes the operation started with camel_folder_fetch_messages().
3659 * Returns: %TRUE if there are more messages to fetch,
3660 * %FALSE if there are no more messages
3665 camel_folder_fetch_messages_finish (CamelFolder *folder,
3666 GAsyncResult *result,
3669 CamelFolderClass *class;
3671 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3672 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
3674 class = CAMEL_FOLDER_GET_CLASS (folder);
3675 g_return_val_if_fail (class->fetch_messages_finish != NULL, FALSE);
3677 return class->fetch_messages_finish (folder, result, error);
3681 * camel_folder_get_message_sync:
3682 * @folder: a #CamelFolder
3683 * @message_uid: the message UID
3684 * @cancellable: optional #GCancellable object, or %NULL
3685 * @error: return location for a #GError, or %NULL
3687 * Gets the message corresponding to @message_uid from @folder.
3689 * Returns: a #CamelMimeMessage corresponding to the requested UID
3694 camel_folder_get_message_sync (CamelFolder *folder,
3695 const gchar *message_uid,
3696 GCancellable *cancellable,
3699 CamelFolderClass *class;
3700 CamelMimeMessage *message = NULL;
3702 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
3703 g_return_val_if_fail (message_uid != NULL, NULL);
3705 class = CAMEL_FOLDER_GET_CLASS (folder);
3706 g_return_val_if_fail (class->get_message_sync != NULL, NULL);
3708 camel_operation_push_message (
3709 cancellable, _("Retrieving message '%s' in %s"),
3710 message_uid, camel_folder_get_display_name (folder));
3712 if (class->get_message_cached) {
3713 /* Return cached message, if available locally; this should
3714 * not do any network I/O, only check if message is already
3715 * downloaded and return it quicker, not being blocked by
3716 * the folder's lock. Returning NULL is not considered as
3717 * an error, it just means that the message is still
3718 * to-be-downloaded. */
3719 message = class->get_message_cached (
3720 folder, message_uid, cancellable);
3724 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
3726 /* Check for cancellation after locking. */
3727 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
3728 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3729 camel_operation_pop_message (cancellable);
3733 message = class->get_message_sync (
3734 folder, message_uid, cancellable, error);
3735 CAMEL_CHECK_GERROR (
3736 folder, get_message_sync, message != NULL, error);
3738 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3741 if (message && camel_mime_message_get_source (message) == NULL) {
3745 store = camel_folder_get_parent_store (folder);
3746 uid = camel_service_get_uid (CAMEL_SERVICE (store));
3748 camel_mime_message_set_source (message, uid);
3751 camel_operation_pop_message (cancellable);
3753 if (message != NULL && camel_debug_start (":folder")) {
3755 "CamelFolder:get_message ('%s', '%s') =\n",
3756 camel_folder_get_full_name (folder), message_uid);
3757 camel_mime_message_dump (message, FALSE);
3765 * camel_folder_get_message:
3766 * @folder: a #CamelFolder
3767 * @message_uid: the message UID
3768 * @io_priority: the I/O priority of the request
3769 * @cancellable: optional #GCancellable object, or %NULL
3770 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3771 * @user_data: data to pass to the callback function
3773 * Asynchronously gets the message corresponding to @message_uid from @folder.
3775 * When the operation is finished, @callback will be called. You can then
3776 * call camel_folder_get_message_finish() to get the result of the operation.
3781 camel_folder_get_message (CamelFolder *folder,
3782 const gchar *message_uid,
3784 GCancellable *cancellable,
3785 GAsyncReadyCallback callback,
3788 CamelFolderClass *class;
3790 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3791 g_return_if_fail (message_uid != NULL);
3793 class = CAMEL_FOLDER_GET_CLASS (folder);
3794 g_return_if_fail (class->get_message != NULL);
3796 class->get_message (
3797 folder, message_uid, io_priority,
3798 cancellable, callback, user_data);
3802 * camel_folder_get_message_finish:
3803 * @folder: a #CamelFolder
3804 * @result: a #GAsyncResult
3805 * @error: return location for a #GError or %NULL
3807 * Finishes the operation started with camel_folder_get_message().
3809 * Returns: a #CamelMimeMessage corresponding to the requested UID
3814 camel_folder_get_message_finish (CamelFolder *folder,
3815 GAsyncResult *result,
3818 CamelFolderClass *class;
3820 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
3821 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
3823 class = CAMEL_FOLDER_GET_CLASS (folder);
3824 g_return_val_if_fail (class->get_message_finish != NULL, NULL);
3826 return class->get_message_finish (folder, result, error);
3830 * camel_folder_get_quota_info_sync:
3831 * @folder: a #CamelFolder
3832 * @cancellable: optional #GCancellable object, or %NULL
3833 * @error: return location for a #GError, or %NULL
3835 * Gets a list of known quotas for @folder. Free the returned
3836 * #CamelFolderQuotaInfo struct with camel_folder_quota_info_free().
3838 * If quotas are not supported for @folder, the function returns %NULL
3839 * and sets @error to #G_IO_ERROR_NOT_SUPPORTED.
3841 * Returns: a #CamelFolderQuotaInfo, or %NULL
3845 CamelFolderQuotaInfo *
3846 camel_folder_get_quota_info_sync (CamelFolder *folder,
3847 GCancellable *cancellable,
3850 CamelFolderClass *class;
3851 CamelFolderQuotaInfo *quota_info;
3852 const gchar *display_name;
3853 const gchar *message;
3855 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
3857 class = CAMEL_FOLDER_GET_CLASS (folder);
3858 g_return_val_if_fail (class->get_quota_info_sync != NULL, NULL);
3860 message = _("Retrieving quota information for '%s'");
3861 display_name = camel_folder_get_display_name (folder);
3862 camel_operation_push_message (cancellable, message, display_name);
3864 quota_info = class->get_quota_info_sync (folder, cancellable, error);
3865 CAMEL_CHECK_GERROR (
3866 folder, get_quota_info_sync, quota_info != NULL, error);
3868 camel_operation_pop_message (cancellable);
3874 * camel_folder_get_quota_info:
3875 * @folder: a #CamelFolder
3876 * @io_priority: the I/O priority of the request
3877 * @cancellable: optional #GCancellable object, or %NULL
3878 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3879 * @user_data: data to pass to the callback function
3881 * Asynchronously gets a list of known quotas for @folder.
3883 * When the operation is finished, @callback will be called. You can
3884 * then call camel_folder_get_quota_info_finish() to get the result of
3890 camel_folder_get_quota_info (CamelFolder *folder,
3892 GCancellable *cancellable,
3893 GAsyncReadyCallback callback,
3896 CamelFolderClass *class;
3898 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3900 class = CAMEL_FOLDER_GET_CLASS (folder);
3901 g_return_if_fail (class->get_quota_info != NULL);
3903 class->get_quota_info (
3904 folder, io_priority,
3905 cancellable, callback, user_data);
3909 * camel_folder_get_quota_info_finish:
3910 * @folder: a #CamelFolder
3911 * @result: a #GAsyncResult
3912 * @error: return location for a #GError or %NULL
3914 * Finishes the operation started with camel_folder_get_quota_info().
3915 * Free the returned #CamelFolderQuotaInfo struct with
3916 * camel_folder_quota_info_free().
3918 * If quotas are not supported for @folder, the function returns %NULL
3919 * and sets @error to #G_IO_ERROR_NOT_SUPPORTED.
3921 * Returns: a #CamelFolderQuotaInfo, or %NULL
3925 CamelFolderQuotaInfo *
3926 camel_folder_get_quota_info_finish (CamelFolder *folder,
3927 GAsyncResult *result,
3930 CamelFolderClass *class;
3932 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
3934 class = CAMEL_FOLDER_GET_CLASS (folder);
3935 g_return_val_if_fail (class->get_quota_info_finish != NULL, NULL);
3937 return class->get_quota_info_finish (folder, result, error);
3941 * camel_folder_purge_message_cache_sync :
3942 * @folder: a #CamelFolder
3943 * @start_uid: the start message UID
3944 * @end_uid: the end message UID
3945 * @cancellable: optional #GCancellable object, or %NULL
3946 * @error: return location for a #GError, or %NULL
3948 * Delete the local cache of all messages between these uids.
3950 * Returns: %TRUE if success, %FALSE if there are any errors.
3955 camel_folder_purge_message_cache_sync (CamelFolder *folder,
3958 GCancellable *cancellable,
3961 CamelFolderClass *class;
3962 gboolean success = TRUE;
3964 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
3966 class = CAMEL_FOLDER_GET_CLASS (folder);
3968 /* Some backends that wont support mobile
3969 * mode, won't have this api implemented. */
3970 if (class->purge_message_cache_sync == NULL)
3973 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
3975 /* Check for cancellation after locking. */
3976 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
3977 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3981 success = class->purge_message_cache_sync (
3982 folder, start_uid, end_uid, cancellable, error);
3983 CAMEL_CHECK_GERROR (folder, purge_message_cache_sync, success, error);
3985 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
3991 * camel_folder_purge_message_cache:
3992 * @folder: a #CamelFolder
3993 * @start_uid: the start message UID
3994 * @end_uid: the end message UID
3995 * @io_priority: the I/O priority of the request
3996 * @cancellable: optional #GCancellable object, or %NULL
3997 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
3998 * @user_data: data to pass to the callback function
4000 * Delete the local cache of all messages between these uids.
4002 * When the operation is finished, @callback will be called. You can then
4003 * call camel_folder_purge_message_cache_finish() to get the result of the
4009 camel_folder_purge_message_cache (CamelFolder *folder,
4013 GCancellable *cancellable,
4014 GAsyncReadyCallback callback,
4017 CamelFolderClass *class;
4019 g_return_if_fail (CAMEL_IS_FOLDER (folder));
4021 class = CAMEL_FOLDER_GET_CLASS (folder);
4022 g_return_if_fail (class->purge_message_cache != NULL);
4024 class->purge_message_cache (
4025 folder, start_uid, end_uid, io_priority,
4026 cancellable, callback, user_data);
4030 * camel_folder_purge_message_cache_finish:
4031 * @folder: a #CamelFolder
4032 * @result: a #GAsyncResult
4033 * @error: return location for a #GError, or %NULL
4035 * Finishes the operation started with camel_folder_purge_message_cache().
4037 * Returns: %TRUE if cache is deleted, %FALSE if there are any errors
4042 camel_folder_purge_message_cache_finish (CamelFolder *folder,
4043 GAsyncResult *result,
4046 CamelFolderClass *class;
4048 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4049 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4051 class = CAMEL_FOLDER_GET_CLASS (folder);
4052 g_return_val_if_fail (class->purge_message_cache_finish != NULL, FALSE);
4054 return class->purge_message_cache_finish (folder, result, error);
4058 * camel_folder_refresh_info_sync:
4059 * @folder: a #CamelFolder
4060 * @cancellable: optional #GCancellable object, or %NULL
4061 * @error: return location for a #GError, or %NULL
4063 * Synchronizes a folder's summary with its backing store.
4065 * Returns: %TRUE on success, %FALSE on error
4070 camel_folder_refresh_info_sync (CamelFolder *folder,
4071 GCancellable *cancellable,
4074 CamelFolderClass *class;
4075 const gchar *display_name;
4076 const gchar *message;
4079 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4081 class = CAMEL_FOLDER_GET_CLASS (folder);
4082 g_return_val_if_fail (class->refresh_info_sync != NULL, FALSE);
4084 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
4086 /* Check for cancellation after locking. */
4087 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
4088 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
4092 message = _("Refreshing folder '%s'");
4093 display_name = camel_folder_get_display_name (folder);
4094 camel_operation_push_message (cancellable, message, display_name);
4096 success = class->refresh_info_sync (folder, cancellable, error);
4097 CAMEL_CHECK_GERROR (folder, refresh_info_sync, success, error);
4099 camel_operation_pop_message (cancellable);
4101 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
4107 * camel_folder_refresh_info:
4108 * @folder: a #CamelFolder
4109 * @io_priority: the I/O priority of the request
4110 * @cancellable: optional #GCancellable object, or %NULL
4111 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
4112 * @user_data: data to pass to the callback function
4114 * Asynchronously synchronizes a folder's summary with its backing store.
4116 * When the operation is finished, @callback will be called. You can then
4117 * call camel_folder_refresh_info_finish() to get the result of the operation.
4122 camel_folder_refresh_info (CamelFolder *folder,
4124 GCancellable *cancellable,
4125 GAsyncReadyCallback callback,
4128 CamelFolderClass *class;
4130 g_return_if_fail (CAMEL_IS_FOLDER (folder));
4132 class = CAMEL_FOLDER_GET_CLASS (folder);
4133 g_return_if_fail (class->refresh_info != NULL);
4135 class->refresh_info (
4136 folder, io_priority, cancellable, callback, user_data);
4140 * camel_folder_refresh_info_finish:
4141 * @folder: a #CamelFolder
4142 * @result: a #GAsyncResult
4143 * @error: return location for a #GError, or %NULL
4145 * Finishes the operation started with camel_folder_refresh_info().
4147 * Returns: %TRUE on success, %FALSE on error
4152 camel_folder_refresh_info_finish (CamelFolder *folder,
4153 GAsyncResult *result,
4156 CamelFolderClass *class;
4158 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4159 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4161 class = CAMEL_FOLDER_GET_CLASS (folder);
4162 g_return_val_if_fail (class->refresh_info_finish != NULL, FALSE);
4164 return class->refresh_info_finish (folder, result, error);
4168 * camel_folder_synchronize_sync:
4169 * @folder: a #CamelFolder
4170 * @expunge: whether to expunge after synchronizing
4171 * @cancellable: optional #GCancellable object, or %NULL
4172 * @error: return location for a #GError, or %NULL
4174 * Synchronizes any changes that have been made to @folder to its
4175 * backing store, optionally expunging deleted messages as well.
4177 * Returns: %TRUE on success, %FALSE on error
4182 camel_folder_synchronize_sync (CamelFolder *folder,
4184 GCancellable *cancellable,
4187 CamelFolderClass *class;
4188 gboolean success = TRUE;
4190 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4192 class = CAMEL_FOLDER_GET_CLASS (folder);
4193 g_return_val_if_fail (class->synchronize_sync != NULL, FALSE);
4195 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
4197 /* Check for cancellation after locking. */
4198 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
4199 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
4203 if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED)) {
4204 success = class->synchronize_sync (
4205 folder, expunge, cancellable, error);
4206 CAMEL_CHECK_GERROR (folder, synchronize_sync, success, error);
4209 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
4215 * camel_folder_synchronize:
4216 * @folder: a #CamelFolder
4217 * @expunge: whether to expunge after synchronizing
4218 * @io_priority: the I/O priority of the request
4219 * @cancellable: optional #GCancellable object, or %NULL
4220 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
4221 * @user_data: data to pass to the callback function
4223 * Synchronizes any changes that have been made to @folder to its backing
4224 * store asynchronously, optionally expunging deleted messages as well.
4226 * When the operation is finished, @callback will be called. You can then
4227 * call camel_folder_synchronize_finish() to get the result of the operation.
4232 camel_folder_synchronize (CamelFolder *folder,
4235 GCancellable *cancellable,
4236 GAsyncReadyCallback callback,
4239 CamelFolderClass *class;
4241 g_return_if_fail (CAMEL_IS_FOLDER (folder));
4243 class = CAMEL_FOLDER_GET_CLASS (folder);
4244 g_return_if_fail (class->synchronize != NULL);
4246 class->synchronize (
4247 folder, expunge, io_priority,
4248 cancellable, callback, user_data);
4252 * camel_folder_synchronize_finish:
4253 * @folder: a #CamelFolder
4254 * @result: a #GAsyncResult
4255 * @error: return location for a #GError, or %NULL
4257 * Finishes the operation started with camel_folder_synchronize().
4259 * Returns: %TRUE on sucess, %FALSE on error
4264 camel_folder_synchronize_finish (CamelFolder *folder,
4265 GAsyncResult *result,
4268 CamelFolderClass *class;
4270 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4271 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4273 class = CAMEL_FOLDER_GET_CLASS (folder);
4274 g_return_val_if_fail (class->synchronize_finish != NULL, FALSE);
4276 return class->synchronize_finish (folder, result, error);
4280 * camel_folder_synchronize_message_sync:
4281 * @folder: a #CamelFolder
4282 * @message_uid: a message UID
4283 * @cancellable: optional #GCancellable object, or %NULL
4284 * @error: return location for a #GError, or %NULL
4286 * Ensure that a message identified by @message_uid has been synchronized in
4287 * @folder so that calling camel_folder_get_message() on it later will work
4290 * Returns: %TRUE on success, %FALSE on error
4295 camel_folder_synchronize_message_sync (CamelFolder *folder,
4296 const gchar *message_uid,
4297 GCancellable *cancellable,
4300 CamelFolderClass *class;
4301 gboolean success = FALSE;
4303 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4304 g_return_val_if_fail (message_uid != NULL, FALSE);
4306 class = CAMEL_FOLDER_GET_CLASS (folder);
4307 g_return_val_if_fail (class->get_message_sync != NULL, FALSE);
4309 camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
4311 /* Check for cancellation after locking. */
4312 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
4313 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
4317 /* Use the sync_message method if the class implements it. */
4318 if (class->synchronize_message_sync != NULL) {
4319 success = class->synchronize_message_sync (
4320 folder, message_uid, cancellable, error);
4321 CAMEL_CHECK_GERROR (
4322 folder, synchronize_message_sync, success, error);
4324 CamelMimeMessage *message;
4326 message = class->get_message_sync (
4327 folder, message_uid, cancellable, error);
4328 CAMEL_CHECK_GERROR (
4329 folder, get_message_sync, message != NULL, error);
4331 if (message != NULL) {
4332 g_object_unref (message);
4337 camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
4343 * camel_folder_synchronize_message;
4344 * @folder: a #CamelFolder
4345 * @message_uid: a message UID
4346 * @io_priority: the I/O priority of the request
4347 * @cancellable: optional #GCancellable object, or %NULL
4348 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
4349 * @user_data: data to pass to the callback function
4351 * Asynchronously ensure that a message identified by @message_uid has been
4352 * synchronized in @folder so that calling camel_folder_get_message() on it
4353 * later will work in offline mode.
4355 * When the operation is finished, @callback will be called. You can then
4356 * call camel_folder_synchronize_message_finish() to get the result of the
4362 camel_folder_synchronize_message (CamelFolder *folder,
4363 const gchar *message_uid,
4365 GCancellable *cancellable,
4366 GAsyncReadyCallback callback,
4369 CamelFolderClass *class;
4371 g_return_if_fail (CAMEL_IS_FOLDER (folder));
4372 g_return_if_fail (message_uid != NULL);
4374 class = CAMEL_FOLDER_GET_CLASS (folder);
4375 g_return_if_fail (class->synchronize_message != NULL);
4377 class->synchronize_message (
4378 folder, message_uid, io_priority,
4379 cancellable, callback, user_data);
4383 * camel_folder_synchronize_message_finish:
4384 * @folder: a #CamelFolder
4385 * @result: a #GAsyncResult
4386 * @error: return location for a #GError, or %NULL
4388 * Finishes the operation started with camel_folder_synchronize_message().
4390 * Returns: %TRUE on success, %FALSE on error
4395 camel_folder_synchronize_message_finish (CamelFolder *folder,
4396 GAsyncResult *result,
4399 CamelFolderClass *class;
4401 g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
4402 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4404 class = CAMEL_FOLDER_GET_CLASS (folder);
4405 g_return_val_if_fail (class->synchronize_message_finish != NULL, FALSE);
4407 return class->synchronize_message_finish (folder, result, error);
4411 * camel_folder_transfer_messages_to_sync:
4412 * @source: the source #CamelFolder
4413 * @message_uids: message UIDs in @source
4414 * @destination: the destination #CamelFolder
4415 * @delete_originals: whether or not to delete the original messages
4416 * @transferred_uids: if non-%NULL, the UIDs of the resulting messages
4417 * in @destination will be stored here, if known.
4418 * @cancellable: optional #GCancellable object, or %NULL
4419 * @error: return location for a #GError, or %NULL
4421 * Copies or moves messages from one folder to another. If the
4422 * @source and @destination folders have the same parent_store, this
4423 * may be more efficient than using camel_folder_append_message_sync().
4425 * Returns: %TRUE on success, %FALSE on failure
4430 camel_folder_transfer_messages_to_sync (CamelFolder *source,
4431 GPtrArray *message_uids,
4432 CamelFolder *destination,
4433 gboolean delete_originals,
4434 GPtrArray **transferred_uids,
4435 GCancellable *cancellable,
4438 CamelFolderClass *class;
4441 g_return_val_if_fail (CAMEL_IS_FOLDER (source), FALSE);
4442 g_return_val_if_fail (CAMEL_IS_FOLDER (destination), FALSE);
4443 g_return_val_if_fail (message_uids != NULL, FALSE);
4445 if (source == destination || message_uids->len == 0)
4448 if (source->priv->parent_store == destination->priv->parent_store) {
4449 /* If either folder is a vtrash, we need to use the
4450 * vtrash transfer method. */
4451 if (CAMEL_IS_VTRASH_FOLDER (destination))
4452 class = CAMEL_FOLDER_GET_CLASS (destination);
4454 class = CAMEL_FOLDER_GET_CLASS (source);
4455 success = class->transfer_messages_to_sync (
4456 source, message_uids, destination, delete_originals,
4457 transferred_uids, cancellable, error);
4459 success = folder_transfer_messages_to_sync (
4460 source, message_uids, destination, delete_originals,
4461 transferred_uids, cancellable, error);
4467 * camel_folder_transfer_messages_to:
4468 * @source: the source #CamelFolder
4469 * @message_uids: message UIDs in @source
4470 * @destination: the destination #CamelFolder
4471 * @delete_originals: whether or not to delete the original messages
4472 * @io_priority: the I/O priority of the request
4473 * @cancellable: optional #GCancellable object, or %NULL
4474 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
4475 * @user_data: data to pass to the callback function
4477 * Asynchronously copies or moves messages from one folder to another.
4478 * If the @source or @destination folders have the same parent store,
4479 * this may be more efficient than using camel_folder_append_message().
4481 * When the operation is finished, @callback will be called. You can then
4482 * call camel_folder_transfer_messages_to_finish() to get the result of the
4488 camel_folder_transfer_messages_to (CamelFolder *source,
4489 GPtrArray *message_uids,
4490 CamelFolder *destination,
4491 gboolean delete_originals,
4493 GCancellable *cancellable,
4494 GAsyncReadyCallback callback,
4497 CamelFolderClass *class;
4499 g_return_if_fail (CAMEL_IS_FOLDER (source));
4500 g_return_if_fail (CAMEL_IS_FOLDER (destination));
4501 g_return_if_fail (message_uids != NULL);
4503 class = CAMEL_FOLDER_GET_CLASS (source);
4504 g_return_if_fail (class->transfer_messages_to != NULL);
4506 class->transfer_messages_to (
4507 source, message_uids, destination, delete_originals,
4508 io_priority, cancellable, callback, user_data);
4512 * camel_folder_transfer_messages_to_finish:
4513 * @source: a #CamelFolder
4514 * @result: a #GAsyncResult
4515 * @transferred_uids: if non-%NULL, the UIDs of the resulting messages
4516 * in @destination will be stored here, if known.
4517 * @error: return location for a #GError, or %NULL
4519 * Finishes the operation started with camel_folder_transfer_messages_to().
4521 * Returns: %TRUE on success, %FALSE on error
4526 camel_folder_transfer_messages_to_finish (CamelFolder *source,
4527 GAsyncResult *result,
4528 GPtrArray **transferred_uids,
4531 CamelFolderClass *class;
4533 g_return_val_if_fail (CAMEL_IS_FOLDER (source), FALSE);
4534 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
4536 class = CAMEL_FOLDER_GET_CLASS (source);
4537 g_return_val_if_fail (class->transfer_messages_to_finish != NULL, FALSE);
4539 return class->transfer_messages_to_finish (
4540 source, result, transferred_uids, error);
4544 * camel_folder_change_info_new:
4546 * Create a new folder change info structure.
4548 * Change info structures are not MT-SAFE and must be
4549 * locked for exclusive access externally.
4551 * Returns: a new #CamelFolderChangeInfo
4553 CamelFolderChangeInfo *
4554 camel_folder_change_info_new (void)
4556 CamelFolderChangeInfo *info;
4558 info = g_slice_new (CamelFolderChangeInfo);
4559 info->uid_added = g_ptr_array_new ();
4560 info->uid_removed = g_ptr_array_new ();
4561 info->uid_changed = g_ptr_array_new ();
4562 info->uid_recent = g_ptr_array_new ();
4563 info->priv = g_slice_new (struct _CamelFolderChangeInfoPrivate);
4564 info->priv->uid_stored = g_hash_table_new (g_str_hash, g_str_equal);
4565 info->priv->uid_source = NULL;
4566 info->priv->uid_filter = g_ptr_array_new ();
4567 info->priv->uid_pool = camel_mempool_new (512, 256, CAMEL_MEMPOOL_ALIGN_BYTE);
4573 * camel_folder_change_info_add_source:
4574 * @info: a #CamelFolderChangeInfo
4577 * Add a source uid for generating a changeset.
4580 camel_folder_change_info_add_source (CamelFolderChangeInfo *info,
4583 struct _CamelFolderChangeInfoPrivate *p;
4585 g_return_if_fail (info != NULL);
4586 g_return_if_fail (uid != NULL);
4590 if (p->uid_source == NULL)
4591 p->uid_source = g_hash_table_new (g_str_hash, g_str_equal);
4593 if (g_hash_table_lookup (p->uid_source, uid) == NULL)
4594 g_hash_table_insert (p->uid_source, camel_mempool_strdup (p->uid_pool, uid), GINT_TO_POINTER (1));
4598 * camel_folder_change_info_add_source_list:
4599 * @info: a #CamelFolderChangeInfo
4600 * @list: a list of uids
4602 * Add a list of source uid's for generating a changeset.
4605 camel_folder_change_info_add_source_list (CamelFolderChangeInfo *info,
4606 const GPtrArray *list)
4608 struct _CamelFolderChangeInfoPrivate *p;
4611 g_return_if_fail (info != NULL);
4612 g_return_if_fail (list != NULL);
4616 if (p->uid_source == NULL)
4617 p->uid_source = g_hash_table_new (g_str_hash, g_str_equal);
4619 for (i = 0; i < list->len; i++) {
4620 gchar *uid = list->pdata[i];
4622 if (g_hash_table_lookup (p->uid_source, uid) == NULL)
4623 g_hash_table_insert (p->uid_source, camel_mempool_strdup (p->uid_pool, uid), GINT_TO_POINTER (1));
4628 * camel_folder_change_info_add_update:
4629 * @info: a #CamelFolderChangeInfo
4632 * Add a uid from the updated list, used to generate a changeset diff.
4635 camel_folder_change_info_add_update (CamelFolderChangeInfo *info,
4638 struct _CamelFolderChangeInfoPrivate *p;
4642 g_return_if_fail (info != NULL);
4643 g_return_if_fail (uid != NULL);
4647 if (p->uid_source == NULL) {
4648 camel_folder_change_info_add_uid (info, uid);
4652 if (g_hash_table_lookup_extended (p->uid_source, uid, (gpointer) &key, (gpointer) &value)) {
4653 g_hash_table_remove (p->uid_source, key);
4655 camel_folder_change_info_add_uid (info, uid);
4660 * camel_folder_change_info_add_update_list:
4661 * @info: a #CamelFolderChangeInfo
4662 * @list: a list of uids
4664 * Add a list of uid's from the updated list.
4667 camel_folder_change_info_add_update_list (CamelFolderChangeInfo *info,
4668 const GPtrArray *list)
4672 g_return_if_fail (info != NULL);
4673 g_return_if_fail (list != NULL);
4675 for (i = 0; i < list->len; i++)
4676 camel_folder_change_info_add_update (info, list->pdata[i]);
4680 change_info_remove (gchar *key,
4682 CamelFolderChangeInfo *info)
4684 struct _CamelFolderChangeInfoPrivate *p = info->priv;
4688 if (g_hash_table_lookup_extended (p->uid_stored, key, (gpointer) &olduid, (gpointer) &olduids)) {
4689 /* if it was added/changed them removed, then remove it */
4690 if (olduids != info->uid_removed) {
4691 g_ptr_array_remove_fast (olduids, olduid);
4692 g_ptr_array_add (info->uid_removed, olduid);
4693 g_hash_table_insert (p->uid_stored, olduid, info->uid_removed);
4698 /* we dont need to copy this, as they've already been copied into our pool */
4699 g_ptr_array_add (info->uid_removed, key);
4700 g_hash_table_insert (p->uid_stored, key, info->uid_removed);
4704 * camel_folder_change_info_build_diff:
4705 * @info: a #CamelFolderChangeInfo
4707 * Compare the source uid set to the updated uid set and generate the
4708 * differences into the added and removed lists.
4711 camel_folder_change_info_build_diff (CamelFolderChangeInfo *info)
4713 struct _CamelFolderChangeInfoPrivate *p;
4715 g_return_if_fail (info != NULL);
4719 if (p->uid_source) {
4720 g_hash_table_foreach (p->uid_source, (GHFunc) change_info_remove, info);
4721 g_hash_table_destroy (p->uid_source);
4722 p->uid_source = NULL;
4727 change_info_recent_uid (CamelFolderChangeInfo *info,
4730 struct _CamelFolderChangeInfoPrivate *p;
4736 /* always add to recent, but dont let anyone else know */
4737 if (!g_hash_table_lookup_extended (p->uid_stored, uid, (gpointer *) &olduid, (gpointer *) &olduids)) {
4738 olduid = camel_mempool_strdup (p->uid_pool, uid);
4740 g_ptr_array_add (info->uid_recent, olduid);
4744 change_info_filter_uid (CamelFolderChangeInfo *info,
4747 struct _CamelFolderChangeInfoPrivate *p;
4753 /* always add to filter, but dont let anyone else know */
4754 if (!g_hash_table_lookup_extended (p->uid_stored, uid, (gpointer *) &olduid, (gpointer *) &olduids)) {
4755 olduid = camel_mempool_strdup (p->uid_pool, uid);
4757 g_ptr_array_add (p->uid_filter, olduid);
4761 change_info_cat (CamelFolderChangeInfo *info,
4763 void (*add)(CamelFolderChangeInfo *info,
4768 for (i = 0; i < source->len; i++)
4769 add (info, source->pdata[i]);
4773 * camel_folder_change_info_cat:
4774 * @info: a #CamelFolderChangeInfo to append to
4775 * @src: a #CamelFolderChangeInfo to append from
4777 * Concatenate one change info onto antoher. Can be used to copy them
4781 camel_folder_change_info_cat (CamelFolderChangeInfo *info,
4782 CamelFolderChangeInfo *source)
4784 g_return_if_fail (info != NULL);
4785 g_return_if_fail (source != NULL);
4787 change_info_cat (info, source->uid_added, camel_folder_change_info_add_uid);
4788 change_info_cat (info, source->uid_removed, camel_folder_change_info_remove_uid);
4789 change_info_cat (info, source->uid_changed, camel_folder_change_info_change_uid);
4790 change_info_cat (info, source->uid_recent, change_info_recent_uid);
4791 change_info_cat (info, source->priv->uid_filter, change_info_filter_uid);
4795 * camel_folder_change_info_add_uid:
4796 * @info: a #CamelFolderChangeInfo
4799 * Add a new uid to the changeinfo.
4802 camel_folder_change_info_add_uid (CamelFolderChangeInfo *info,
4805 struct _CamelFolderChangeInfoPrivate *p;
4809 g_return_if_fail (info != NULL);
4810 g_return_if_fail (uid != NULL);
4814 if (g_hash_table_lookup_extended (p->uid_stored, uid, (gpointer) &olduid, (gpointer) &olduids)) {
4815 /* if it was removed then added, promote it to a changed */
4816 /* if it was changed then added, leave as changed */
4817 if (olduids == info->uid_removed) {
4818 g_ptr_array_remove_fast (olduids, olduid);
4819 g_ptr_array_add (info->uid_changed, olduid);
4820 g_hash_table_insert (p->uid_stored, olduid, info->uid_changed);
4825 olduid = camel_mempool_strdup (p->uid_pool, uid);
4826 g_ptr_array_add (info->uid_added, olduid);
4827 g_hash_table_insert (p->uid_stored, olduid, info->uid_added);
4831 * camel_folder_change_info_remove_uid:
4832 * @info: a #CamelFolderChangeInfo
4835 * Add a uid to the removed uid list.
4838 camel_folder_change_info_remove_uid (CamelFolderChangeInfo *info,
4841 struct _CamelFolderChangeInfoPrivate *p;
4845 g_return_if_fail (info != NULL);
4846 g_return_if_fail (uid != NULL);
4850 if (g_hash_table_lookup_extended (p->uid_stored, uid, (gpointer) &olduid, (gpointer) &olduids)) {
4851 /* if it was added/changed them removed, then remove it */
4852 if (olduids != info->uid_removed) {
4853 g_ptr_array_remove_fast (olduids, olduid);
4854 g_ptr_array_add (info->uid_removed, olduid);
4855 g_hash_table_insert (p->uid_stored, olduid, info->uid_removed);
4860 olduid = camel_mempool_strdup (p->uid_pool, uid);
4861 g_ptr_array_add (info->uid_removed, olduid);
4862 g_hash_table_insert (p->uid_stored, olduid, info->uid_removed);
4866 * camel_folder_change_info_change_uid:
4867 * @info: a #CamelFolderChangeInfo
4870 * Add a uid to the changed uid list.
4873 camel_folder_change_info_change_uid (CamelFolderChangeInfo *info,
4876 struct _CamelFolderChangeInfoPrivate *p;
4880 g_return_if_fail (info != NULL);
4881 g_return_if_fail (uid != NULL);
4885 if (g_hash_table_lookup_extended (p->uid_stored, uid, (gpointer) &olduid, (gpointer) &olduids)) {
4886 /* if we have it already, leave it as that */
4890 olduid = camel_mempool_strdup (p->uid_pool, uid);
4891 g_ptr_array_add (info->uid_changed, olduid);
4892 g_hash_table_insert (p->uid_stored, olduid, info->uid_changed);
4896 * camel_folder_change_info_recent_uid:
4897 * @info: a #CamelFolderChangeInfo
4900 * Add a recent uid to the changedinfo.
4901 * This will also add the uid to the uid_filter array for potential
4905 camel_folder_change_info_recent_uid (CamelFolderChangeInfo *info,
4908 g_return_if_fail (info != NULL);
4909 g_return_if_fail (uid != NULL);
4911 change_info_recent_uid (info, uid);
4912 change_info_filter_uid (info, uid);
4916 * camel_folder_change_info_changed:
4917 * @info: a #CamelFolderChangeInfo
4919 * Gets whether or not there have been any changes.
4921 * Returns: %TRUE if the changeset contains any changes or %FALSE
4925 camel_folder_change_info_changed (CamelFolderChangeInfo *info)
4927 g_return_val_if_fail (info != NULL, FALSE);
4929 return (info->uid_added->len || info->uid_removed->len || info->uid_changed->len || info->uid_recent->len);
4933 * camel_folder_change_info_clear:
4934 * @info: a #CamelFolderChangeInfo
4936 * Empty out the change info; called after changes have been
4940 camel_folder_change_info_clear (CamelFolderChangeInfo *info)
4942 struct _CamelFolderChangeInfoPrivate *p;
4944 g_return_if_fail (info != NULL);
4948 g_ptr_array_set_size (info->uid_added, 0);
4949 g_ptr_array_set_size (info->uid_removed, 0);
4950 g_ptr_array_set_size (info->uid_changed, 0);
4951 g_ptr_array_set_size (info->uid_recent, 0);
4952 if (p->uid_source) {
4953 g_hash_table_destroy (p->uid_source);
4954 p->uid_source = NULL;
4956 g_hash_table_destroy (p->uid_stored);
4957 p->uid_stored = g_hash_table_new (g_str_hash, g_str_equal);
4958 g_ptr_array_set_size (p->uid_filter, 0);
4959 camel_mempool_flush (p->uid_pool, TRUE);
4963 * camel_folder_change_info_free:
4964 * @info: a #CamelFolderChangeInfo
4966 * Free memory associated with the folder change info lists.
4969 camel_folder_change_info_free (CamelFolderChangeInfo *info)
4971 struct _CamelFolderChangeInfoPrivate *p;
4973 g_return_if_fail (info != NULL);
4978 g_hash_table_destroy (p->uid_source);
4980 g_hash_table_destroy (p->uid_stored);
4981 g_ptr_array_free (p->uid_filter, TRUE);
4982 camel_mempool_destroy (p->uid_pool);
4983 g_slice_free (struct _CamelFolderChangeInfoPrivate, p);
4985 g_ptr_array_free (info->uid_added, TRUE);
4986 g_ptr_array_free (info->uid_removed, TRUE);
4987 g_ptr_array_free (info->uid_changed, TRUE);
4988 g_ptr_array_free (info->uid_recent, TRUE);
4989 g_slice_free (CamelFolderChangeInfo, info);