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 TnyList *header_list;
141 ModestMailOperation *mail_op;
142 GDestroyNotify destroy_notify;
143 gint last_total_bytes;
144 gint sum_total_bytes;
148 typedef struct _RefreshAsyncHelper {
149 ModestMailOperation *mail_op;
150 RefreshAsyncUserCallback user_callback;
152 } RefreshAsyncHelper;
154 typedef struct _XFerMsgsAsyncHelper
156 ModestMailOperation *mail_op;
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);
492 /* Note that if we call cancel with an already canceled mail
493 operation the progress changed signal won't be emitted */
494 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
498 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
500 /* Cancel the mail operation */
501 g_return_val_if_fail (priv->account, FALSE);
502 tny_account_cancel (priv->account);
504 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
505 ModestTnySendQueue *queue;
506 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
508 /* Cancel the sending of the following next messages */
509 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, NULL);
516 modest_mail_operation_get_task_done (ModestMailOperation *self)
518 ModestMailOperationPrivate *priv;
520 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
523 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
528 modest_mail_operation_get_task_total (ModestMailOperation *self)
530 ModestMailOperationPrivate *priv;
532 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
535 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
540 modest_mail_operation_is_finished (ModestMailOperation *self)
542 ModestMailOperationPrivate *priv;
543 gboolean retval = FALSE;
545 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
548 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
550 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
551 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
552 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
553 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
563 * Creates an image of the current state of a mail operation, the
564 * caller must free it
566 static ModestMailOperationState *
567 modest_mail_operation_clone_state (ModestMailOperation *self)
569 ModestMailOperationState *state;
570 ModestMailOperationPrivate *priv;
572 /* FIXME: this should be fixed properly
574 * in some cases, priv was NULL, so checking here to
577 g_return_val_if_fail (self, NULL);
578 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
579 g_return_val_if_fail (priv, NULL);
584 state = g_slice_new (ModestMailOperationState);
586 state->status = priv->status;
587 state->op_type = priv->op_type;
588 state->done = priv->done;
589 state->total = priv->total;
590 state->finished = modest_mail_operation_is_finished (self);
591 state->bytes_done = 0;
592 state->bytes_total = 0;
597 /* ******************************************************************* */
598 /* ************************** SEND ACTIONS ************************* */
599 /* ******************************************************************* */
602 modest_mail_operation_send_mail (ModestMailOperation *self,
603 TnyTransportAccount *transport_account,
606 TnySendQueue *send_queue = NULL;
607 ModestMailOperationPrivate *priv;
609 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
610 g_return_if_fail (transport_account && TNY_IS_TRANSPORT_ACCOUNT (transport_account));
611 g_return_if_fail (msg && TNY_IS_MSG (msg));
613 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
615 /* Get account and set it into mail_operation */
616 priv->account = g_object_ref (transport_account);
617 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
621 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
622 if (!TNY_IS_SEND_QUEUE(send_queue)) {
623 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
624 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
625 "modest: could not find send queue for account\n");
626 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
627 modest_mail_operation_notify_end (self);
630 /* Add the msg to the queue */
631 modest_mail_operation_notify_start (self);
633 tny_send_queue_add_async (send_queue, msg, NULL, NULL, NULL);
635 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
636 modest_mail_operation_notify_end (self);
643 idle_create_msg_cb (gpointer idle_data)
645 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
647 /* This is a GDK lock because we are an idle callback and
648 * info->callback can contain Gtk+ code */
650 gdk_threads_enter (); /* CHECKED */
651 info->callback (info->mail_op, info->msg, info->userdata);
653 g_object_unref (info->mail_op);
655 g_object_unref (info->msg);
656 g_slice_free (CreateMsgIdleInfo, info);
657 gdk_threads_leave (); /* CHECKED */
663 create_msg_thread (gpointer thread_data)
665 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
666 TnyMsg *new_msg = NULL;
667 ModestMailOperationPrivate *priv;
669 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
670 if (info->html_body == NULL) {
671 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
672 info->bcc, info->subject, info->plain_body,
673 info->attachments_list);
675 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
676 info->bcc, info->subject, info->html_body,
677 info->plain_body, info->attachments_list,
684 /* Set priority flags in message */
685 header = tny_msg_get_header (new_msg);
686 tny_header_set_flag (header, info->priority_flags);
688 /* Set attachment flags in message */
689 if (info->attachments_list != NULL)
690 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
692 g_object_unref (G_OBJECT(header));
694 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
695 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
696 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
697 "modest: failed to create a new msg\n");
705 g_free (info->plain_body);
706 g_free (info->html_body);
707 g_free (info->subject);
708 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
709 g_list_free (info->attachments_list);
710 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
711 g_list_free (info->images_list);
713 if (info->callback) {
714 CreateMsgIdleInfo *idle_info;
715 idle_info = g_slice_new0 (CreateMsgIdleInfo);
716 idle_info->mail_op = g_object_ref (info->mail_op);
717 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
718 idle_info->callback = info->callback;
719 idle_info->userdata = info->userdata;
720 g_idle_add (idle_create_msg_cb, idle_info);
722 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
725 g_object_unref (info->mail_op);
726 g_slice_free (CreateMsgInfo, info);
727 if (new_msg) g_object_unref(new_msg);
733 modest_mail_operation_create_msg (ModestMailOperation *self,
734 const gchar *from, const gchar *to,
735 const gchar *cc, const gchar *bcc,
736 const gchar *subject, const gchar *plain_body,
737 const gchar *html_body,
738 const GList *attachments_list,
739 const GList *images_list,
740 TnyHeaderFlags priority_flags,
741 ModestMailOperationCreateMsgCallback callback,
744 ModestMailOperationPrivate *priv;
745 CreateMsgInfo *info = NULL;
747 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
749 info = g_slice_new0 (CreateMsgInfo);
750 info->mail_op = g_object_ref (self);
752 info->from = g_strdup (from);
753 info->to = g_strdup (to);
754 info->cc = g_strdup (cc);
755 info->bcc = g_strdup (bcc);
756 info->subject = g_strdup (subject);
757 info->plain_body = g_strdup (plain_body);
758 info->html_body = g_strdup (html_body);
759 info->attachments_list = g_list_copy ((GList *) attachments_list);
760 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
761 info->images_list = g_list_copy ((GList *) images_list);
762 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
763 info->priority_flags = priority_flags;
765 info->callback = callback;
766 info->userdata = userdata;
768 g_thread_create (create_msg_thread, info, FALSE, NULL);
773 TnyTransportAccount *transport_account;
778 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
782 ModestMailOperationPrivate *priv = NULL;
783 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
784 TnyFolder *draft_folder = NULL;
785 TnyFolder *outbox_folder = NULL;
786 TnyHeader *header = NULL;
793 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
796 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
797 modest_mail_operation_notify_end (self);
801 /* Call mail operation */
802 modest_mail_operation_send_mail (self, info->transport_account, msg);
804 if (info->draft_msg != NULL) {
805 TnyFolder *folder = NULL;
806 TnyFolder *src_folder = NULL;
807 TnyFolderType folder_type;
808 TnyTransportAccount *transport_account = NULL;
810 /* To remove the old mail from its source folder, we need to get the
811 * transport account of the original draft message (the transport account
812 * might have been changed by the user) */
813 header = tny_msg_get_header (info->draft_msg);
814 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
815 modest_runtime_get_account_store(), header);
816 if (transport_account == NULL)
817 transport_account = g_object_ref(info->transport_account);
818 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
819 TNY_FOLDER_TYPE_DRAFTS);
820 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
821 TNY_FOLDER_TYPE_OUTBOX);
822 g_object_unref(transport_account);
825 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
829 if (!outbox_folder) {
830 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
835 folder = tny_msg_get_folder (info->draft_msg);
836 if (folder == NULL) goto end;
837 folder_type = modest_tny_folder_guess_folder_type (folder);
839 if (folder_type == TNY_FOLDER_TYPE_INVALID)
840 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
842 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
843 src_folder = outbox_folder;
845 src_folder = draft_folder;
847 /* Note: This can fail (with a warning) if the message is not really already in a folder,
848 * because this function requires it to have a UID. */
849 tny_folder_remove_msg (src_folder, header, NULL);
851 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
852 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
854 g_object_unref (folder);
859 g_object_unref (header);
863 g_object_unref (info->draft_msg);
865 g_object_unref (draft_folder);
867 g_object_unref (outbox_folder);
868 if (info->transport_account)
869 g_object_unref (info->transport_account);
870 g_slice_free (SendNewMailInfo, info);
874 modest_mail_operation_send_new_mail (ModestMailOperation *self,
875 TnyTransportAccount *transport_account,
877 const gchar *from, const gchar *to,
878 const gchar *cc, const gchar *bcc,
879 const gchar *subject, const gchar *plain_body,
880 const gchar *html_body,
881 const GList *attachments_list,
882 const GList *images_list,
883 TnyHeaderFlags priority_flags)
885 ModestMailOperationPrivate *priv = NULL;
886 SendNewMailInfo *info;
888 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
889 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
891 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
892 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
893 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
894 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
896 /* Check parametters */
898 /* Set status failed and set an error */
899 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
900 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
901 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
902 _("Error trying to send a mail. You need to set at least one recipient"));
905 info = g_slice_new0 (SendNewMailInfo);
906 info->transport_account = transport_account;
907 if (transport_account)
908 g_object_ref (transport_account);
909 info->draft_msg = draft_msg;
911 g_object_ref (draft_msg);
914 modest_mail_operation_notify_start (self);
915 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
916 attachments_list, images_list, priority_flags,
917 modest_mail_operation_send_new_mail_cb, info);
923 TnyTransportAccount *transport_account;
925 SaveToDraftstCallback callback;
929 ModestMailOperation *mailop;
930 } SaveToDraftsAddMsgInfo;
933 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
938 ModestMailOperationPrivate *priv = NULL;
939 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
941 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
944 g_warning ("%s: priv->error != NULL", __FUNCTION__);
945 g_error_free(priv->error);
948 priv->error = (err == NULL) ? NULL : g_error_copy(err);
950 if ((!priv->error) && (info->draft_msg != NULL)) {
951 TnyHeader *header = tny_msg_get_header (info->draft_msg);
952 TnyFolder *src_folder = tny_header_get_folder (header);
954 /* Remove the old draft */
955 tny_folder_remove_msg (src_folder, header, NULL);
957 /* Synchronize to expunge and to update the msg counts */
958 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
959 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
961 g_object_unref (G_OBJECT(header));
962 g_object_unref (G_OBJECT(src_folder));
966 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
968 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
970 /* Call the user callback */
972 info->callback (info->mailop, info->msg, info->user_data);
974 if (info->transport_account)
975 g_object_unref (G_OBJECT(info->transport_account));
977 g_object_unref (G_OBJECT (info->draft_msg));
979 g_object_unref (G_OBJECT(info->drafts));
981 g_object_unref (G_OBJECT (info->msg));
983 modest_mail_operation_notify_end (info->mailop);
984 g_object_unref(info->mailop);
985 g_slice_free (SaveToDraftsAddMsgInfo, info);
990 TnyTransportAccount *transport_account;
992 SaveToDraftstCallback callback;
997 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1001 TnyFolder *drafts = NULL;
1002 ModestMailOperationPrivate *priv = NULL;
1003 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1005 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1008 if (!(priv->error)) {
1009 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1010 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1011 "modest: failed to create a new msg\n");
1014 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1015 TNY_FOLDER_TYPE_DRAFTS);
1016 if (!drafts && !(priv->error)) {
1017 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1018 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1019 "modest: failed to create a new msg\n");
1024 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1025 cb_info->transport_account = g_object_ref(info->transport_account);
1026 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1027 cb_info->callback = info->callback;
1028 cb_info->user_data = info->user_data;
1029 cb_info->drafts = g_object_ref(drafts);
1030 cb_info->msg = g_object_ref(msg);
1031 cb_info->mailop = g_object_ref(self);
1032 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1035 /* Call the user callback */
1036 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1038 info->callback (self, msg, info->user_data);
1039 modest_mail_operation_notify_end (self);
1043 g_object_unref (G_OBJECT(drafts));
1044 if (info->draft_msg)
1045 g_object_unref (G_OBJECT (info->draft_msg));
1046 if (info->transport_account)
1047 g_object_unref (G_OBJECT(info->transport_account));
1048 g_slice_free (SaveToDraftsInfo, info);
1052 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1053 TnyTransportAccount *transport_account,
1055 const gchar *from, const gchar *to,
1056 const gchar *cc, const gchar *bcc,
1057 const gchar *subject, const gchar *plain_body,
1058 const gchar *html_body,
1059 const GList *attachments_list,
1060 const GList *images_list,
1061 TnyHeaderFlags priority_flags,
1062 SaveToDraftstCallback callback,
1065 ModestMailOperationPrivate *priv = NULL;
1066 SaveToDraftsInfo *info = NULL;
1068 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1069 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1071 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1073 /* Get account and set it into mail_operation */
1074 priv->account = g_object_ref (transport_account);
1075 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1077 info = g_slice_new0 (SaveToDraftsInfo);
1078 info->transport_account = g_object_ref (transport_account);
1079 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1080 info->callback = callback;
1081 info->user_data = user_data;
1083 modest_mail_operation_notify_start (self);
1084 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1085 attachments_list, images_list, priority_flags,
1086 modest_mail_operation_save_to_drafts_cb, info);
1091 ModestMailOperation *mail_op;
1092 TnyMimePart *mime_part;
1094 GetMimePartSizeCallback callback;
1096 } GetMimePartSizeInfo;
1098 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1099 /* We use this folder observer to track the headers that have been
1100 * added to a folder */
1103 TnyList *new_headers;
1104 } InternalFolderObserver;
1107 GObjectClass parent;
1108 } InternalFolderObserverClass;
1110 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1112 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1113 internal_folder_observer,
1115 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1119 foreach_add_item (gpointer header, gpointer user_data)
1121 tny_list_prepend (TNY_LIST (user_data),
1122 g_object_ref (G_OBJECT (header)));
1125 /* This is the method that looks for new messages in a folder */
1127 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1129 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1131 TnyFolderChangeChanged changed;
1133 changed = tny_folder_change_get_changed (change);
1135 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1138 /* Get added headers */
1139 list = tny_simple_list_new ();
1140 tny_folder_change_get_added_headers (change, list);
1142 /* Add them to the folder observer */
1143 tny_list_foreach (list, foreach_add_item,
1144 derived->new_headers);
1146 g_object_unref (G_OBJECT (list));
1151 internal_folder_observer_init (InternalFolderObserver *self)
1153 self->new_headers = tny_simple_list_new ();
1156 internal_folder_observer_finalize (GObject *object)
1158 InternalFolderObserver *self;
1160 self = (InternalFolderObserver *) object;
1161 g_object_unref (self->new_headers);
1163 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1166 tny_folder_observer_init (TnyFolderObserverIface *iface)
1168 iface->update = internal_folder_observer_update;
1171 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1173 GObjectClass *object_class;
1175 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1176 object_class = (GObjectClass*) klass;
1177 object_class->finalize = internal_folder_observer_finalize;
1182 ModestMailOperation *mail_op;
1183 gchar *account_name;
1184 UpdateAccountCallback callback;
1189 TnyFolderObserver *inbox_observer;
1190 RetrieveAllCallback retrieve_all_cb;
1191 } UpdateAccountInfo;
1195 destroy_update_account_info (UpdateAccountInfo *info)
1197 g_free (info->account_name);
1198 g_object_unref (info->folders);
1199 g_object_unref (info->mail_op);
1200 g_slice_free (UpdateAccountInfo, info);
1204 update_account_get_msg_async_cb (TnyFolder *folder,
1210 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1212 /* Just delete the helper. Don't do anything with the new
1213 msg. There is also no need to check for errors */
1214 g_object_unref (msg_info->mail_op);
1215 g_object_unref (msg_info->header);
1216 g_slice_free (GetMsgInfo, msg_info);
1220 inbox_refreshed_cb (TnyFolder *inbox,
1225 UpdateAccountInfo *info;
1226 ModestMailOperationPrivate *priv;
1227 TnyIterator *new_headers_iter;
1228 GPtrArray *new_headers_array = NULL;
1229 gint max_size, retrieve_limit, i;
1230 ModestAccountMgr *mgr;
1231 ModestAccountRetrieveType retrieve_type;
1232 TnyList *new_headers = NULL;
1233 gboolean headers_only, ignore_limit;
1234 TnyTransportAccount *transport_account;
1236 info = (UpdateAccountInfo *) user_data;
1237 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1238 mgr = modest_runtime_get_account_mgr ();
1240 if (canceled || err || !inbox) {
1241 /* Try to send anyway */
1245 /* Get the message max size */
1246 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1247 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1249 max_size = G_MAXINT;
1251 max_size = max_size * KB;
1253 /* Create the new headers array. We need it to sort the
1254 new headers by date */
1255 new_headers_array = g_ptr_array_new ();
1256 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1257 while (!tny_iterator_is_done (new_headers_iter)) {
1258 TnyHeader *header = NULL;
1260 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1261 /* Apply per-message size limits */
1262 if (tny_header_get_message_size (header) < max_size)
1263 g_ptr_array_add (new_headers_array, g_object_ref (header));
1265 g_object_unref (header);
1266 tny_iterator_next (new_headers_iter);
1268 g_object_unref (new_headers_iter);
1269 tny_folder_remove_observer (inbox, info->inbox_observer);
1270 g_object_unref (info->inbox_observer);
1271 info->inbox_observer = NULL;
1273 /* Update the last updated key, even if we don't have to get new headers */
1274 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1276 if (new_headers_array->len == 0)
1279 /* Get per-account message amount retrieval limit */
1280 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1281 if (retrieve_limit == 0)
1282 retrieve_limit = G_MAXINT;
1284 /* Get per-account retrieval type */
1285 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1286 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1289 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1291 /* Ask the users if they want to retrieve all the messages
1292 even though the limit was exceeded */
1293 ignore_limit = FALSE;
1294 if (new_headers_array->len > retrieve_limit) {
1295 /* Ask the user if a callback has been specified and
1296 if the mail operation has a source (this means that
1297 was invoked by the user and not automatically by a
1299 if (info->retrieve_all_cb && priv->source)
1300 ignore_limit = info->retrieve_all_cb (priv->source,
1301 new_headers_array->len,
1305 if (!headers_only) {
1307 const gint msg_list_size = compute_message_array_size (new_headers_array);
1311 priv->total = new_headers_array->len;
1313 priv->total = MIN (new_headers_array->len, retrieve_limit);
1314 while (msg_num < priv->total) {
1315 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1316 TnyFolder *folder = tny_header_get_folder (header);
1317 GetMsgInfo *msg_info;
1319 /* Create the message info */
1320 msg_info = g_slice_new0 (GetMsgInfo);
1321 msg_info->mail_op = g_object_ref (info->mail_op);
1322 msg_info->header = g_object_ref (header);
1323 msg_info->total_bytes = msg_list_size;
1325 /* Get message in an async way */
1326 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1327 get_msg_status_cb, msg_info);
1329 g_object_unref (folder);
1335 /* Copy the headers to a list and free the array */
1336 new_headers = tny_simple_list_new ();
1337 for (i=0; i < new_headers_array->len; i++) {
1338 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1339 tny_list_append (new_headers, G_OBJECT (header));
1341 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1342 g_ptr_array_free (new_headers_array, FALSE);
1345 /* Get the transport account */
1346 transport_account = (TnyTransportAccount *)
1347 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1348 info->account_name);
1350 if (transport_account) {
1351 ModestTnySendQueue *send_queue;
1355 send_queue = modest_runtime_get_send_queue (transport_account);
1357 /* Get outbox folder */
1358 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1359 num_messages = tny_folder_get_all_count (outbox);
1360 g_object_unref (outbox);
1362 if (num_messages != 0) {
1364 g_object_unref (priv->account);
1366 /* Reenable suspended items */
1367 modest_tny_send_queue_wakeup (MODEST_TNY_SEND_QUEUE (send_queue));
1370 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (send_queue));
1374 /* Check if the operation was a success */
1376 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1378 /* Set the account back to not busy */
1379 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1381 /* Call the user callback */
1383 info->callback (info->mail_op, new_headers, info->user_data);
1385 /* Notify about operation end */
1386 modest_mail_operation_notify_end (info->mail_op);
1390 g_object_unref (new_headers);
1391 destroy_update_account_info (info);
1395 recurse_folders_async_cb (TnyFolderStore *folder_store,
1401 UpdateAccountInfo *info;
1402 ModestMailOperationPrivate *priv;
1404 info = (UpdateAccountInfo *) user_data;
1405 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1407 if (err || canceled) {
1408 /* Try to continue anyway */
1410 TnyIterator *iter = tny_list_create_iterator (list);
1411 while (!tny_iterator_is_done (iter)) {
1412 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1413 TnyList *folders = tny_simple_list_new ();
1415 /* Add to the list of all folders */
1416 tny_list_append (info->folders, (GObject *) folder);
1418 /* Add pending call */
1419 info->pending_calls++;
1421 tny_folder_store_get_folders_async (folder, folders, NULL,
1422 recurse_folders_async_cb,
1425 g_object_unref (G_OBJECT (folder));
1427 tny_iterator_next (iter);
1429 g_object_unref (G_OBJECT (iter));
1430 g_object_unref (G_OBJECT (list));
1433 /* Remove my own pending call */
1434 info->pending_calls--;
1436 /* This means that we have all the folders */
1437 if (info->pending_calls == 0) {
1438 TnyIterator *iter_all_folders;
1439 TnyFolder *inbox = NULL;
1441 iter_all_folders = tny_list_create_iterator (info->folders);
1443 /* Do a poke status over all folders */
1444 while (!tny_iterator_is_done (iter_all_folders) &&
1445 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1446 TnyFolder *folder = NULL;
1448 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1450 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1451 /* Get a reference to the INBOX */
1452 inbox = g_object_ref (folder);
1454 /* Issue a poke status over the folder */
1456 tny_folder_poke_status (folder);
1459 /* Free and go to next */
1460 g_object_unref (folder);
1461 tny_iterator_next (iter_all_folders);
1463 g_object_unref (iter_all_folders);
1465 /* Refresh the INBOX */
1467 /* Refresh the folder. Our observer receives
1468 * the new emails during folder refreshes, so
1469 * we can use observer->new_headers
1471 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1472 tny_folder_add_observer (inbox, info->inbox_observer);
1474 /* Refresh the INBOX */
1475 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1476 g_object_unref (inbox);
1478 /* We could not perform the inbox refresh but
1479 we'll try to send mails anyway */
1480 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1486 modest_mail_operation_update_account (ModestMailOperation *self,
1487 const gchar *account_name,
1489 RetrieveAllCallback retrieve_all_cb,
1490 UpdateAccountCallback callback,
1493 UpdateAccountInfo *info = NULL;
1494 ModestMailOperationPrivate *priv = NULL;
1495 ModestTnyAccountStore *account_store = NULL;
1496 TnyStoreAccount *store_account = NULL;
1498 ModestMailOperationState *state;
1500 /* Init mail operation */
1501 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1504 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1505 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1507 /* Get the store account */
1508 account_store = modest_runtime_get_account_store ();
1509 store_account = (TnyStoreAccount *)
1510 modest_tny_account_store_get_server_account (account_store,
1512 TNY_ACCOUNT_TYPE_STORE);
1513 priv->account = g_object_ref (store_account);
1515 /* Create the helper object */
1516 info = g_slice_new0 (UpdateAccountInfo);
1517 info->pending_calls = 1;
1518 info->folders = tny_simple_list_new ();
1519 info->mail_op = g_object_ref (self);
1520 info->poke_all = poke_all;
1521 info->account_name = g_strdup (account_name);
1522 info->callback = callback;
1523 info->user_data = user_data;
1524 info->retrieve_all_cb = retrieve_all_cb;
1526 /* Set account busy */
1527 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1528 modest_mail_operation_notify_start (self);
1530 /* notify about the start of the operation */
1531 state = modest_mail_operation_clone_state (self);
1535 /* Start notifying progress */
1536 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1537 g_slice_free (ModestMailOperationState, state);
1539 /* Get all folders and continue in the callback */
1540 folders = tny_simple_list_new ();
1541 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1543 recurse_folders_async_cb,
1548 * Used to notify the queue from the main
1549 * loop. We call it inside an idle call to achieve that
1552 idle_notify_queue (gpointer data)
1554 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1556 gdk_threads_enter ();
1557 modest_mail_operation_notify_end (mail_op);
1558 gdk_threads_leave ();
1559 g_object_unref (mail_op);
1565 compare_headers_by_date (gconstpointer a,
1568 TnyHeader **header1, **header2;
1569 time_t sent1, sent2;
1571 header1 = (TnyHeader **) a;
1572 header2 = (TnyHeader **) b;
1574 sent1 = tny_header_get_date_sent (*header1);
1575 sent2 = tny_header_get_date_sent (*header2);
1577 /* We want the most recent ones (greater time_t) at the
1586 /* ******************************************************************* */
1587 /* ************************** STORE ACTIONS ************************* */
1588 /* ******************************************************************* */
1591 ModestMailOperation *mail_op;
1592 CreateFolderUserCallback callback;
1598 create_folder_cb (TnyFolderStore *parent_folder,
1600 TnyFolder *new_folder,
1604 ModestMailOperationPrivate *priv;
1605 CreateFolderInfo *info;
1607 info = (CreateFolderInfo *) user_data;
1608 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1610 if (canceled || err) {
1611 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1613 priv->error = g_error_copy (err);
1615 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1616 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1619 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1622 /* The user will unref the new_folder */
1624 info->callback (info->mail_op, parent_folder,
1625 new_folder, info->user_data);
1627 /* Notify about operation end */
1628 modest_mail_operation_notify_end (info->mail_op);
1631 g_object_unref (info->mail_op);
1632 g_slice_free (CreateFolderInfo, info);
1636 modest_mail_operation_create_folder (ModestMailOperation *self,
1637 TnyFolderStore *parent,
1639 CreateFolderUserCallback callback,
1642 ModestMailOperationPrivate *priv;
1644 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1645 g_return_if_fail (name);
1647 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1648 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1649 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1650 g_object_ref (parent) :
1651 modest_tny_folder_get_account (TNY_FOLDER (parent));
1653 /* Check for already existing folder */
1654 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1655 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1656 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1657 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1658 _CS("ckdg_ib_folder_already_exists"));
1662 if (TNY_IS_FOLDER (parent)) {
1663 /* Check folder rules */
1664 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1665 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1666 /* Set status failed and set an error */
1667 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1668 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1669 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1670 _("mail_in_ui_folder_create_error"));
1674 if (!strcmp (name, " ") || strchr (name, '/')) {
1675 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1676 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1677 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1678 _("mail_in_ui_folder_create_error"));
1682 CreateFolderInfo *info;
1684 info = g_slice_new0 (CreateFolderInfo);
1685 info->mail_op = g_object_ref (self);
1686 info->callback = callback;
1687 info->user_data = user_data;
1689 modest_mail_operation_notify_start (self);
1691 /* Create the folder */
1692 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1695 /* Call the user callback anyway */
1697 callback (self, parent, NULL, user_data);
1698 /* Notify about operation end */
1699 modest_mail_operation_notify_end (self);
1704 modest_mail_operation_remove_folder (ModestMailOperation *self,
1706 gboolean remove_to_trash)
1708 TnyAccount *account;
1709 ModestMailOperationPrivate *priv;
1710 ModestTnyFolderRules rules;
1712 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1713 g_return_if_fail (TNY_IS_FOLDER (folder));
1715 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1717 /* Check folder rules */
1718 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1719 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1720 /* Set status failed and set an error */
1721 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1722 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1723 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1724 _("mail_in_ui_folder_delete_error"));
1728 /* Get the account */
1729 account = modest_tny_folder_get_account (folder);
1730 priv->account = g_object_ref(account);
1731 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1733 /* Delete folder or move to trash */
1734 if (remove_to_trash) {
1735 TnyFolder *trash_folder = NULL;
1736 trash_folder = modest_tny_account_get_special_folder (account,
1737 TNY_FOLDER_TYPE_TRASH);
1738 /* TODO: error_handling */
1740 modest_mail_operation_notify_start (self);
1741 modest_mail_operation_xfer_folder (self, folder,
1742 TNY_FOLDER_STORE (trash_folder),
1744 g_object_unref (trash_folder);
1746 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1749 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1751 modest_mail_operation_notify_start (self);
1752 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1753 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1756 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1758 g_object_unref (parent);
1760 g_warning ("%s: could not get parent folder", __FUNCTION__);
1762 g_object_unref (G_OBJECT (account));
1765 /* Notify about operation end */
1766 modest_mail_operation_notify_end (self);
1770 transfer_folder_status_cb (GObject *obj,
1774 ModestMailOperation *self;
1775 ModestMailOperationPrivate *priv;
1776 ModestMailOperationState *state;
1777 XFerFolderAsyncHelper *helper;
1779 g_return_if_fail (status != NULL);
1780 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1782 helper = (XFerFolderAsyncHelper *) user_data;
1783 g_return_if_fail (helper != NULL);
1785 self = helper->mail_op;
1786 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1788 priv->done = status->position;
1789 priv->total = status->of_total;
1791 state = modest_mail_operation_clone_state (self);
1793 /* This is not a GDK lock because we are a Tinymail callback
1794 * which is already GDK locked by Tinymail */
1796 /* no gdk_threads_enter (), CHECKED */
1798 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1800 /* no gdk_threads_leave (), CHECKED */
1802 g_slice_free (ModestMailOperationState, state);
1807 transfer_folder_cb (TnyFolder *folder,
1809 TnyFolderStore *into,
1810 TnyFolder *new_folder,
1814 XFerFolderAsyncHelper *helper;
1815 ModestMailOperation *self = NULL;
1816 ModestMailOperationPrivate *priv = NULL;
1818 helper = (XFerFolderAsyncHelper *) user_data;
1819 g_return_if_fail (helper != NULL);
1821 self = helper->mail_op;
1822 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1825 priv->error = g_error_copy (err);
1827 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1828 } else if (cancelled) {
1829 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1830 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1831 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1832 _("Transference of %s was cancelled."),
1833 tny_folder_get_name (folder));
1836 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1839 /* Notify about operation end */
1840 modest_mail_operation_notify_end (self);
1842 /* If user defined callback function was defined, call it */
1843 if (helper->user_callback) {
1845 /* This is not a GDK lock because we are a Tinymail callback
1846 * which is already GDK locked by Tinymail */
1848 /* no gdk_threads_enter (), CHECKED */
1849 helper->user_callback (self, new_folder, helper->user_data);
1850 /* no gdk_threads_leave () , CHECKED */
1854 g_object_unref (helper->mail_op);
1855 g_slice_free (XFerFolderAsyncHelper, helper);
1860 * This function checks if the new name is a valid name for our local
1861 * folders account. The new name could not be the same than then name
1862 * of any of the mandatory local folders
1864 * We can not rely on tinymail because tinymail does not check the
1865 * name of the virtual folders that the account could have in the case
1866 * that we're doing a rename (because it directly calls Camel which
1867 * knows nothing about our virtual folders).
1869 * In the case of an actual copy/move (i.e. move/copy a folder between
1870 * accounts) tinymail uses the tny_folder_store_create_account which
1871 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1872 * checks the new name of the folder, so this call in that case
1873 * wouldn't be needed. *But* NOTE that if tinymail changes its
1874 * implementation (if folder transfers within the same account is no
1875 * longer implemented as a rename) this call will allow Modest to work
1878 * If the new name is not valid, this function will set the status to
1879 * failed and will set also an error in the mail operation
1882 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1883 TnyFolderStore *into,
1884 const gchar *new_name)
1886 if (TNY_IS_ACCOUNT (into) &&
1887 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1888 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1890 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1891 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1892 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1893 _CS("ckdg_ib_folder_already_exists"));
1900 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1902 TnyFolderStore *parent,
1903 gboolean delete_original,
1904 XferFolderAsyncUserCallback user_callback,
1907 ModestMailOperationPrivate *priv = NULL;
1908 ModestTnyFolderRules parent_rules = 0, rules;
1909 XFerFolderAsyncHelper *helper = NULL;
1910 const gchar *folder_name = NULL;
1911 const gchar *error_msg;
1913 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1914 g_return_if_fail (TNY_IS_FOLDER (folder));
1915 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1917 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1918 folder_name = tny_folder_get_name (folder);
1920 /* Set the error msg */
1921 error_msg = _("mail_in_ui_folder_move_target_error");
1923 /* Get account and set it into mail_operation */
1924 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1925 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1926 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1928 /* Get folder rules */
1929 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1930 if (TNY_IS_FOLDER (parent))
1931 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1933 /* Apply operation constraints */
1934 if ((gpointer) parent == (gpointer) folder ||
1935 (!TNY_IS_FOLDER_STORE (parent)) ||
1936 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1939 } else if (TNY_IS_FOLDER (parent) &&
1940 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
1944 } else if (TNY_IS_FOLDER (parent) &&
1945 TNY_IS_FOLDER_STORE (folder) &&
1946 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
1947 TNY_FOLDER_STORE (folder))) {
1948 /* Do not move a parent into a child */
1950 } else if (TNY_IS_FOLDER_STORE (parent) &&
1951 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
1952 /* Check that the new folder name is not used by any
1955 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
1956 /* Check that the new folder name is not used by any
1957 special local folder */
1960 /* Create the helper */
1961 helper = g_slice_new0 (XFerFolderAsyncHelper);
1962 helper->mail_op = g_object_ref (self);
1963 helper->user_callback = user_callback;
1964 helper->user_data = user_data;
1966 /* Move/Copy folder */
1967 modest_mail_operation_notify_start (self);
1968 tny_folder_copy_async (folder,
1970 tny_folder_get_name (folder),
1973 transfer_folder_status_cb,
1979 /* Set status failed and set an error */
1980 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1981 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1982 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1985 /* Call the user callback if exists */
1987 user_callback (self, NULL, user_data);
1989 /* Notify the queue */
1990 modest_mail_operation_notify_end (self);
1994 modest_mail_operation_rename_folder (ModestMailOperation *self,
1997 XferFolderAsyncUserCallback user_callback,
2000 ModestMailOperationPrivate *priv;
2001 ModestTnyFolderRules rules;
2002 XFerFolderAsyncHelper *helper;
2004 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2005 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2006 g_return_if_fail (name);
2008 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2010 /* Get account and set it into mail_operation */
2011 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2012 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2014 /* Check folder rules */
2015 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2016 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2018 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2021 TnyFolderStore *into;
2023 into = tny_folder_get_folder_store (folder);
2025 /* Check that the new folder name is not used by any
2026 special local folder */
2027 if (new_name_valid_if_local_account (priv, into, name)) {
2028 /* Create the helper */
2029 helper = g_slice_new0 (XFerFolderAsyncHelper);
2030 helper->mail_op = g_object_ref(self);
2031 helper->user_callback = user_callback;
2032 helper->user_data = user_data;
2034 /* Rename. Camel handles folder subscription/unsubscription */
2035 modest_mail_operation_notify_start (self);
2036 tny_folder_copy_async (folder, into, name, TRUE,
2038 transfer_folder_status_cb,
2043 g_object_unref (into);
2048 /* Set status failed and set an error */
2049 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2050 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2051 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2052 _("FIXME: unable to rename"));
2055 user_callback (self, NULL, user_data);
2057 /* Notify about operation end */
2058 modest_mail_operation_notify_end (self);
2061 /* ******************************************************************* */
2062 /* ************************** MSG ACTIONS ************************* */
2063 /* ******************************************************************* */
2066 modest_mail_operation_get_msg (ModestMailOperation *self,
2068 GetMsgAsyncUserCallback user_callback,
2071 GetMsgInfo *helper = NULL;
2073 ModestMailOperationPrivate *priv;
2075 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2076 g_return_if_fail (TNY_IS_HEADER (header));
2078 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2079 folder = tny_header_get_folder (header);
2081 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2085 /* Get account and set it into mail_operation */
2086 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2088 /* Check for cached messages */
2089 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2090 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2092 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2094 /* Create the helper */
2095 helper = g_slice_new0 (GetMsgInfo);
2096 helper->header = g_object_ref (header);
2097 helper->mail_op = g_object_ref (self);
2098 helper->user_callback = user_callback;
2099 helper->user_data = user_data;
2100 helper->destroy_notify = NULL;
2101 helper->last_total_bytes = 0;
2102 helper->sum_total_bytes = 0;
2103 helper->total_bytes = tny_header_get_message_size (header);
2105 modest_mail_operation_notify_start (self);
2107 /* notify about the start of the operation */
2108 ModestMailOperationState *state;
2109 state = modest_mail_operation_clone_state (self);
2112 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2115 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2117 g_object_unref (G_OBJECT (folder));
2121 get_msg_status_cb (GObject *obj,
2125 GetMsgInfo *helper = NULL;
2127 g_return_if_fail (status != NULL);
2128 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2130 helper = (GetMsgInfo *) user_data;
2131 g_return_if_fail (helper != NULL);
2133 /* Notify progress */
2134 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2135 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2139 get_msg_async_cb (TnyFolder *folder,
2145 GetMsgInfo *info = NULL;
2146 ModestMailOperationPrivate *priv = NULL;
2149 info = (GetMsgInfo *) user_data;
2151 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2155 tny_iterator_next (info->iter);
2156 finished = (tny_iterator_is_done (info->iter));
2158 finished = (priv->done == priv->total) ? TRUE : FALSE;
2162 if (canceled || err) {
2163 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2165 priv->error = g_error_copy ((const GError *) err);
2166 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2169 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2170 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2173 } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
2174 /* Set the success status before calling the user callback */
2175 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2176 } else if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED) {
2182 /* Call the user callback */
2183 if (info->user_callback)
2184 info->user_callback (info->mail_op, info->header, canceled,
2185 msg, err, info->user_data);
2187 /* Notify about operation end if this is the last callback */
2189 /* Free user data */
2190 if (info->destroy_notify)
2191 info->destroy_notify (info->user_data);
2193 /* Notify about operation end */
2194 modest_mail_operation_notify_end (info->mail_op);
2198 g_object_unref (info->iter);
2199 if (info->header_list)
2200 g_object_unref (info->header_list);
2201 g_object_unref (info->header);
2202 g_object_unref (info->mail_op);
2203 g_slice_free (GetMsgInfo, info);
2204 } else if (info->iter) {
2205 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->iter));
2206 TnyFolder *folder = tny_header_get_folder (header);
2208 g_object_unref (info->header);
2209 info->header = g_object_ref (header);
2211 /* Retrieve the next message */
2212 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, info);
2214 g_object_unref (header);
2215 g_object_unref (folder);
2217 g_warning ("%s: finished != TRUE but no messages left", __FUNCTION__);
2222 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2223 TnyList *header_list,
2224 GetMsgAsyncUserCallback user_callback,
2226 GDestroyNotify notify)
2228 ModestMailOperationPrivate *priv = NULL;
2230 TnyIterator *iter = NULL;
2232 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2234 /* Init mail operation */
2235 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2236 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2237 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2239 priv->total = tny_list_get_length(header_list);
2241 /* Get account and set it into mail_operation */
2242 if (tny_list_get_length (header_list) >= 1) {
2243 iter = tny_list_create_iterator (header_list);
2244 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2246 TnyFolder *folder = tny_header_get_folder (header);
2248 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2249 g_object_unref (folder);
2251 g_object_unref (header);
2254 if (tny_list_get_length (header_list) == 1) {
2255 g_object_unref (iter);
2260 msg_list_size = compute_message_list_size (header_list);
2262 modest_mail_operation_notify_start (self);
2263 iter = tny_list_create_iterator (header_list);
2264 if (!tny_iterator_is_done (iter)) {
2265 /* notify about the start of the operation */
2266 ModestMailOperationState *state;
2267 state = modest_mail_operation_clone_state (self);
2270 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2273 GetMsgInfo *msg_info = NULL;
2274 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2275 TnyFolder *folder = tny_header_get_folder (header);
2277 /* Create the message info */
2278 msg_info = g_slice_new0 (GetMsgInfo);
2279 msg_info->mail_op = g_object_ref (self);
2280 msg_info->header = g_object_ref (header);
2281 msg_info->header_list = g_object_ref (header_list);
2282 msg_info->iter = g_object_ref (iter);
2283 msg_info->user_callback = user_callback;
2284 msg_info->user_data = user_data;
2285 msg_info->destroy_notify = notify;
2286 msg_info->last_total_bytes = 0;
2287 msg_info->sum_total_bytes = 0;
2288 msg_info->total_bytes = msg_list_size;
2290 /* The callback will call it per each header */
2291 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2293 /* Free and go on */
2294 g_object_unref (header);
2295 g_object_unref (folder);
2296 g_slice_free (ModestMailOperationState, state);
2298 g_object_unref (iter);
2303 modest_mail_operation_remove_msg (ModestMailOperation *self,
2305 gboolean remove_to_trash /*ignored*/)
2308 ModestMailOperationPrivate *priv;
2310 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2311 g_return_if_fail (TNY_IS_HEADER (header));
2313 if (remove_to_trash)
2314 g_warning ("remove to trash is not implemented");
2316 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2317 folder = tny_header_get_folder (header);
2319 /* Get account and set it into mail_operation */
2320 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2321 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2322 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2324 /* remove message from folder */
2325 tny_folder_remove_msg (folder, header, &(priv->error));
2327 gboolean expunge, leave_on_server;
2328 const gchar *account_name;
2329 TnyAccount *account;
2330 ModestTransportStoreProtocol account_proto;
2332 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2333 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2335 modest_mail_operation_notify_start (self);
2337 /* Get leave on server setting */
2338 account = tny_folder_get_account (folder);
2339 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2341 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2344 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2346 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2347 modest_tny_folder_is_remote_folder (folder) == FALSE)
2353 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2356 g_object_unref (account);
2362 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2364 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2367 g_object_unref (G_OBJECT (folder));
2369 /* Notify about operation end */
2370 modest_mail_operation_notify_end (self);
2374 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2376 gboolean remove_to_trash /*ignored*/)
2378 TnyFolder *folder = NULL;
2379 ModestMailOperationPrivate *priv;
2380 TnyIterator *iter = NULL;
2381 TnyHeader *header = NULL;
2382 TnyList *remove_headers = NULL;
2383 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2385 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2386 g_return_if_fail (TNY_IS_LIST (headers));
2388 if (remove_to_trash)
2389 g_warning ("remove to trash is not implemented");
2391 if (tny_list_get_length(headers) == 0) {
2392 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2393 goto cleanup; /* nothing to do */
2396 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2397 remove_headers = g_object_ref(headers);
2399 /* Get folder from first header and sync it */
2400 iter = tny_list_create_iterator (headers);
2401 header = TNY_HEADER (tny_iterator_get_current (iter));
2403 folder = tny_header_get_folder (header);
2404 if (!TNY_IS_FOLDER(folder)) {
2405 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2409 /* Don't remove messages that are being sent */
2410 if (modest_tny_folder_is_local_folder (folder)) {
2411 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2413 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2414 TnyTransportAccount *traccount = NULL;
2415 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2416 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2418 ModestTnySendQueueStatus status;
2419 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2420 TnyIterator *iter = tny_list_create_iterator(headers);
2421 g_object_unref(remove_headers);
2422 remove_headers = TNY_LIST(tny_simple_list_new());
2423 while (!tny_iterator_is_done(iter)) {
2425 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2426 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2427 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2428 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2429 tny_list_append(remove_headers, G_OBJECT(hdr));
2431 g_object_unref(hdr);
2433 tny_iterator_next(iter);
2435 g_object_unref(iter);
2436 g_object_unref(traccount);
2440 /* Get account and set it into mail_operation */
2441 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2442 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2443 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2445 /* remove message from folder */
2446 modest_mail_operation_notify_start (self);
2448 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2450 gboolean expunge, leave_on_server;
2451 const gchar *account_name;
2453 TnyAccount *account;
2454 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2456 account = tny_folder_get_account (folder);
2457 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2459 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2462 proto = tny_account_get_proto (account);
2464 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2467 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2468 modest_tny_folder_is_remote_folder (folder) == FALSE)
2474 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2476 g_object_unref (account);
2482 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2484 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2489 g_object_unref (remove_headers);
2491 g_object_unref (header);
2493 g_object_unref (iter);
2495 g_object_unref (folder);
2497 /* Notify about operation end */
2498 modest_mail_operation_notify_end (self);
2502 notify_progress_of_multiple_messages (ModestMailOperation *self,
2504 gint *last_total_bytes,
2505 gint *sum_total_bytes,
2507 gboolean increment_done)
2509 ModestMailOperationPrivate *priv;
2510 ModestMailOperationState *state;
2511 gboolean is_num_bytes = FALSE;
2513 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2515 /* We know that tinymail sends us information about
2516 * transferred bytes with this particular message
2518 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2519 * I just added the 'if' so we don't get runtime warning)
2521 if (status->message)
2522 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2524 state = modest_mail_operation_clone_state (self);
2525 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2526 /* We know that we're in a different message when the
2527 total number of bytes to transfer is different. Of
2528 course it could fail if we're transferring messages
2529 of the same size, but this is a workarround */
2530 if (status->of_total != *last_total_bytes) {
2531 /* We need to increment the done when there is
2532 no information about each individual
2533 message, we need to do this in message
2534 transfers, and we don't do it for getting
2538 *sum_total_bytes += *last_total_bytes;
2539 *last_total_bytes = status->of_total;
2541 state->bytes_done += status->position + *sum_total_bytes;
2542 state->bytes_total = total_bytes;
2544 /* Notify the status change. Only notify about changes
2545 referred to bytes */
2546 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2550 g_slice_free (ModestMailOperationState, state);
2554 transfer_msgs_status_cb (GObject *obj,
2558 XFerMsgsAsyncHelper *helper;
2560 g_return_if_fail (status != NULL);
2561 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2563 helper = (XFerMsgsAsyncHelper *) user_data;
2564 g_return_if_fail (helper != NULL);
2566 /* Notify progress */
2567 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2568 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2573 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2575 XFerMsgsAsyncHelper *helper;
2576 ModestMailOperation *self;
2577 ModestMailOperationPrivate *priv;
2578 TnyIterator *iter = NULL;
2579 TnyHeader *header = NULL;
2581 helper = (XFerMsgsAsyncHelper *) user_data;
2582 self = helper->mail_op;
2584 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2587 priv->error = g_error_copy (err);
2589 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2590 } else if (cancelled) {
2591 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2592 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2593 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2594 _("Error trying to refresh the contents of %s"),
2595 tny_folder_get_name (folder));
2598 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2600 /* Update folder counts */
2601 tny_folder_poke_status (folder);
2602 tny_folder_poke_status (helper->dest_folder);
2606 /* Mark headers as deleted and seen */
2607 if ((helper->delete) &&
2608 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2609 iter = tny_list_create_iterator (helper->headers);
2610 while (!tny_iterator_is_done (iter)) {
2611 header = TNY_HEADER (tny_iterator_get_current (iter));
2612 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2613 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2614 g_object_unref (header);
2616 tny_iterator_next (iter);
2621 /* Notify about operation end */
2622 modest_mail_operation_notify_end (self);
2624 /* If user defined callback function was defined, call it */
2625 if (helper->user_callback) {
2626 /* This is not a GDK lock because we are a Tinymail callback and
2627 * Tinymail already acquires the Gdk lock */
2629 /* no gdk_threads_enter (), CHECKED */
2630 helper->user_callback (self, helper->user_data);
2631 /* no gdk_threads_leave (), CHECKED */
2635 if (helper->headers)
2636 g_object_unref (helper->headers);
2637 if (helper->dest_folder)
2638 g_object_unref (helper->dest_folder);
2639 if (helper->mail_op)
2640 g_object_unref (helper->mail_op);
2642 g_object_unref (folder);
2644 g_object_unref (iter);
2645 g_slice_free (XFerMsgsAsyncHelper, helper);
2649 compute_message_list_size (TnyList *headers)
2654 iter = tny_list_create_iterator (headers);
2655 while (!tny_iterator_is_done (iter)) {
2656 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2657 size += tny_header_get_message_size (header);
2658 g_object_unref (header);
2659 tny_iterator_next (iter);
2661 g_object_unref (iter);
2667 compute_message_array_size (GPtrArray *headers)
2672 for (i = 0; i < headers->len; i++) {
2673 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2674 size += tny_header_get_message_size (header);
2682 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2685 gboolean delete_original,
2686 XferMsgsAsyncUserCallback user_callback,
2689 ModestMailOperationPrivate *priv = NULL;
2690 TnyIterator *iter = NULL;
2691 TnyFolder *src_folder = NULL;
2692 XFerMsgsAsyncHelper *helper = NULL;
2693 TnyHeader *header = NULL;
2694 ModestTnyFolderRules rules = 0;
2696 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2697 g_return_if_fail (headers && TNY_IS_LIST (headers));
2698 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2700 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2701 priv->total = tny_list_get_length (headers);
2703 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2704 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2706 /* Apply folder rules */
2707 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2708 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2709 /* Set status failed and set an error */
2710 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2711 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2712 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2713 _CS("ckct_ib_unable_to_paste_here"));
2714 /* Notify the queue */
2715 modest_mail_operation_notify_end (self);
2719 /* Get source folder */
2720 iter = tny_list_create_iterator (headers);
2721 header = TNY_HEADER (tny_iterator_get_current (iter));
2723 src_folder = tny_header_get_folder (header);
2724 g_object_unref (header);
2726 g_object_unref (iter);
2728 if (src_folder == NULL) {
2729 /* Notify the queue */
2730 modest_mail_operation_notify_end (self);
2732 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2737 /* Check folder source and destination */
2738 if (src_folder == folder) {
2739 /* Set status failed and set an error */
2740 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2741 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2742 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2743 _("mail_in_ui_folder_copy_target_error"));
2745 /* Notify the queue */
2746 modest_mail_operation_notify_end (self);
2749 g_object_unref (src_folder);
2753 /* Create the helper */
2754 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2755 helper->mail_op = g_object_ref(self);
2756 helper->dest_folder = g_object_ref(folder);
2757 helper->headers = g_object_ref(headers);
2758 helper->user_callback = user_callback;
2759 helper->user_data = user_data;
2760 helper->delete = delete_original;
2761 helper->last_total_bytes = 0;
2762 helper->sum_total_bytes = 0;
2763 helper->total_bytes = compute_message_list_size (headers);
2765 /* Get account and set it into mail_operation */
2766 priv->account = modest_tny_folder_get_account (src_folder);
2768 /* Transfer messages */
2769 modest_mail_operation_notify_start (self);
2770 tny_folder_transfer_msgs_async (src_folder,
2775 transfer_msgs_status_cb,
2781 on_refresh_folder (TnyFolder *folder,
2786 RefreshAsyncHelper *helper = NULL;
2787 ModestMailOperation *self = NULL;
2788 ModestMailOperationPrivate *priv = NULL;
2790 helper = (RefreshAsyncHelper *) user_data;
2791 self = helper->mail_op;
2792 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2794 g_return_if_fail(priv!=NULL);
2797 priv->error = g_error_copy (error);
2798 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2803 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2804 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2805 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2806 _("Error trying to refresh the contents of %s"),
2807 tny_folder_get_name (folder));
2811 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2814 /* Call user defined callback, if it exists */
2815 if (helper->user_callback) {
2817 /* This is not a GDK lock because we are a Tinymail callback and
2818 * Tinymail already acquires the Gdk lock */
2819 helper->user_callback (self, folder, helper->user_data);
2823 g_slice_free (RefreshAsyncHelper, helper);
2825 /* Notify about operation end */
2826 modest_mail_operation_notify_end (self);
2827 g_object_unref(self);
2831 on_refresh_folder_status_update (GObject *obj,
2835 RefreshAsyncHelper *helper = NULL;
2836 ModestMailOperation *self = NULL;
2837 ModestMailOperationPrivate *priv = NULL;
2838 ModestMailOperationState *state;
2840 g_return_if_fail (user_data != NULL);
2841 g_return_if_fail (status != NULL);
2842 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2844 helper = (RefreshAsyncHelper *) user_data;
2845 self = helper->mail_op;
2846 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2848 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2850 priv->done = status->position;
2851 priv->total = status->of_total;
2853 state = modest_mail_operation_clone_state (self);
2855 /* This is not a GDK lock because we are a Tinymail callback and
2856 * Tinymail already acquires the Gdk lock */
2857 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2859 g_slice_free (ModestMailOperationState, state);
2863 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2865 RefreshAsyncUserCallback user_callback,
2868 ModestMailOperationPrivate *priv = NULL;
2869 RefreshAsyncHelper *helper = NULL;
2871 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2873 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2875 /* Get account and set it into mail_operation */
2876 priv->account = modest_tny_folder_get_account (folder);
2877 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2879 /* Create the helper */
2880 helper = g_slice_new0 (RefreshAsyncHelper);
2881 helper->mail_op = g_object_ref(self);
2882 helper->user_callback = user_callback;
2883 helper->user_data = user_data;
2885 /* Refresh the folder. TODO: tinymail could issue a status
2886 updates before the callback call then this could happen. We
2887 must review the design */
2888 modest_mail_operation_notify_start (self);
2890 /* notify that the operation was started */
2891 ModestMailOperationState *state;
2892 state = modest_mail_operation_clone_state (self);
2895 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2898 tny_folder_refresh_async (folder,
2900 on_refresh_folder_status_update,
2905 run_queue_stop (ModestTnySendQueue *queue,
2906 ModestMailOperation *self)
2908 ModestMailOperationPrivate *priv;
2910 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2911 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2912 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2914 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2916 modest_mail_operation_notify_end (self);
2917 g_signal_handlers_disconnect_by_func (queue, run_queue_stop, self);
2918 g_object_unref (self);
2921 modest_mail_operation_run_queue (ModestMailOperation *self,
2922 ModestTnySendQueue *queue)
2924 ModestMailOperationPrivate *priv;
2926 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2927 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2928 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2930 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2931 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
2932 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
2934 modest_mail_operation_notify_start (self);
2935 g_object_ref (self);
2936 g_signal_connect ((gpointer) queue, "queue-stop", G_CALLBACK (run_queue_stop), (gpointer) self);
2940 sync_folder_finish_callback (TnyFolder *self, gboolean cancelled, GError *err, ModestMailOperation *mail_op)
2942 ModestMailOperationPrivate *priv;
2944 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
2946 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2947 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2949 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2951 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2953 modest_mail_operation_notify_end (mail_op);
2954 g_object_unref (mail_op);
2958 modest_mail_operation_sync_folder (ModestMailOperation *self,
2959 TnyFolder *folder, gboolean expunge)
2961 ModestMailOperationPrivate *priv;
2963 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2964 g_return_if_fail (TNY_IS_FOLDER (folder));
2965 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2967 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2968 priv->account = TNY_ACCOUNT (tny_folder_get_account (folder));
2969 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
2971 modest_mail_operation_notify_start (self);
2972 g_object_ref (self);
2973 tny_folder_sync_async (folder, expunge, (TnyFolderCallback) sync_folder_finish_callback, NULL, self);
2977 modest_mail_operation_notify_start (ModestMailOperation *self)
2979 ModestMailOperationPrivate *priv = NULL;
2981 g_return_if_fail (self);
2983 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2985 /* Ensure that all the fields are filled correctly */
2986 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
2988 /* Notify the observers about the mail operation. We do not
2989 wrapp this emission because we assume that this function is
2990 always called from within the main lock */
2991 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
2996 * It's used by the mail operation queue to notify the observers
2997 * attached to that signal that the operation finished. We need to use
2998 * that because tinymail does not give us the progress of a given
2999 * operation when it finishes (it directly calls the operation
3003 modest_mail_operation_notify_end (ModestMailOperation *self)
3005 ModestMailOperationPrivate *priv = NULL;
3007 g_return_if_fail (self);
3009 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3011 /* Notify the observers about the mail operation end. We do
3012 not wrapp this emission because we assume that this
3013 function is always called from within the main lock */
3014 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3016 /* Remove the error user data */
3017 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3018 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3022 modest_mail_operation_get_account (ModestMailOperation *self)
3024 ModestMailOperationPrivate *priv = NULL;
3026 g_return_val_if_fail (self, NULL);
3028 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3030 return (priv->account) ? g_object_ref (priv->account) : NULL;
3034 modest_mail_operation_noop (ModestMailOperation *self)
3036 ModestMailOperationPrivate *priv = NULL;
3038 g_return_if_fail (self);
3040 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3041 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3042 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3046 /* This mail operation does nothing actually */
3047 modest_mail_operation_notify_start (self);
3048 modest_mail_operation_notify_end (self);
3053 modest_mail_operation_to_string (ModestMailOperation *self)
3055 const gchar *type, *status, *account_id;
3056 ModestMailOperationPrivate *priv = NULL;
3058 g_return_val_if_fail (self, NULL);
3060 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3062 /* new operations don't have anything interesting */
3063 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3064 return g_strdup_printf ("%p <new operation>", self);
3066 switch (priv->op_type) {
3067 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3068 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3069 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3070 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3071 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3072 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3073 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3074 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3075 default: type = "UNEXPECTED"; break;
3078 switch (priv->status) {
3079 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3080 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3081 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3082 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3083 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3084 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3085 default: status= "UNEXPECTED"; break;
3088 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3090 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3091 priv->done, priv->total,
3092 priv->error && priv->error->message ? priv->error->message : "");