1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <tny-mime-part.h>
33 #include <tny-store-account.h>
34 #include <tny-folder-store.h>
35 #include <tny-folder-store-query.h>
36 #include <tny-camel-stream.h>
37 #include <tny-camel-pop-store-account.h>
38 #include <tny-camel-pop-folder.h>
39 #include <tny-camel-imap-folder.h>
40 #include <tny-camel-mem-stream.h>
41 #include <tny-simple-list.h>
42 #include <tny-send-queue.h>
43 #include <tny-status.h>
44 #include <tny-folder-observer.h>
45 #include <camel/camel-stream-mem.h>
46 #include <glib/gi18n.h>
47 #include "modest-platform.h"
48 #include "modest-account-mgr-helpers.h"
49 #include <modest-tny-account.h>
50 #include <modest-tny-send-queue.h>
51 #include <modest-runtime.h>
52 #include "modest-text-utils.h"
53 #include "modest-tny-msg.h"
54 #include "modest-tny-folder.h"
55 #include "modest-tny-account-store.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-marshal.h"
58 #include "modest-error.h"
59 #include "modest-mail-operation.h"
60 #include <modest-count-stream.h>
61 #include <libgnomevfs/gnome-vfs.h>
62 #include "modest-utils.h"
67 * Remove all these #ifdef stuff when the tinymail's idle calls become
70 #define TINYMAIL_IDLES_NOT_LOCKED_YET 1
72 /* 'private'/'protected' functions */
73 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
74 static void modest_mail_operation_init (ModestMailOperation *obj);
75 static void modest_mail_operation_finalize (GObject *obj);
77 static void get_msg_async_cb (TnyFolder *folder,
83 static void get_msg_status_cb (GObject *obj,
87 static void modest_mail_operation_notify_start (ModestMailOperation *self);
88 static void modest_mail_operation_notify_end (ModestMailOperation *self);
90 static void notify_progress_of_multiple_messages (ModestMailOperation *self,
92 gint *last_total_bytes,
93 gint *sum_total_bytes,
95 gboolean increment_done);
97 static guint compute_message_list_size (TnyList *headers);
99 static guint compute_message_array_size (GPtrArray *headers);
101 static int compare_headers_by_date (gconstpointer a,
104 enum _ModestMailOperationSignals
106 PROGRESS_CHANGED_SIGNAL,
107 OPERATION_STARTED_SIGNAL,
108 OPERATION_FINISHED_SIGNAL,
112 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
113 struct _ModestMailOperationPrivate {
119 ErrorCheckingUserCallback error_checking;
120 gpointer error_checking_user_data;
121 ErrorCheckingUserDataDestroyer error_checking_user_data_destroyer;
122 ModestMailOperationStatus status;
123 ModestMailOperationTypeOperation op_type;
126 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
127 MODEST_TYPE_MAIL_OPERATION, \
128 ModestMailOperationPrivate))
130 #define CHECK_EXCEPTION(priv, new_status) if (priv->error) {\
131 priv->status = new_status;\
136 GetMsgAsyncUserCallback user_callback;
138 TnyIterator *more_msgs;
140 ModestMailOperation *mail_op;
141 GDestroyNotify destroy_notify;
142 gint last_total_bytes;
143 gint sum_total_bytes;
147 typedef struct _RefreshAsyncHelper {
148 ModestMailOperation *mail_op;
149 RefreshAsyncUserCallback user_callback;
151 } RefreshAsyncHelper;
153 typedef struct _XFerMsgsAsyncHelper
155 ModestMailOperation *mail_op;
157 TnyIterator *more_msgs;
158 TnyFolder *dest_folder;
159 XferMsgsAsyncUserCallback user_callback;
162 gint last_total_bytes;
163 gint sum_total_bytes;
165 } XFerMsgsAsyncHelper;
167 typedef struct _XFerFolderAsyncHelper
169 ModestMailOperation *mail_op;
170 XferFolderAsyncUserCallback user_callback;
172 } XFerFolderAsyncHelper;
174 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
178 static void modest_mail_operation_create_msg (ModestMailOperation *self,
179 const gchar *from, const gchar *to,
180 const gchar *cc, const gchar *bcc,
181 const gchar *subject, const gchar *plain_body,
182 const gchar *html_body, const GList *attachments_list,
183 const GList *images_list,
184 TnyHeaderFlags priority_flags,
185 ModestMailOperationCreateMsgCallback callback,
188 static gboolean idle_notify_queue (gpointer data);
191 ModestMailOperation *mail_op;
199 GList *attachments_list;
201 TnyHeaderFlags priority_flags;
202 ModestMailOperationCreateMsgCallback callback;
208 ModestMailOperation *mail_op;
210 ModestMailOperationCreateMsgCallback callback;
215 static GObjectClass *parent_class = NULL;
217 static guint signals[NUM_SIGNALS] = {0};
220 modest_mail_operation_get_type (void)
222 static GType my_type = 0;
224 static const GTypeInfo my_info = {
225 sizeof(ModestMailOperationClass),
226 NULL, /* base init */
227 NULL, /* base finalize */
228 (GClassInitFunc) modest_mail_operation_class_init,
229 NULL, /* class finalize */
230 NULL, /* class data */
231 sizeof(ModestMailOperation),
233 (GInstanceInitFunc) modest_mail_operation_init,
236 my_type = g_type_register_static (G_TYPE_OBJECT,
237 "ModestMailOperation",
244 modest_mail_operation_class_init (ModestMailOperationClass *klass)
246 GObjectClass *gobject_class;
247 gobject_class = (GObjectClass*) klass;
249 parent_class = g_type_class_peek_parent (klass);
250 gobject_class->finalize = modest_mail_operation_finalize;
252 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
255 * ModestMailOperation::progress-changed
256 * @self: the #MailOperation that emits the signal
257 * @user_data: user data set when the signal handler was connected
259 * Emitted when the progress of a mail operation changes
261 signals[PROGRESS_CHANGED_SIGNAL] =
262 g_signal_new ("progress-changed",
263 G_TYPE_FROM_CLASS (gobject_class),
265 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
267 g_cclosure_marshal_VOID__POINTER,
268 G_TYPE_NONE, 1, G_TYPE_POINTER);
272 * This signal is issued whenever a mail operation starts, and
273 * starts mean when the tinymail operation is issued. This
274 * means that it could happen that something wrong happens and
275 * the tinymail function is never called. In this situation a
276 * operation-finished will be issued without any
279 signals[OPERATION_STARTED_SIGNAL] =
280 g_signal_new ("operation-started",
281 G_TYPE_FROM_CLASS (gobject_class),
283 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
285 g_cclosure_marshal_VOID__VOID,
290 * This signal is issued whenever a mail operation
291 * finishes. Note that this signal could be issued without any
292 * previous "operation-started" signal, because this last one
293 * is only issued when the tinymail operation is successfully
296 signals[OPERATION_FINISHED_SIGNAL] =
297 g_signal_new ("operation-finished",
298 G_TYPE_FROM_CLASS (gobject_class),
300 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
302 g_cclosure_marshal_VOID__VOID,
307 modest_mail_operation_init (ModestMailOperation *obj)
309 ModestMailOperationPrivate *priv;
311 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
313 priv->account = NULL;
314 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
315 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
320 priv->error_checking = NULL;
321 priv->error_checking_user_data = NULL;
325 modest_mail_operation_finalize (GObject *obj)
327 ModestMailOperationPrivate *priv;
329 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
334 g_error_free (priv->error);
338 g_object_unref (priv->source);
342 g_object_unref (priv->account);
343 priv->account = NULL;
347 G_OBJECT_CLASS(parent_class)->finalize (obj);
351 modest_mail_operation_new (GObject *source)
353 ModestMailOperation *obj;
354 ModestMailOperationPrivate *priv;
356 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
357 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
360 priv->source = g_object_ref(source);
366 modest_mail_operation_new_with_error_handling (GObject *source,
367 ErrorCheckingUserCallback error_handler,
369 ErrorCheckingUserDataDestroyer error_handler_destroyer)
371 ModestMailOperation *obj;
372 ModestMailOperationPrivate *priv;
374 obj = modest_mail_operation_new (source);
375 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
377 g_return_val_if_fail (error_handler != NULL, obj);
378 priv->error_checking = error_handler;
379 priv->error_checking_user_data = user_data;
380 priv->error_checking_user_data_destroyer = error_handler_destroyer;
386 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
388 ModestMailOperationPrivate *priv;
390 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
392 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
393 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
395 /* Call the user callback */
396 if (priv->error_checking != NULL)
397 priv->error_checking (self, priv->error_checking_user_data);
401 ModestMailOperationTypeOperation
402 modest_mail_operation_get_type_operation (ModestMailOperation *self)
404 ModestMailOperationPrivate *priv;
406 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
407 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
409 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
411 return priv->op_type;
415 modest_mail_operation_is_mine (ModestMailOperation *self,
418 ModestMailOperationPrivate *priv;
420 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
423 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
424 if (priv->source == NULL) return FALSE;
426 return priv->source == me;
430 modest_mail_operation_get_source (ModestMailOperation *self)
432 ModestMailOperationPrivate *priv;
434 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
437 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
439 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
443 return (priv->source) ? g_object_ref (priv->source) : NULL;
446 ModestMailOperationStatus
447 modest_mail_operation_get_status (ModestMailOperation *self)
449 ModestMailOperationPrivate *priv;
451 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
452 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
453 MODEST_MAIL_OPERATION_STATUS_INVALID);
455 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
457 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
458 return MODEST_MAIL_OPERATION_STATUS_INVALID;
465 modest_mail_operation_get_error (ModestMailOperation *self)
467 ModestMailOperationPrivate *priv;
469 g_return_val_if_fail (self, NULL);
470 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
472 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
475 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
483 modest_mail_operation_cancel (ModestMailOperation *self)
485 ModestMailOperationPrivate *priv;
486 gboolean canceled = FALSE;
488 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
490 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
493 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
495 /* Cancel the mail operation */
496 g_return_val_if_fail (priv->account, FALSE);
497 tny_account_cancel (priv->account);
499 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
500 ModestTnySendQueue *queue;
501 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
503 /* Cancel the sending of the following next messages */
504 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, NULL);
511 modest_mail_operation_get_task_done (ModestMailOperation *self)
513 ModestMailOperationPrivate *priv;
515 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
518 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
523 modest_mail_operation_get_task_total (ModestMailOperation *self)
525 ModestMailOperationPrivate *priv;
527 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
530 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
535 modest_mail_operation_is_finished (ModestMailOperation *self)
537 ModestMailOperationPrivate *priv;
538 gboolean retval = FALSE;
540 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
543 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
545 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
546 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
547 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
548 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
558 * Creates an image of the current state of a mail operation, the
559 * caller must free it
561 static ModestMailOperationState *
562 modest_mail_operation_clone_state (ModestMailOperation *self)
564 ModestMailOperationState *state;
565 ModestMailOperationPrivate *priv;
567 /* FIXME: this should be fixed properly
569 * in some cases, priv was NULL, so checking here to
572 g_return_val_if_fail (self, NULL);
573 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
574 g_return_val_if_fail (priv, NULL);
579 state = g_slice_new (ModestMailOperationState);
581 state->status = priv->status;
582 state->op_type = priv->op_type;
583 state->done = priv->done;
584 state->total = priv->total;
585 state->finished = modest_mail_operation_is_finished (self);
586 state->bytes_done = 0;
587 state->bytes_total = 0;
592 /* ******************************************************************* */
593 /* ************************** SEND ACTIONS ************************* */
594 /* ******************************************************************* */
597 modest_mail_operation_send_mail (ModestMailOperation *self,
598 TnyTransportAccount *transport_account,
601 TnySendQueue *send_queue = NULL;
602 ModestMailOperationPrivate *priv;
604 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
605 g_return_if_fail (transport_account && TNY_IS_TRANSPORT_ACCOUNT (transport_account));
606 g_return_if_fail (msg && TNY_IS_MSG (msg));
608 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
610 /* Get account and set it into mail_operation */
611 priv->account = g_object_ref (transport_account);
612 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
616 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
617 if (!TNY_IS_SEND_QUEUE(send_queue)) {
618 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
619 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
620 "modest: could not find send queue for account\n");
621 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
622 modest_mail_operation_notify_end (self);
625 /* Add the msg to the queue */
626 modest_mail_operation_notify_start (self);
628 tny_send_queue_add_async (send_queue, msg, NULL, NULL, NULL);
629 modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue), FALSE);
631 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
632 modest_mail_operation_notify_end (self);
639 idle_create_msg_cb (gpointer idle_data)
641 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
643 /* This is a GDK lock because we are an idle callback and
644 * info->callback can contain Gtk+ code */
646 gdk_threads_enter (); /* CHECKED */
647 info->callback (info->mail_op, info->msg, info->userdata);
649 g_object_unref (info->mail_op);
651 g_object_unref (info->msg);
652 g_slice_free (CreateMsgIdleInfo, info);
653 gdk_threads_leave (); /* CHECKED */
659 create_msg_thread (gpointer thread_data)
661 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
662 TnyMsg *new_msg = NULL;
663 ModestMailOperationPrivate *priv;
665 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
666 if (info->html_body == NULL) {
667 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
668 info->bcc, info->subject, info->plain_body,
669 info->attachments_list);
671 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
672 info->bcc, info->subject, info->html_body,
673 info->plain_body, info->attachments_list,
680 /* Set priority flags in message */
681 header = tny_msg_get_header (new_msg);
682 tny_header_set_flag (header, info->priority_flags);
684 /* Set attachment flags in message */
685 if (info->attachments_list != NULL)
686 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
688 g_object_unref (G_OBJECT(header));
690 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
691 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
692 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
693 "modest: failed to create a new msg\n");
701 g_free (info->plain_body);
702 g_free (info->html_body);
703 g_free (info->subject);
704 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
705 g_list_free (info->attachments_list);
706 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
707 g_list_free (info->images_list);
709 if (info->callback) {
710 CreateMsgIdleInfo *idle_info;
711 idle_info = g_slice_new0 (CreateMsgIdleInfo);
712 idle_info->mail_op = g_object_ref (info->mail_op);
713 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
714 idle_info->callback = info->callback;
715 idle_info->userdata = info->userdata;
716 g_idle_add (idle_create_msg_cb, idle_info);
718 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
721 g_object_unref (info->mail_op);
722 g_slice_free (CreateMsgInfo, info);
723 if (new_msg) g_object_unref(new_msg);
729 modest_mail_operation_create_msg (ModestMailOperation *self,
730 const gchar *from, const gchar *to,
731 const gchar *cc, const gchar *bcc,
732 const gchar *subject, const gchar *plain_body,
733 const gchar *html_body,
734 const GList *attachments_list,
735 const GList *images_list,
736 TnyHeaderFlags priority_flags,
737 ModestMailOperationCreateMsgCallback callback,
740 CreateMsgInfo *info = NULL;
742 info = g_slice_new0 (CreateMsgInfo);
743 info->mail_op = g_object_ref (self);
745 info->from = g_strdup (from);
746 info->to = g_strdup (to);
747 info->cc = g_strdup (cc);
748 info->bcc = g_strdup (bcc);
749 info->subject = g_strdup (subject);
750 info->plain_body = g_strdup (plain_body);
751 info->html_body = g_strdup (html_body);
752 info->attachments_list = g_list_copy ((GList *) attachments_list);
753 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
754 info->images_list = g_list_copy ((GList *) images_list);
755 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
756 info->priority_flags = priority_flags;
758 info->callback = callback;
759 info->userdata = userdata;
761 g_thread_create (create_msg_thread, info, FALSE, NULL);
766 TnyTransportAccount *transport_account;
771 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
775 ModestMailOperationPrivate *priv = NULL;
776 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
777 TnyFolder *draft_folder = NULL;
778 TnyFolder *outbox_folder = NULL;
779 TnyHeader *header = NULL;
786 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
789 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
790 modest_mail_operation_notify_end (self);
794 /* Call mail operation */
795 modest_mail_operation_send_mail (self, info->transport_account, msg);
797 if (info->draft_msg != NULL) {
798 TnyFolder *folder = NULL;
799 TnyFolder *src_folder = NULL;
800 TnyFolderType folder_type;
801 TnyTransportAccount *transport_account = NULL;
803 /* To remove the old mail from its source folder, we need to get the
804 * transport account of the original draft message (the transport account
805 * might have been changed by the user) */
806 header = tny_msg_get_header (info->draft_msg);
807 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
808 modest_runtime_get_account_store(), header);
809 if (transport_account == NULL)
810 transport_account = g_object_ref(info->transport_account);
811 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
812 TNY_FOLDER_TYPE_DRAFTS);
813 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
814 TNY_FOLDER_TYPE_OUTBOX);
815 g_object_unref(transport_account);
818 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
822 if (!outbox_folder) {
823 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
828 folder = tny_msg_get_folder (info->draft_msg);
829 if (folder == NULL) goto end;
830 folder_type = modest_tny_folder_guess_folder_type (folder);
832 if (folder_type == TNY_FOLDER_TYPE_INVALID)
833 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
835 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
836 src_folder = outbox_folder;
838 src_folder = draft_folder;
840 /* Note: This can fail (with a warning) if the message is not really already in a folder,
841 * because this function requires it to have a UID. */
842 tny_folder_remove_msg (src_folder, header, NULL);
844 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
845 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
847 g_object_unref (folder);
852 g_object_unref (header);
856 g_object_unref (info->draft_msg);
858 g_object_unref (draft_folder);
860 g_object_unref (outbox_folder);
861 if (info->transport_account)
862 g_object_unref (info->transport_account);
863 g_slice_free (SendNewMailInfo, info);
867 modest_mail_operation_send_new_mail (ModestMailOperation *self,
868 TnyTransportAccount *transport_account,
870 const gchar *from, const gchar *to,
871 const gchar *cc, const gchar *bcc,
872 const gchar *subject, const gchar *plain_body,
873 const gchar *html_body,
874 const GList *attachments_list,
875 const GList *images_list,
876 TnyHeaderFlags priority_flags)
878 ModestMailOperationPrivate *priv = NULL;
879 SendNewMailInfo *info;
881 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
882 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
884 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
885 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
886 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
887 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
889 /* Check parametters */
891 /* Set status failed and set an error */
892 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
893 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
894 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
895 _("Error trying to send a mail. You need to set at least one recipient"));
898 info = g_slice_new0 (SendNewMailInfo);
899 info->transport_account = transport_account;
900 if (transport_account)
901 g_object_ref (transport_account);
902 info->draft_msg = draft_msg;
904 g_object_ref (draft_msg);
907 modest_mail_operation_notify_start (self);
908 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
909 attachments_list, images_list, priority_flags,
910 modest_mail_operation_send_new_mail_cb, info);
916 TnyTransportAccount *transport_account;
918 SaveToDraftstCallback callback;
922 ModestMailOperation *mailop;
923 } SaveToDraftsAddMsgInfo;
926 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
931 ModestMailOperationPrivate *priv = NULL;
932 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
934 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
937 g_warning ("%s: priv->error != NULL", __FUNCTION__);
938 g_error_free(priv->error);
941 priv->error = (err == NULL) ? NULL : g_error_copy(err);
943 if ((!priv->error) && (info->draft_msg != NULL)) {
944 TnyHeader *header = tny_msg_get_header (info->draft_msg);
945 TnyFolder *src_folder = tny_header_get_folder (header);
947 /* Remove the old draft */
948 tny_folder_remove_msg (src_folder, header, NULL);
950 /* Synchronize to expunge and to update the msg counts */
951 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
952 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
954 g_object_unref (G_OBJECT(header));
955 g_object_unref (G_OBJECT(src_folder));
959 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
961 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
963 /* Call the user callback */
965 info->callback (info->mailop, info->msg, info->user_data);
967 if (info->transport_account)
968 g_object_unref (G_OBJECT(info->transport_account));
970 g_object_unref (G_OBJECT (info->draft_msg));
972 g_object_unref (G_OBJECT(info->drafts));
974 g_object_unref (G_OBJECT (info->msg));
976 modest_mail_operation_notify_end (info->mailop);
977 g_object_unref(info->mailop);
978 g_slice_free (SaveToDraftsAddMsgInfo, info);
983 TnyTransportAccount *transport_account;
985 SaveToDraftstCallback callback;
990 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
994 TnyFolder *drafts = NULL;
995 ModestMailOperationPrivate *priv = NULL;
996 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
998 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1001 if (!(priv->error)) {
1002 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1003 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1004 "modest: failed to create a new msg\n");
1007 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1008 TNY_FOLDER_TYPE_DRAFTS);
1009 if (!drafts && !(priv->error)) {
1010 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1011 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1012 "modest: failed to create a new msg\n");
1017 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1018 cb_info->transport_account = g_object_ref(info->transport_account);
1019 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1020 cb_info->callback = info->callback;
1021 cb_info->user_data = info->user_data;
1022 cb_info->drafts = g_object_ref(drafts);
1023 cb_info->msg = g_object_ref(msg);
1024 cb_info->mailop = g_object_ref(self);
1025 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1028 /* Call the user callback */
1029 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1031 info->callback (self, msg, info->user_data);
1032 modest_mail_operation_notify_end (self);
1036 g_object_unref (G_OBJECT(drafts));
1037 if (info->draft_msg)
1038 g_object_unref (G_OBJECT (info->draft_msg));
1039 if (info->transport_account)
1040 g_object_unref (G_OBJECT(info->transport_account));
1041 g_slice_free (SaveToDraftsInfo, info);
1045 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1046 TnyTransportAccount *transport_account,
1048 const gchar *from, const gchar *to,
1049 const gchar *cc, const gchar *bcc,
1050 const gchar *subject, const gchar *plain_body,
1051 const gchar *html_body,
1052 const GList *attachments_list,
1053 const GList *images_list,
1054 TnyHeaderFlags priority_flags,
1055 SaveToDraftstCallback callback,
1058 ModestMailOperationPrivate *priv = NULL;
1059 SaveToDraftsInfo *info = NULL;
1061 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1062 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1064 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1066 /* Get account and set it into mail_operation */
1067 priv->account = g_object_ref (transport_account);
1068 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1070 info = g_slice_new0 (SaveToDraftsInfo);
1071 info->transport_account = g_object_ref (transport_account);
1072 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1073 info->callback = callback;
1074 info->user_data = user_data;
1076 modest_mail_operation_notify_start (self);
1077 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1078 attachments_list, images_list, priority_flags,
1079 modest_mail_operation_save_to_drafts_cb, info);
1084 ModestMailOperation *mail_op;
1085 TnyMimePart *mime_part;
1087 GetMimePartSizeCallback callback;
1089 } GetMimePartSizeInfo;
1091 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1092 /* We use this folder observer to track the headers that have been
1093 * added to a folder */
1096 TnyList *new_headers;
1097 } InternalFolderObserver;
1100 GObjectClass parent;
1101 } InternalFolderObserverClass;
1103 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1105 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1106 internal_folder_observer,
1108 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1112 foreach_add_item (gpointer header, gpointer user_data)
1114 tny_list_prepend (TNY_LIST (user_data),
1115 g_object_ref (G_OBJECT (header)));
1118 /* This is the method that looks for new messages in a folder */
1120 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1122 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1124 TnyFolderChangeChanged changed;
1126 changed = tny_folder_change_get_changed (change);
1128 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1131 /* Get added headers */
1132 list = tny_simple_list_new ();
1133 tny_folder_change_get_added_headers (change, list);
1135 /* Add them to the folder observer */
1136 tny_list_foreach (list, foreach_add_item,
1137 derived->new_headers);
1139 g_object_unref (G_OBJECT (list));
1144 internal_folder_observer_init (InternalFolderObserver *self)
1146 self->new_headers = tny_simple_list_new ();
1149 internal_folder_observer_finalize (GObject *object)
1151 InternalFolderObserver *self;
1153 self = (InternalFolderObserver *) object;
1154 g_object_unref (self->new_headers);
1156 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1159 tny_folder_observer_init (TnyFolderObserverIface *iface)
1161 iface->update = internal_folder_observer_update;
1164 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1166 GObjectClass *object_class;
1168 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1169 object_class = (GObjectClass*) klass;
1170 object_class->finalize = internal_folder_observer_finalize;
1175 ModestMailOperation *mail_op;
1176 gchar *account_name;
1177 UpdateAccountCallback callback;
1182 TnyFolderObserver *inbox_observer;
1183 RetrieveAllCallback retrieve_all_cb;
1184 gboolean interactive;
1185 } UpdateAccountInfo;
1189 destroy_update_account_info (UpdateAccountInfo *info)
1191 g_free (info->account_name);
1192 g_object_unref (info->folders);
1193 g_object_unref (info->mail_op);
1194 g_slice_free (UpdateAccountInfo, info);
1198 update_account_get_msg_async_cb (TnyFolder *folder,
1204 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1206 /* Just delete the helper. Don't do anything with the new
1207 msg. There is also no need to check for errors */
1208 g_object_unref (msg_info->mail_op);
1209 g_object_unref (msg_info->header);
1210 g_slice_free (GetMsgInfo, msg_info);
1214 inbox_refreshed_cb (TnyFolder *inbox,
1219 UpdateAccountInfo *info;
1220 ModestMailOperationPrivate *priv;
1221 TnyIterator *new_headers_iter;
1222 GPtrArray *new_headers_array = NULL;
1223 gint max_size, retrieve_limit, i;
1224 ModestAccountMgr *mgr;
1225 ModestAccountRetrieveType retrieve_type;
1226 TnyList *new_headers = NULL;
1227 gboolean headers_only, ignore_limit, succeeded;
1228 TnyTransportAccount *transport_account = NULL;
1230 info = (UpdateAccountInfo *) user_data;
1231 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1232 mgr = modest_runtime_get_account_mgr ();
1234 if (canceled || err || !inbox) {
1235 /* Try to send anyway */
1239 /* Get the message max size */
1240 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1241 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1243 max_size = G_MAXINT;
1245 max_size = max_size * KB;
1247 /* Create the new headers array. We need it to sort the
1248 new headers by date */
1249 new_headers_array = g_ptr_array_new ();
1250 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1251 while (!tny_iterator_is_done (new_headers_iter)) {
1252 TnyHeader *header = NULL;
1254 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1255 /* Apply per-message size limits */
1256 if (tny_header_get_message_size (header) < max_size)
1257 g_ptr_array_add (new_headers_array, g_object_ref (header));
1259 g_object_unref (header);
1260 tny_iterator_next (new_headers_iter);
1262 g_object_unref (new_headers_iter);
1263 tny_folder_remove_observer (inbox, info->inbox_observer);
1264 g_object_unref (info->inbox_observer);
1265 info->inbox_observer = NULL;
1267 /* Update the last updated key, even if we don't have to get new headers */
1268 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1269 if (!canceled && !err)
1270 modest_account_mgr_set_server_account_username_has_succeeded (mgr, tny_account_get_id (priv->account), TRUE);
1272 if (new_headers_array->len == 0)
1275 /* Get per-account message amount retrieval limit */
1276 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1277 if (retrieve_limit == 0)
1278 retrieve_limit = G_MAXINT;
1280 /* Get per-account retrieval type */
1281 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1282 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1285 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1287 /* Ask the users if they want to retrieve all the messages
1288 even though the limit was exceeded */
1289 ignore_limit = FALSE;
1290 if (new_headers_array->len > retrieve_limit) {
1291 /* Ask the user if a callback has been specified and
1292 if the mail operation has a source (this means that
1293 was invoked by the user and not automatically by a
1295 if (info->retrieve_all_cb && priv->source)
1296 ignore_limit = info->retrieve_all_cb (priv->source,
1297 new_headers_array->len,
1301 if (!headers_only) {
1303 const gint msg_list_size = compute_message_array_size (new_headers_array);
1307 priv->total = new_headers_array->len;
1309 priv->total = MIN (new_headers_array->len, retrieve_limit);
1310 while (msg_num < priv->total) {
1311 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1312 TnyFolder *folder = tny_header_get_folder (header);
1313 GetMsgInfo *msg_info;
1315 /* Create the message info */
1316 msg_info = g_slice_new0 (GetMsgInfo);
1317 msg_info->mail_op = g_object_ref (info->mail_op);
1318 msg_info->header = g_object_ref (header);
1319 msg_info->total_bytes = msg_list_size;
1321 /* Get message in an async way */
1322 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1323 get_msg_status_cb, msg_info);
1325 g_object_unref (folder);
1331 /* Copy the headers to a list and free the array */
1332 new_headers = tny_simple_list_new ();
1333 for (i=0; i < new_headers_array->len; i++) {
1334 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1335 tny_list_append (new_headers, G_OBJECT (header));
1337 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1338 g_ptr_array_free (new_headers_array, FALSE);
1344 modest_account_mgr_set_server_account_username_has_succeeded (modest_runtime_get_account_mgr (),
1345 tny_account_get_name (priv->account),
1348 /* Get the transport account */
1349 transport_account = (TnyTransportAccount *)
1350 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1351 info->account_name);
1353 if (transport_account) {
1354 ModestTnySendQueue *send_queue;
1358 send_queue = modest_runtime_get_send_queue (transport_account);
1359 g_object_unref (transport_account);
1361 /* Get outbox folder */
1362 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1363 if (outbox) { /* this could fail in some cases */
1364 num_messages = tny_folder_get_all_count (outbox);
1365 g_object_unref (outbox);
1367 g_warning ("%s: could not get outbox", __FUNCTION__);
1371 if (num_messages != 0) {
1372 /* Reenable suspended items */
1373 modest_tny_send_queue_wakeup (MODEST_TNY_SEND_QUEUE (send_queue));
1376 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (send_queue));
1377 modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue),
1382 /* Check if the operation was a success */
1384 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1386 /* Set the account back to not busy */
1387 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1389 /* Call the user callback */
1391 info->callback (info->mail_op, new_headers, info->user_data);
1393 /* Notify about operation end */
1394 modest_mail_operation_notify_end (info->mail_op);
1398 g_object_unref (new_headers);
1399 destroy_update_account_info (info);
1403 recurse_folders_async_cb (TnyFolderStore *folder_store,
1409 UpdateAccountInfo *info;
1410 ModestMailOperationPrivate *priv;
1412 info = (UpdateAccountInfo *) user_data;
1413 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1415 if (err || canceled) {
1416 /* Try to continue anyway */
1417 } else if (info->poke_all) {
1418 /* We're not getting INBOX children if we don't want to poke all */
1419 TnyIterator *iter = tny_list_create_iterator (list);
1420 while (!tny_iterator_is_done (iter)) {
1421 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1422 TnyList *folders = tny_simple_list_new ();
1424 /* Add to the list of all folders */
1425 tny_list_append (info->folders, (GObject *) folder);
1427 /* Add pending call */
1428 info->pending_calls++;
1430 tny_folder_store_get_folders_async (folder, folders, NULL,
1431 recurse_folders_async_cb,
1434 g_object_unref (G_OBJECT (folder));
1436 tny_iterator_next (iter);
1438 g_object_unref (G_OBJECT (iter));
1439 g_object_unref (G_OBJECT (list));
1442 /* Remove my own pending call */
1443 info->pending_calls--;
1445 /* This means that we have all the folders */
1446 if (info->pending_calls == 0) {
1447 TnyIterator *iter_all_folders;
1448 TnyFolder *inbox = NULL;
1450 iter_all_folders = tny_list_create_iterator (info->folders);
1452 /* Do a poke status over all folders */
1453 while (!tny_iterator_is_done (iter_all_folders) &&
1454 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1455 TnyFolder *folder = NULL;
1457 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1459 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1460 /* Get a reference to the INBOX */
1461 inbox = g_object_ref (folder);
1463 /* Issue a poke status over the folder */
1465 tny_folder_poke_status (folder);
1468 /* Free and go to next */
1469 g_object_unref (folder);
1470 tny_iterator_next (iter_all_folders);
1472 g_object_unref (iter_all_folders);
1474 /* Refresh the INBOX */
1476 /* Refresh the folder. Our observer receives
1477 * the new emails during folder refreshes, so
1478 * we can use observer->new_headers
1480 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1481 tny_folder_add_observer (inbox, info->inbox_observer);
1483 /* Refresh the INBOX */
1484 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1485 g_object_unref (inbox);
1487 /* We could not perform the inbox refresh but
1488 we'll try to send mails anyway */
1489 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1495 modest_mail_operation_update_account (ModestMailOperation *self,
1496 const gchar *account_name,
1498 gboolean interactive,
1499 RetrieveAllCallback retrieve_all_cb,
1500 UpdateAccountCallback callback,
1503 UpdateAccountInfo *info = NULL;
1504 ModestMailOperationPrivate *priv = NULL;
1505 ModestTnyAccountStore *account_store = NULL;
1507 ModestMailOperationState *state;
1509 /* Init mail operation */
1510 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1513 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1514 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1516 /* Get the store account */
1517 account_store = modest_runtime_get_account_store ();
1519 modest_tny_account_store_get_server_account (account_store,
1521 TNY_ACCOUNT_TYPE_STORE);
1523 /* The above function could return NULL */
1524 if (!priv->account) {
1525 /* Check if the operation was a success */
1526 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1527 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1529 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1531 /* Call the user callback */
1533 callback (self, NULL, user_data);
1535 /* Notify about operation end */
1536 modest_mail_operation_notify_end (self);
1541 /* Create the helper object */
1542 info = g_slice_new0 (UpdateAccountInfo);
1543 info->pending_calls = 1;
1544 info->folders = tny_simple_list_new ();
1545 info->mail_op = g_object_ref (self);
1546 info->poke_all = poke_all;
1547 info->interactive = interactive;
1548 info->account_name = g_strdup (account_name);
1549 info->callback = callback;
1550 info->user_data = user_data;
1551 info->retrieve_all_cb = retrieve_all_cb;
1553 /* Set account busy */
1554 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1555 modest_mail_operation_notify_start (self);
1557 /* notify about the start of the operation */
1558 state = modest_mail_operation_clone_state (self);
1562 /* Start notifying progress */
1563 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1564 g_slice_free (ModestMailOperationState, state);
1566 /* Get all folders and continue in the callback */
1567 folders = tny_simple_list_new ();
1568 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (priv->account),
1570 recurse_folders_async_cb,
1575 * Used to notify the queue from the main
1576 * loop. We call it inside an idle call to achieve that
1579 idle_notify_queue (gpointer data)
1581 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1583 gdk_threads_enter ();
1584 modest_mail_operation_notify_end (mail_op);
1585 gdk_threads_leave ();
1586 g_object_unref (mail_op);
1592 compare_headers_by_date (gconstpointer a,
1595 TnyHeader **header1, **header2;
1596 time_t sent1, sent2;
1598 header1 = (TnyHeader **) a;
1599 header2 = (TnyHeader **) b;
1601 sent1 = tny_header_get_date_sent (*header1);
1602 sent2 = tny_header_get_date_sent (*header2);
1604 /* We want the most recent ones (greater time_t) at the
1613 /* ******************************************************************* */
1614 /* ************************** STORE ACTIONS ************************* */
1615 /* ******************************************************************* */
1618 ModestMailOperation *mail_op;
1619 CreateFolderUserCallback callback;
1625 create_folder_cb (TnyFolderStore *parent_folder,
1627 TnyFolder *new_folder,
1631 ModestMailOperationPrivate *priv;
1632 CreateFolderInfo *info;
1634 info = (CreateFolderInfo *) user_data;
1635 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1637 if (canceled || err) {
1638 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1640 priv->error = g_error_copy (err);
1642 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1643 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1646 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1649 /* The user will unref the new_folder */
1651 info->callback (info->mail_op, parent_folder,
1652 new_folder, info->user_data);
1654 /* Notify about operation end */
1655 modest_mail_operation_notify_end (info->mail_op);
1658 g_object_unref (info->mail_op);
1659 g_slice_free (CreateFolderInfo, info);
1663 modest_mail_operation_create_folder (ModestMailOperation *self,
1664 TnyFolderStore *parent,
1666 CreateFolderUserCallback callback,
1669 ModestMailOperationPrivate *priv;
1671 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1672 g_return_if_fail (name);
1674 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1675 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1676 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1677 g_object_ref (parent) :
1678 modest_tny_folder_get_account (TNY_FOLDER (parent));
1680 /* Check for already existing folder */
1681 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1682 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1683 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1684 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1685 _CS("ckdg_ib_folder_already_exists"));
1689 if (TNY_IS_FOLDER (parent)) {
1690 /* Check folder rules */
1691 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1692 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1693 /* Set status failed and set an error */
1694 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1695 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1696 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1697 _("mail_in_ui_folder_create_error"));
1701 if (!strcmp (name, " ") || strchr (name, '/')) {
1702 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1703 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1704 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1705 _("mail_in_ui_folder_create_error"));
1709 CreateFolderInfo *info;
1711 info = g_slice_new0 (CreateFolderInfo);
1712 info->mail_op = g_object_ref (self);
1713 info->callback = callback;
1714 info->user_data = user_data;
1716 modest_mail_operation_notify_start (self);
1718 /* Create the folder */
1719 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1722 /* Call the user callback anyway */
1724 callback (self, parent, NULL, user_data);
1725 /* Notify about operation end */
1726 modest_mail_operation_notify_end (self);
1731 modest_mail_operation_remove_folder (ModestMailOperation *self,
1733 gboolean remove_to_trash)
1735 ModestMailOperationPrivate *priv;
1736 ModestTnyFolderRules rules;
1738 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1739 g_return_if_fail (TNY_IS_FOLDER (folder));
1741 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1743 /* Check folder rules */
1744 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1745 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1746 /* Set status failed and set an error */
1747 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1748 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1749 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1750 _("mail_in_ui_folder_delete_error"));
1754 /* Get the account */
1755 priv->account = modest_tny_folder_get_account (folder);
1756 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1758 /* Delete folder or move to trash */
1759 if (remove_to_trash) {
1760 TnyFolder *trash_folder = NULL;
1761 trash_folder = modest_tny_account_get_special_folder (priv->account,
1762 TNY_FOLDER_TYPE_TRASH);
1763 /* TODO: error_handling */
1765 modest_mail_operation_notify_start (self);
1766 modest_mail_operation_xfer_folder (self, folder,
1767 TNY_FOLDER_STORE (trash_folder),
1769 g_object_unref (trash_folder);
1771 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1774 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1776 modest_mail_operation_notify_start (self);
1777 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1778 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1781 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1783 g_object_unref (parent);
1785 g_warning ("%s: could not get parent folder", __FUNCTION__);
1789 /* Notify about operation end */
1790 modest_mail_operation_notify_end (self);
1794 transfer_folder_status_cb (GObject *obj,
1798 ModestMailOperation *self;
1799 ModestMailOperationPrivate *priv;
1800 ModestMailOperationState *state;
1801 XFerFolderAsyncHelper *helper;
1803 g_return_if_fail (status != NULL);
1804 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1806 helper = (XFerFolderAsyncHelper *) user_data;
1807 g_return_if_fail (helper != NULL);
1809 self = helper->mail_op;
1810 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1812 priv->done = status->position;
1813 priv->total = status->of_total;
1815 state = modest_mail_operation_clone_state (self);
1817 /* This is not a GDK lock because we are a Tinymail callback
1818 * which is already GDK locked by Tinymail */
1820 /* no gdk_threads_enter (), CHECKED */
1822 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1824 /* no gdk_threads_leave (), CHECKED */
1826 g_slice_free (ModestMailOperationState, state);
1831 transfer_folder_cb (TnyFolder *folder,
1833 TnyFolderStore *into,
1834 TnyFolder *new_folder,
1838 XFerFolderAsyncHelper *helper;
1839 ModestMailOperation *self = NULL;
1840 ModestMailOperationPrivate *priv = NULL;
1842 helper = (XFerFolderAsyncHelper *) user_data;
1843 g_return_if_fail (helper != NULL);
1845 self = helper->mail_op;
1846 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1849 priv->error = g_error_copy (err);
1851 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1852 } else if (cancelled) {
1853 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1854 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1855 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1856 _("Transference of %s was cancelled."),
1857 tny_folder_get_name (folder));
1860 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1863 /* Notify about operation end */
1864 modest_mail_operation_notify_end (self);
1866 /* If user defined callback function was defined, call it */
1867 if (helper->user_callback) {
1869 /* This is not a GDK lock because we are a Tinymail callback
1870 * which is already GDK locked by Tinymail */
1872 /* no gdk_threads_enter (), CHECKED */
1873 helper->user_callback (self, new_folder, helper->user_data);
1874 /* no gdk_threads_leave () , CHECKED */
1878 g_object_unref (helper->mail_op);
1879 g_slice_free (XFerFolderAsyncHelper, helper);
1884 * This function checks if the new name is a valid name for our local
1885 * folders account. The new name could not be the same than then name
1886 * of any of the mandatory local folders
1888 * We can not rely on tinymail because tinymail does not check the
1889 * name of the virtual folders that the account could have in the case
1890 * that we're doing a rename (because it directly calls Camel which
1891 * knows nothing about our virtual folders).
1893 * In the case of an actual copy/move (i.e. move/copy a folder between
1894 * accounts) tinymail uses the tny_folder_store_create_account which
1895 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1896 * checks the new name of the folder, so this call in that case
1897 * wouldn't be needed. *But* NOTE that if tinymail changes its
1898 * implementation (if folder transfers within the same account is no
1899 * longer implemented as a rename) this call will allow Modest to work
1902 * If the new name is not valid, this function will set the status to
1903 * failed and will set also an error in the mail operation
1906 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1907 TnyFolderStore *into,
1908 const gchar *new_name)
1910 if (TNY_IS_ACCOUNT (into) &&
1911 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1912 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1914 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1915 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1916 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1917 _CS("ckdg_ib_folder_already_exists"));
1924 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1926 TnyFolderStore *parent,
1927 gboolean delete_original,
1928 XferFolderAsyncUserCallback user_callback,
1931 ModestMailOperationPrivate *priv = NULL;
1932 ModestTnyFolderRules parent_rules = 0, rules;
1933 XFerFolderAsyncHelper *helper = NULL;
1934 const gchar *folder_name = NULL;
1935 const gchar *error_msg;
1937 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1938 g_return_if_fail (TNY_IS_FOLDER (folder));
1939 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1941 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1942 folder_name = tny_folder_get_name (folder);
1944 /* Set the error msg */
1945 error_msg = _("mail_in_ui_folder_move_target_error");
1947 /* Get account and set it into mail_operation */
1948 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1949 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1950 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1952 /* Get folder rules */
1953 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1954 if (TNY_IS_FOLDER (parent))
1955 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1957 /* Apply operation constraints */
1958 if ((gpointer) parent == (gpointer) folder ||
1959 (!TNY_IS_FOLDER_STORE (parent)) ||
1960 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1963 } else if (TNY_IS_FOLDER (parent) &&
1964 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
1968 } else if (TNY_IS_FOLDER (parent) &&
1969 TNY_IS_FOLDER_STORE (folder) &&
1970 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
1971 TNY_FOLDER_STORE (folder))) {
1972 /* Do not move a parent into a child */
1974 } else if (TNY_IS_FOLDER_STORE (parent) &&
1975 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
1976 /* Check that the new folder name is not used by any
1979 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
1980 /* Check that the new folder name is not used by any
1981 special local folder */
1984 /* Create the helper */
1985 helper = g_slice_new0 (XFerFolderAsyncHelper);
1986 helper->mail_op = g_object_ref (self);
1987 helper->user_callback = user_callback;
1988 helper->user_data = user_data;
1990 /* Move/Copy folder */
1991 modest_mail_operation_notify_start (self);
1992 tny_folder_copy_async (folder,
1994 tny_folder_get_name (folder),
1997 transfer_folder_status_cb,
2003 /* Set status failed and set an error */
2004 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2005 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2006 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2009 /* Call the user callback if exists */
2011 user_callback (self, NULL, user_data);
2013 /* Notify the queue */
2014 modest_mail_operation_notify_end (self);
2018 modest_mail_operation_rename_folder (ModestMailOperation *self,
2021 XferFolderAsyncUserCallback user_callback,
2024 ModestMailOperationPrivate *priv;
2025 ModestTnyFolderRules rules;
2026 XFerFolderAsyncHelper *helper;
2028 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2029 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2030 g_return_if_fail (name);
2032 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2034 /* Get account and set it into mail_operation */
2035 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2036 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2038 /* Check folder rules */
2039 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2040 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2042 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2045 TnyFolderStore *into;
2047 into = tny_folder_get_folder_store (folder);
2049 /* Check that the new folder name is not used by any
2050 special local folder */
2051 if (new_name_valid_if_local_account (priv, into, name)) {
2052 /* Create the helper */
2053 helper = g_slice_new0 (XFerFolderAsyncHelper);
2054 helper->mail_op = g_object_ref(self);
2055 helper->user_callback = user_callback;
2056 helper->user_data = user_data;
2058 /* Rename. Camel handles folder subscription/unsubscription */
2059 modest_mail_operation_notify_start (self);
2060 tny_folder_copy_async (folder, into, name, TRUE,
2062 transfer_folder_status_cb,
2067 g_object_unref (into);
2072 /* Set status failed and set an error */
2073 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2074 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2075 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2076 _("FIXME: unable to rename"));
2079 user_callback (self, NULL, user_data);
2081 /* Notify about operation end */
2082 modest_mail_operation_notify_end (self);
2085 /* ******************************************************************* */
2086 /* ************************** MSG ACTIONS ************************* */
2087 /* ******************************************************************* */
2090 modest_mail_operation_get_msg (ModestMailOperation *self,
2092 GetMsgAsyncUserCallback user_callback,
2095 GetMsgInfo *helper = NULL;
2097 ModestMailOperationPrivate *priv;
2099 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2100 g_return_if_fail (TNY_IS_HEADER (header));
2102 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2103 folder = tny_header_get_folder (header);
2105 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2109 /* Get account and set it into mail_operation */
2110 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2112 /* Check for cached messages */
2113 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2114 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2116 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2118 /* Create the helper */
2119 helper = g_slice_new0 (GetMsgInfo);
2120 helper->header = g_object_ref (header);
2121 helper->mail_op = g_object_ref (self);
2122 helper->user_callback = user_callback;
2123 helper->user_data = user_data;
2124 helper->destroy_notify = NULL;
2125 helper->last_total_bytes = 0;
2126 helper->sum_total_bytes = 0;
2127 helper->total_bytes = tny_header_get_message_size (header);
2129 modest_mail_operation_notify_start (self);
2131 /* notify about the start of the operation */
2132 ModestMailOperationState *state;
2133 state = modest_mail_operation_clone_state (self);
2136 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2139 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2141 g_object_unref (G_OBJECT (folder));
2145 get_msg_status_cb (GObject *obj,
2149 GetMsgInfo *helper = NULL;
2151 g_return_if_fail (status != NULL);
2152 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2154 helper = (GetMsgInfo *) user_data;
2155 g_return_if_fail (helper != NULL);
2157 /* Notify progress */
2158 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2159 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2163 get_msg_async_cb (TnyFolder *folder,
2169 GetMsgInfo *info = NULL;
2170 ModestMailOperationPrivate *priv = NULL;
2173 info = (GetMsgInfo *) user_data;
2175 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2178 if (info->more_msgs) {
2179 tny_iterator_next (info->more_msgs);
2180 finished = (tny_iterator_is_done (info->more_msgs));
2182 finished = (priv->done == priv->total) ? TRUE : FALSE;
2185 /* If canceled by the user, ignore the error given by Tinymail */
2186 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED) {
2189 } else if (canceled || err) {
2190 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2192 priv->error = g_error_copy ((const GError *) err);
2193 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2196 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2197 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2200 } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
2201 /* Set the success status before calling the user callback */
2202 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2206 /* Call the user callback */
2207 if (info->user_callback)
2208 info->user_callback (info->mail_op, info->header, canceled,
2209 msg, err, info->user_data);
2211 /* Notify about operation end if this is the last callback */
2213 /* Free user data */
2214 if (info->destroy_notify)
2215 info->destroy_notify (info->user_data);
2217 /* Notify about operation end */
2218 modest_mail_operation_notify_end (info->mail_op);
2221 if (info->more_msgs)
2222 g_object_unref (info->more_msgs);
2223 g_object_unref (info->header);
2224 g_object_unref (info->mail_op);
2225 g_slice_free (GetMsgInfo, info);
2226 } else if (info->more_msgs) {
2227 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->more_msgs));
2228 TnyFolder *folder = tny_header_get_folder (header);
2230 g_object_unref (info->header);
2231 info->header = g_object_ref (header);
2233 /* Retrieve the next message */
2234 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, info);
2236 g_object_unref (header);
2237 g_object_unref (folder);
2239 g_warning ("%s: finished != TRUE but no messages left", __FUNCTION__);
2244 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2245 TnyList *header_list,
2246 GetMsgAsyncUserCallback user_callback,
2248 GDestroyNotify notify)
2250 ModestMailOperationPrivate *priv = NULL;
2252 TnyIterator *iter = NULL;
2253 gboolean has_uncached_messages;
2255 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2257 /* Init mail operation */
2258 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2259 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2261 priv->total = tny_list_get_length(header_list);
2263 /* Check uncached messages */
2264 for (iter = tny_list_create_iterator (header_list), has_uncached_messages = FALSE;
2265 !has_uncached_messages && !tny_iterator_is_done (iter);
2266 tny_iterator_next (iter)) {
2269 header = (TnyHeader *) tny_iterator_get_current (iter);
2270 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
2271 has_uncached_messages = TRUE;
2272 g_object_unref (header);
2274 g_object_unref (iter);
2275 priv->op_type = has_uncached_messages?MODEST_MAIL_OPERATION_TYPE_RECEIVE:MODEST_MAIL_OPERATION_TYPE_OPEN;
2277 /* Get account and set it into mail_operation */
2278 if (tny_list_get_length (header_list) >= 1) {
2279 TnyIterator *iterator = tny_list_create_iterator (header_list);
2280 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iterator));
2282 TnyFolder *folder = tny_header_get_folder (header);
2284 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2285 g_object_unref (folder);
2287 g_object_unref (header);
2289 g_object_unref (iterator);
2292 msg_list_size = compute_message_list_size (header_list);
2294 modest_mail_operation_notify_start (self);
2295 iter = tny_list_create_iterator (header_list);
2296 if (!tny_iterator_is_done (iter)) {
2297 /* notify about the start of the operation */
2298 ModestMailOperationState *state;
2299 state = modest_mail_operation_clone_state (self);
2302 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2305 GetMsgInfo *msg_info = NULL;
2306 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2307 TnyFolder *folder = tny_header_get_folder (header);
2309 /* Create the message info */
2310 msg_info = g_slice_new0 (GetMsgInfo);
2311 msg_info->mail_op = g_object_ref (self);
2312 msg_info->header = g_object_ref (header);
2313 msg_info->more_msgs = g_object_ref (iter);
2314 msg_info->user_callback = user_callback;
2315 msg_info->user_data = user_data;
2316 msg_info->destroy_notify = notify;
2317 msg_info->last_total_bytes = 0;
2318 msg_info->sum_total_bytes = 0;
2319 msg_info->total_bytes = msg_list_size;
2321 /* The callback will call it per each header */
2322 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2324 /* Free and go on */
2325 g_object_unref (header);
2326 g_object_unref (folder);
2327 g_slice_free (ModestMailOperationState, state);
2329 g_object_unref (iter);
2334 modest_mail_operation_remove_msg (ModestMailOperation *self,
2336 gboolean remove_to_trash /*ignored*/)
2339 ModestMailOperationPrivate *priv;
2341 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2342 g_return_if_fail (TNY_IS_HEADER (header));
2344 if (remove_to_trash)
2345 g_warning ("remove to trash is not implemented");
2347 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2348 folder = tny_header_get_folder (header);
2350 /* Get account and set it into mail_operation */
2351 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2352 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2353 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2355 /* remove message from folder */
2356 tny_folder_remove_msg (folder, header, &(priv->error));
2358 gboolean expunge, leave_on_server;
2359 const gchar *account_name;
2360 TnyAccount *account;
2361 ModestTransportStoreProtocol account_proto;
2363 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2364 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2366 modest_mail_operation_notify_start (self);
2368 /* Get leave on server setting */
2369 account = tny_folder_get_account (folder);
2370 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2372 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2375 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2377 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2378 modest_tny_folder_is_remote_folder (folder) == FALSE)
2384 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2387 g_object_unref (account);
2393 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2395 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2398 g_object_unref (G_OBJECT (folder));
2400 /* Notify about operation end */
2401 modest_mail_operation_notify_end (self);
2405 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2407 gboolean remove_to_trash /*ignored*/)
2409 TnyFolder *folder = NULL;
2410 ModestMailOperationPrivate *priv;
2411 TnyIterator *iter = NULL;
2412 TnyHeader *header = NULL;
2413 TnyList *remove_headers = NULL;
2414 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2416 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2417 g_return_if_fail (TNY_IS_LIST (headers));
2419 if (remove_to_trash)
2420 g_warning ("remove to trash is not implemented");
2422 if (tny_list_get_length(headers) == 0) {
2423 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2424 goto cleanup; /* nothing to do */
2427 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2428 remove_headers = g_object_ref(headers);
2430 /* Get folder from first header and sync it */
2431 iter = tny_list_create_iterator (headers);
2432 header = TNY_HEADER (tny_iterator_get_current (iter));
2434 folder = tny_header_get_folder (header);
2435 if (!TNY_IS_FOLDER(folder)) {
2436 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2440 /* Don't remove messages that are being sent */
2441 if (modest_tny_folder_is_local_folder (folder)) {
2442 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2444 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2445 TnyTransportAccount *traccount = NULL;
2446 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2447 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2449 ModestTnySendQueueStatus status;
2450 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2451 TnyIterator *iter = tny_list_create_iterator(headers);
2452 g_object_unref(remove_headers);
2453 remove_headers = TNY_LIST(tny_simple_list_new());
2454 while (!tny_iterator_is_done(iter)) {
2456 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2457 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2458 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2459 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2460 tny_list_append(remove_headers, G_OBJECT(hdr));
2462 g_object_unref(hdr);
2464 tny_iterator_next(iter);
2466 g_object_unref(iter);
2467 g_object_unref(traccount);
2471 /* Get account and set it into mail_operation */
2472 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2473 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2474 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2476 /* remove message from folder */
2477 modest_mail_operation_notify_start (self);
2479 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2481 gboolean expunge, leave_on_server;
2482 const gchar *account_name;
2484 TnyAccount *account;
2485 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2487 account = tny_folder_get_account (folder);
2488 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2490 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2493 proto = tny_account_get_proto (account);
2495 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2498 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2499 modest_tny_folder_is_remote_folder (folder) == FALSE)
2505 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2507 g_object_unref (account);
2513 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2515 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2520 g_object_unref (remove_headers);
2522 g_object_unref (header);
2524 g_object_unref (iter);
2526 g_object_unref (folder);
2528 /* Notify about operation end */
2529 modest_mail_operation_notify_end (self);
2533 notify_progress_of_multiple_messages (ModestMailOperation *self,
2535 gint *last_total_bytes,
2536 gint *sum_total_bytes,
2538 gboolean increment_done)
2540 ModestMailOperationPrivate *priv;
2541 ModestMailOperationState *state;
2542 gboolean is_num_bytes = FALSE;
2544 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2546 /* We know that tinymail sends us information about
2547 * transferred bytes with this particular message
2549 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2550 * I just added the 'if' so we don't get runtime warning)
2552 if (status->message)
2553 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2555 state = modest_mail_operation_clone_state (self);
2556 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2557 /* We know that we're in a different message when the
2558 total number of bytes to transfer is different. Of
2559 course it could fail if we're transferring messages
2560 of the same size, but this is a workarround */
2561 if (status->of_total != *last_total_bytes) {
2562 /* We need to increment the done when there is
2563 no information about each individual
2564 message, we need to do this in message
2565 transfers, and we don't do it for getting
2569 *sum_total_bytes += *last_total_bytes;
2570 *last_total_bytes = status->of_total;
2572 state->bytes_done += status->position + *sum_total_bytes;
2573 state->bytes_total = total_bytes;
2575 /* Notify the status change. Only notify about changes
2576 referred to bytes */
2577 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2581 g_slice_free (ModestMailOperationState, state);
2585 transfer_msgs_status_cb (GObject *obj,
2589 XFerMsgsAsyncHelper *helper;
2591 g_return_if_fail (status != NULL);
2592 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2594 helper = (XFerMsgsAsyncHelper *) user_data;
2595 g_return_if_fail (helper != NULL);
2597 /* Notify progress */
2598 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2599 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2604 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2606 XFerMsgsAsyncHelper *helper;
2607 ModestMailOperation *self;
2608 ModestMailOperationPrivate *priv;
2609 gboolean finished = TRUE;
2611 helper = (XFerMsgsAsyncHelper *) user_data;
2612 self = helper->mail_op;
2614 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2617 priv->error = g_error_copy (err);
2619 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2620 } else if (cancelled) {
2621 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2622 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2623 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2624 _("Error trying to refresh the contents of %s"),
2625 tny_folder_get_name (folder));
2626 } else if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
2627 if (helper->more_msgs) {
2628 /* We'll transfer the next message in the list */
2629 tny_iterator_next (helper->more_msgs);
2630 if (!tny_iterator_is_done (helper->more_msgs)) {
2631 GObject *next_header;
2632 g_object_unref (helper->headers);
2633 helper->headers = tny_simple_list_new ();
2634 next_header = tny_iterator_get_current (helper->more_msgs);
2635 tny_list_append (helper->headers, next_header);
2636 g_object_unref (next_header);
2643 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2649 /* Update folder counts */
2650 tny_folder_poke_status (folder);
2651 tny_folder_poke_status (helper->dest_folder);
2653 /* Notify about operation end */
2654 modest_mail_operation_notify_end (self);
2656 /* If user defined callback function was defined, call it */
2657 if (helper->user_callback) {
2658 /* This is not a GDK lock because we are a Tinymail callback and
2659 * Tinymail already acquires the Gdk lock */
2661 /* no gdk_threads_enter (), CHECKED */
2662 helper->user_callback (self, helper->user_data);
2663 /* no gdk_threads_leave (), CHECKED */
2667 if (helper->more_msgs)
2668 g_object_unref (helper->more_msgs);
2669 if (helper->headers)
2670 g_object_unref (helper->headers);
2671 if (helper->dest_folder)
2672 g_object_unref (helper->dest_folder);
2673 if (helper->mail_op)
2674 g_object_unref (helper->mail_op);
2675 g_slice_free (XFerMsgsAsyncHelper, helper);
2677 /* Transfer more messages */
2678 tny_folder_transfer_msgs_async (folder,
2680 helper->dest_folder,
2683 transfer_msgs_status_cb,
2689 compute_message_list_size (TnyList *headers)
2694 iter = tny_list_create_iterator (headers);
2695 while (!tny_iterator_is_done (iter)) {
2696 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2697 size += tny_header_get_message_size (header);
2698 g_object_unref (header);
2699 tny_iterator_next (iter);
2701 g_object_unref (iter);
2707 compute_message_array_size (GPtrArray *headers)
2712 for (i = 0; i < headers->len; i++) {
2713 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2714 size += tny_header_get_message_size (header);
2722 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2725 gboolean delete_original,
2726 XferMsgsAsyncUserCallback user_callback,
2729 ModestMailOperationPrivate *priv = NULL;
2730 TnyIterator *iter = NULL;
2731 TnyFolder *src_folder = NULL;
2732 XFerMsgsAsyncHelper *helper = NULL;
2733 TnyHeader *header = NULL;
2734 ModestTnyFolderRules rules = 0;
2735 TnyAccount *dst_account = NULL;
2736 gboolean leave_on_server;
2738 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2739 g_return_if_fail (headers && TNY_IS_LIST (headers));
2740 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2742 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2743 priv->total = tny_list_get_length (headers);
2745 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2746 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2748 /* Apply folder rules */
2749 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2750 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2751 /* Set status failed and set an error */
2752 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2753 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2754 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2755 _CS("ckct_ib_unable_to_paste_here"));
2756 /* Notify the queue */
2757 modest_mail_operation_notify_end (self);
2761 /* Get source folder */
2762 iter = tny_list_create_iterator (headers);
2763 header = TNY_HEADER (tny_iterator_get_current (iter));
2765 src_folder = tny_header_get_folder (header);
2766 g_object_unref (header);
2768 g_object_unref (iter);
2770 if (src_folder == NULL) {
2771 /* Notify the queue */
2772 modest_mail_operation_notify_end (self);
2774 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2779 /* Check folder source and destination */
2780 if (src_folder == folder) {
2781 /* Set status failed and set an error */
2782 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2783 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2784 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2785 _("mail_in_ui_folder_copy_target_error"));
2787 /* Notify the queue */
2788 modest_mail_operation_notify_end (self);
2791 g_object_unref (src_folder);
2795 /* Create the helper */
2796 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2797 helper->mail_op = g_object_ref(self);
2798 helper->dest_folder = g_object_ref(folder);
2799 helper->user_callback = user_callback;
2800 helper->user_data = user_data;
2801 helper->delete = delete_original;
2802 helper->last_total_bytes = 0;
2803 helper->sum_total_bytes = 0;
2804 helper->total_bytes = compute_message_list_size (headers);
2806 /* Get account and set it into mail_operation */
2807 priv->account = modest_tny_folder_get_account (src_folder);
2808 dst_account = modest_tny_folder_get_account (folder);
2810 if (priv->account == dst_account) {
2811 /* Transfer all messages at once using the fast
2812 * method. Note that depending on the server this
2813 * might not be that fast, and might not be
2814 * user-cancellable either */
2815 helper->headers = g_object_ref (headers);
2816 helper->more_msgs = NULL;
2818 /* Transfer messages one by one so the user can cancel
2821 helper->headers = tny_simple_list_new ();
2822 helper->more_msgs = tny_list_create_iterator (headers);
2823 hdr = tny_iterator_get_current (helper->more_msgs);
2824 tny_list_append (helper->headers, hdr);
2825 g_object_unref (hdr);
2828 /* If leave_on_server is set to TRUE then don't use
2829 delete_original, we always pass FALSE. This is because
2830 otherwise tinymail will try to sync the source folder and
2831 this could cause an error if we're offline while
2832 transferring an already downloaded message from a POP
2834 if (modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (priv->account)) ==
2835 MODEST_PROTOCOL_STORE_POP) {
2836 const gchar *account_name;
2838 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (priv->account);
2839 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2842 leave_on_server = FALSE;
2845 modest_mail_operation_notify_start (self);
2846 tny_folder_transfer_msgs_async (src_folder,
2849 (leave_on_server) ? FALSE : delete_original,
2851 transfer_msgs_status_cb,
2853 g_object_unref (src_folder);
2854 g_object_unref (dst_account);
2859 on_refresh_folder (TnyFolder *folder,
2864 RefreshAsyncHelper *helper = NULL;
2865 ModestMailOperation *self = NULL;
2866 ModestMailOperationPrivate *priv = NULL;
2868 helper = (RefreshAsyncHelper *) user_data;
2869 self = helper->mail_op;
2870 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2872 g_return_if_fail(priv!=NULL);
2875 priv->error = g_error_copy (error);
2876 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2881 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2882 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2883 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2884 _("Error trying to refresh the contents of %s"),
2885 tny_folder_get_name (folder));
2889 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2892 /* Call user defined callback, if it exists */
2893 if (helper->user_callback) {
2895 /* This is not a GDK lock because we are a Tinymail callback and
2896 * Tinymail already acquires the Gdk lock */
2897 helper->user_callback (self, folder, helper->user_data);
2901 g_slice_free (RefreshAsyncHelper, helper);
2903 /* Notify about operation end */
2904 modest_mail_operation_notify_end (self);
2905 g_object_unref(self);
2909 on_refresh_folder_status_update (GObject *obj,
2913 RefreshAsyncHelper *helper = NULL;
2914 ModestMailOperation *self = NULL;
2915 ModestMailOperationPrivate *priv = NULL;
2916 ModestMailOperationState *state;
2918 g_return_if_fail (user_data != NULL);
2919 g_return_if_fail (status != NULL);
2920 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2922 helper = (RefreshAsyncHelper *) user_data;
2923 self = helper->mail_op;
2924 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2926 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2928 priv->done = status->position;
2929 priv->total = status->of_total;
2931 state = modest_mail_operation_clone_state (self);
2933 /* This is not a GDK lock because we are a Tinymail callback and
2934 * Tinymail already acquires the Gdk lock */
2935 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2937 g_slice_free (ModestMailOperationState, state);
2941 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2943 RefreshAsyncUserCallback user_callback,
2946 ModestMailOperationPrivate *priv = NULL;
2947 RefreshAsyncHelper *helper = NULL;
2949 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2951 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2953 /* Get account and set it into mail_operation */
2954 priv->account = modest_tny_folder_get_account (folder);
2955 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2957 /* Create the helper */
2958 helper = g_slice_new0 (RefreshAsyncHelper);
2959 helper->mail_op = g_object_ref(self);
2960 helper->user_callback = user_callback;
2961 helper->user_data = user_data;
2963 modest_mail_operation_notify_start (self);
2965 /* notify that the operation was started */
2966 ModestMailOperationState *state;
2967 state = modest_mail_operation_clone_state (self);
2970 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2973 /* FIXME: we're leaking the state here, or? valgrind thinks so */
2975 tny_folder_refresh_async (folder,
2977 on_refresh_folder_status_update,
2982 run_queue_stop (ModestTnySendQueue *queue,
2983 ModestMailOperation *self)
2985 ModestMailOperationPrivate *priv;
2987 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2988 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2989 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2991 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2993 modest_mail_operation_notify_end (self);
2994 g_signal_handlers_disconnect_by_func (queue, run_queue_stop, self);
2995 g_object_unref (self);
2998 modest_mail_operation_run_queue (ModestMailOperation *self,
2999 ModestTnySendQueue *queue)
3001 ModestMailOperationPrivate *priv;
3003 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3004 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
3005 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3007 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3008 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
3009 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
3011 modest_mail_operation_notify_start (self);
3012 g_object_ref (self);
3013 g_signal_connect ((gpointer) queue, "queue-stop", G_CALLBACK (run_queue_stop), (gpointer) self);
3017 sync_folder_finish_callback (TnyFolder *self, gboolean cancelled, GError *err, ModestMailOperation *mail_op)
3019 ModestMailOperationPrivate *priv;
3021 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3023 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3024 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
3026 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3028 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3030 modest_mail_operation_notify_end (mail_op);
3031 g_object_unref (mail_op);
3035 modest_mail_operation_sync_folder (ModestMailOperation *self,
3036 TnyFolder *folder, gboolean expunge)
3038 ModestMailOperationPrivate *priv;
3040 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3041 g_return_if_fail (TNY_IS_FOLDER (folder));
3042 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3044 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3045 priv->account = TNY_ACCOUNT (tny_folder_get_account (folder));
3046 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
3048 modest_mail_operation_notify_start (self);
3049 g_object_ref (self);
3050 tny_folder_sync_async (folder, expunge, (TnyFolderCallback) sync_folder_finish_callback, NULL, self);
3054 modest_mail_operation_notify_start (ModestMailOperation *self)
3056 ModestMailOperationPrivate *priv = NULL;
3058 g_return_if_fail (self);
3060 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3062 /* Ensure that all the fields are filled correctly */
3063 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
3065 /* Notify the observers about the mail operation. We do not
3066 wrapp this emission because we assume that this function is
3067 always called from within the main lock */
3068 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
3073 * It's used by the mail operation queue to notify the observers
3074 * attached to that signal that the operation finished. We need to use
3075 * that because tinymail does not give us the progress of a given
3076 * operation when it finishes (it directly calls the operation
3080 modest_mail_operation_notify_end (ModestMailOperation *self)
3082 ModestMailOperationPrivate *priv = NULL;
3084 g_return_if_fail (self);
3086 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3088 /* Notify the observers about the mail operation end. We do
3089 not wrapp this emission because we assume that this
3090 function is always called from within the main lock */
3091 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3093 /* Remove the error user data */
3094 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3095 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3099 modest_mail_operation_get_account (ModestMailOperation *self)
3101 ModestMailOperationPrivate *priv = NULL;
3103 g_return_val_if_fail (self, NULL);
3105 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3107 return (priv->account) ? g_object_ref (priv->account) : NULL;
3111 modest_mail_operation_noop (ModestMailOperation *self)
3113 ModestMailOperationPrivate *priv = NULL;
3115 g_return_if_fail (self);
3117 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3118 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3119 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3123 /* This mail operation does nothing actually */
3124 modest_mail_operation_notify_start (self);
3125 modest_mail_operation_notify_end (self);
3130 modest_mail_operation_to_string (ModestMailOperation *self)
3132 const gchar *type, *status, *account_id;
3133 ModestMailOperationPrivate *priv = NULL;
3135 g_return_val_if_fail (self, NULL);
3137 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3139 /* new operations don't have anything interesting */
3140 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3141 return g_strdup_printf ("%p <new operation>", self);
3143 switch (priv->op_type) {
3144 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3145 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3146 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3147 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3148 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3149 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3150 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3151 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3152 default: type = "UNEXPECTED"; break;
3155 switch (priv->status) {
3156 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3157 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3158 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3159 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3160 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3161 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3162 default: status= "UNEXPECTED"; break;
3165 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3167 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3168 priv->done, priv->total,
3169 priv->error && priv->error->message ? priv->error->message : "");