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);
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 CreateMsgInfo *info = NULL;
746 info = g_slice_new0 (CreateMsgInfo);
747 info->mail_op = g_object_ref (self);
749 info->from = g_strdup (from);
750 info->to = g_strdup (to);
751 info->cc = g_strdup (cc);
752 info->bcc = g_strdup (bcc);
753 info->subject = g_strdup (subject);
754 info->plain_body = g_strdup (plain_body);
755 info->html_body = g_strdup (html_body);
756 info->attachments_list = g_list_copy ((GList *) attachments_list);
757 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
758 info->images_list = g_list_copy ((GList *) images_list);
759 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
760 info->priority_flags = priority_flags;
762 info->callback = callback;
763 info->userdata = userdata;
765 g_thread_create (create_msg_thread, info, FALSE, NULL);
770 TnyTransportAccount *transport_account;
775 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
779 ModestMailOperationPrivate *priv = NULL;
780 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
781 TnyFolder *draft_folder = NULL;
782 TnyFolder *outbox_folder = NULL;
783 TnyHeader *header = NULL;
790 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
793 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
794 modest_mail_operation_notify_end (self);
798 /* Call mail operation */
799 modest_mail_operation_send_mail (self, info->transport_account, msg);
801 if (info->draft_msg != NULL) {
802 TnyFolder *folder = NULL;
803 TnyFolder *src_folder = NULL;
804 TnyFolderType folder_type;
805 TnyTransportAccount *transport_account = NULL;
807 /* To remove the old mail from its source folder, we need to get the
808 * transport account of the original draft message (the transport account
809 * might have been changed by the user) */
810 header = tny_msg_get_header (info->draft_msg);
811 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
812 modest_runtime_get_account_store(), header);
813 if (transport_account == NULL)
814 transport_account = g_object_ref(info->transport_account);
815 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
816 TNY_FOLDER_TYPE_DRAFTS);
817 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
818 TNY_FOLDER_TYPE_OUTBOX);
819 g_object_unref(transport_account);
822 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
826 if (!outbox_folder) {
827 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
832 folder = tny_msg_get_folder (info->draft_msg);
833 if (folder == NULL) goto end;
834 folder_type = modest_tny_folder_guess_folder_type (folder);
836 if (folder_type == TNY_FOLDER_TYPE_INVALID)
837 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
839 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
840 src_folder = outbox_folder;
842 src_folder = draft_folder;
844 /* Note: This can fail (with a warning) if the message is not really already in a folder,
845 * because this function requires it to have a UID. */
846 tny_folder_remove_msg (src_folder, header, NULL);
848 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
849 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
851 g_object_unref (folder);
856 g_object_unref (header);
860 g_object_unref (info->draft_msg);
862 g_object_unref (draft_folder);
864 g_object_unref (outbox_folder);
865 if (info->transport_account)
866 g_object_unref (info->transport_account);
867 g_slice_free (SendNewMailInfo, info);
871 modest_mail_operation_send_new_mail (ModestMailOperation *self,
872 TnyTransportAccount *transport_account,
874 const gchar *from, const gchar *to,
875 const gchar *cc, const gchar *bcc,
876 const gchar *subject, const gchar *plain_body,
877 const gchar *html_body,
878 const GList *attachments_list,
879 const GList *images_list,
880 TnyHeaderFlags priority_flags)
882 ModestMailOperationPrivate *priv = NULL;
883 SendNewMailInfo *info;
885 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
886 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
888 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
889 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
890 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
891 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
893 /* Check parametters */
895 /* Set status failed and set an error */
896 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
897 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
898 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
899 _("Error trying to send a mail. You need to set at least one recipient"));
902 info = g_slice_new0 (SendNewMailInfo);
903 info->transport_account = transport_account;
904 if (transport_account)
905 g_object_ref (transport_account);
906 info->draft_msg = draft_msg;
908 g_object_ref (draft_msg);
911 modest_mail_operation_notify_start (self);
912 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
913 attachments_list, images_list, priority_flags,
914 modest_mail_operation_send_new_mail_cb, info);
920 TnyTransportAccount *transport_account;
922 SaveToDraftstCallback callback;
926 ModestMailOperation *mailop;
927 } SaveToDraftsAddMsgInfo;
930 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
935 ModestMailOperationPrivate *priv = NULL;
936 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
938 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
941 g_warning ("%s: priv->error != NULL", __FUNCTION__);
942 g_error_free(priv->error);
945 priv->error = (err == NULL) ? NULL : g_error_copy(err);
947 if ((!priv->error) && (info->draft_msg != NULL)) {
948 TnyHeader *header = tny_msg_get_header (info->draft_msg);
949 TnyFolder *src_folder = tny_header_get_folder (header);
951 /* Remove the old draft */
952 tny_folder_remove_msg (src_folder, header, NULL);
954 /* Synchronize to expunge and to update the msg counts */
955 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
956 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
958 g_object_unref (G_OBJECT(header));
959 g_object_unref (G_OBJECT(src_folder));
963 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
965 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
967 /* Call the user callback */
969 info->callback (info->mailop, info->msg, info->user_data);
971 if (info->transport_account)
972 g_object_unref (G_OBJECT(info->transport_account));
974 g_object_unref (G_OBJECT (info->draft_msg));
976 g_object_unref (G_OBJECT(info->drafts));
978 g_object_unref (G_OBJECT (info->msg));
980 modest_mail_operation_notify_end (info->mailop);
981 g_object_unref(info->mailop);
982 g_slice_free (SaveToDraftsAddMsgInfo, info);
987 TnyTransportAccount *transport_account;
989 SaveToDraftstCallback callback;
994 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
998 TnyFolder *drafts = NULL;
999 ModestMailOperationPrivate *priv = NULL;
1000 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1002 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1005 if (!(priv->error)) {
1006 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1007 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1008 "modest: failed to create a new msg\n");
1011 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1012 TNY_FOLDER_TYPE_DRAFTS);
1013 if (!drafts && !(priv->error)) {
1014 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1015 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1016 "modest: failed to create a new msg\n");
1021 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1022 cb_info->transport_account = g_object_ref(info->transport_account);
1023 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1024 cb_info->callback = info->callback;
1025 cb_info->user_data = info->user_data;
1026 cb_info->drafts = g_object_ref(drafts);
1027 cb_info->msg = g_object_ref(msg);
1028 cb_info->mailop = g_object_ref(self);
1029 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1032 /* Call the user callback */
1033 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1035 info->callback (self, msg, info->user_data);
1036 modest_mail_operation_notify_end (self);
1040 g_object_unref (G_OBJECT(drafts));
1041 if (info->draft_msg)
1042 g_object_unref (G_OBJECT (info->draft_msg));
1043 if (info->transport_account)
1044 g_object_unref (G_OBJECT(info->transport_account));
1045 g_slice_free (SaveToDraftsInfo, info);
1049 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1050 TnyTransportAccount *transport_account,
1052 const gchar *from, const gchar *to,
1053 const gchar *cc, const gchar *bcc,
1054 const gchar *subject, const gchar *plain_body,
1055 const gchar *html_body,
1056 const GList *attachments_list,
1057 const GList *images_list,
1058 TnyHeaderFlags priority_flags,
1059 SaveToDraftstCallback callback,
1062 ModestMailOperationPrivate *priv = NULL;
1063 SaveToDraftsInfo *info = NULL;
1065 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1066 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1068 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1070 /* Get account and set it into mail_operation */
1071 priv->account = g_object_ref (transport_account);
1072 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1074 info = g_slice_new0 (SaveToDraftsInfo);
1075 info->transport_account = g_object_ref (transport_account);
1076 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1077 info->callback = callback;
1078 info->user_data = user_data;
1080 modest_mail_operation_notify_start (self);
1081 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1082 attachments_list, images_list, priority_flags,
1083 modest_mail_operation_save_to_drafts_cb, info);
1088 ModestMailOperation *mail_op;
1089 TnyMimePart *mime_part;
1091 GetMimePartSizeCallback callback;
1093 } GetMimePartSizeInfo;
1095 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1096 /* We use this folder observer to track the headers that have been
1097 * added to a folder */
1100 TnyList *new_headers;
1101 } InternalFolderObserver;
1104 GObjectClass parent;
1105 } InternalFolderObserverClass;
1107 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1109 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1110 internal_folder_observer,
1112 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1116 foreach_add_item (gpointer header, gpointer user_data)
1118 tny_list_prepend (TNY_LIST (user_data),
1119 g_object_ref (G_OBJECT (header)));
1122 /* This is the method that looks for new messages in a folder */
1124 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1126 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1128 TnyFolderChangeChanged changed;
1130 changed = tny_folder_change_get_changed (change);
1132 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1135 /* Get added headers */
1136 list = tny_simple_list_new ();
1137 tny_folder_change_get_added_headers (change, list);
1139 /* Add them to the folder observer */
1140 tny_list_foreach (list, foreach_add_item,
1141 derived->new_headers);
1143 g_object_unref (G_OBJECT (list));
1148 internal_folder_observer_init (InternalFolderObserver *self)
1150 self->new_headers = tny_simple_list_new ();
1153 internal_folder_observer_finalize (GObject *object)
1155 InternalFolderObserver *self;
1157 self = (InternalFolderObserver *) object;
1158 g_object_unref (self->new_headers);
1160 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1163 tny_folder_observer_init (TnyFolderObserverIface *iface)
1165 iface->update = internal_folder_observer_update;
1168 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1170 GObjectClass *object_class;
1172 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1173 object_class = (GObjectClass*) klass;
1174 object_class->finalize = internal_folder_observer_finalize;
1179 ModestMailOperation *mail_op;
1180 gchar *account_name;
1181 UpdateAccountCallback callback;
1186 TnyFolderObserver *inbox_observer;
1187 RetrieveAllCallback retrieve_all_cb;
1188 } UpdateAccountInfo;
1192 destroy_update_account_info (UpdateAccountInfo *info)
1194 g_free (info->account_name);
1195 g_object_unref (info->folders);
1196 g_object_unref (info->mail_op);
1197 g_slice_free (UpdateAccountInfo, info);
1201 update_account_get_msg_async_cb (TnyFolder *folder,
1207 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1209 /* Just delete the helper. Don't do anything with the new
1210 msg. There is also no need to check for errors */
1211 g_object_unref (msg_info->mail_op);
1212 g_object_unref (msg_info->header);
1213 g_slice_free (GetMsgInfo, msg_info);
1217 inbox_refreshed_cb (TnyFolder *inbox,
1222 UpdateAccountInfo *info;
1223 ModestMailOperationPrivate *priv;
1224 TnyIterator *new_headers_iter;
1225 GPtrArray *new_headers_array = NULL;
1226 gint max_size, retrieve_limit, i;
1227 ModestAccountMgr *mgr;
1228 ModestAccountRetrieveType retrieve_type;
1229 TnyList *new_headers = NULL;
1230 gboolean headers_only, ignore_limit;
1231 TnyTransportAccount *transport_account;
1233 info = (UpdateAccountInfo *) user_data;
1234 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1235 mgr = modest_runtime_get_account_mgr ();
1237 if (canceled || err || !inbox) {
1238 /* Try to send anyway */
1242 /* Get the message max size */
1243 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1244 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1246 max_size = G_MAXINT;
1248 max_size = max_size * KB;
1250 /* Create the new headers array. We need it to sort the
1251 new headers by date */
1252 new_headers_array = g_ptr_array_new ();
1253 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1254 while (!tny_iterator_is_done (new_headers_iter)) {
1255 TnyHeader *header = NULL;
1257 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1258 /* Apply per-message size limits */
1259 if (tny_header_get_message_size (header) < max_size)
1260 g_ptr_array_add (new_headers_array, g_object_ref (header));
1262 g_object_unref (header);
1263 tny_iterator_next (new_headers_iter);
1265 g_object_unref (new_headers_iter);
1266 tny_folder_remove_observer (inbox, info->inbox_observer);
1267 g_object_unref (info->inbox_observer);
1268 info->inbox_observer = NULL;
1270 /* Update the last updated key, even if we don't have to get new headers */
1271 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1273 if (new_headers_array->len == 0)
1276 /* Get per-account message amount retrieval limit */
1277 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1278 if (retrieve_limit == 0)
1279 retrieve_limit = G_MAXINT;
1281 /* Get per-account retrieval type */
1282 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1283 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1286 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1288 /* Ask the users if they want to retrieve all the messages
1289 even though the limit was exceeded */
1290 ignore_limit = FALSE;
1291 if (new_headers_array->len > retrieve_limit) {
1292 /* Ask the user if a callback has been specified and
1293 if the mail operation has a source (this means that
1294 was invoked by the user and not automatically by a
1296 if (info->retrieve_all_cb && priv->source)
1297 ignore_limit = info->retrieve_all_cb (priv->source,
1298 new_headers_array->len,
1302 if (!headers_only) {
1304 const gint msg_list_size = compute_message_array_size (new_headers_array);
1308 priv->total = new_headers_array->len;
1310 priv->total = MIN (new_headers_array->len, retrieve_limit);
1311 while (msg_num < priv->total) {
1312 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1313 TnyFolder *folder = tny_header_get_folder (header);
1314 GetMsgInfo *msg_info;
1316 /* Create the message info */
1317 msg_info = g_slice_new0 (GetMsgInfo);
1318 msg_info->mail_op = g_object_ref (info->mail_op);
1319 msg_info->header = g_object_ref (header);
1320 msg_info->total_bytes = msg_list_size;
1322 /* Get message in an async way */
1323 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1324 get_msg_status_cb, msg_info);
1326 g_object_unref (folder);
1332 /* Copy the headers to a list and free the array */
1333 new_headers = tny_simple_list_new ();
1334 for (i=0; i < new_headers_array->len; i++) {
1335 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1336 tny_list_append (new_headers, G_OBJECT (header));
1338 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1339 g_ptr_array_free (new_headers_array, FALSE);
1342 /* Get the transport account */
1343 transport_account = (TnyTransportAccount *)
1344 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1345 info->account_name);
1347 if (transport_account) {
1348 ModestTnySendQueue *send_queue;
1352 send_queue = modest_runtime_get_send_queue (transport_account);
1354 /* Get outbox folder */
1355 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1356 if (outbox) { /* this could fail in some cases */
1357 num_messages = tny_folder_get_all_count (outbox);
1358 g_object_unref (outbox);
1360 g_warning ("%s: could not get outbox", __FUNCTION__);
1364 if (num_messages != 0) {
1366 g_object_unref (priv->account);
1368 /* Reenable suspended items */
1369 modest_tny_send_queue_wakeup (MODEST_TNY_SEND_QUEUE (send_queue));
1372 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (send_queue));
1376 /* Check if the operation was a success */
1378 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1380 /* Set the account back to not busy */
1381 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1383 /* Call the user callback */
1385 info->callback (info->mail_op, new_headers, info->user_data);
1387 /* Notify about operation end */
1388 modest_mail_operation_notify_end (info->mail_op);
1392 g_object_unref (new_headers);
1393 destroy_update_account_info (info);
1397 recurse_folders_async_cb (TnyFolderStore *folder_store,
1403 UpdateAccountInfo *info;
1404 ModestMailOperationPrivate *priv;
1406 info = (UpdateAccountInfo *) user_data;
1407 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1409 if (err || canceled) {
1410 /* Try to continue anyway */
1412 TnyIterator *iter = tny_list_create_iterator (list);
1413 while (!tny_iterator_is_done (iter)) {
1414 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1415 TnyList *folders = tny_simple_list_new ();
1417 /* Add to the list of all folders */
1418 tny_list_append (info->folders, (GObject *) folder);
1420 /* Add pending call */
1421 info->pending_calls++;
1423 tny_folder_store_get_folders_async (folder, folders, NULL,
1424 recurse_folders_async_cb,
1427 g_object_unref (G_OBJECT (folder));
1429 tny_iterator_next (iter);
1431 g_object_unref (G_OBJECT (iter));
1432 g_object_unref (G_OBJECT (list));
1435 /* Remove my own pending call */
1436 info->pending_calls--;
1438 /* This means that we have all the folders */
1439 if (info->pending_calls == 0) {
1440 TnyIterator *iter_all_folders;
1441 TnyFolder *inbox = NULL;
1443 iter_all_folders = tny_list_create_iterator (info->folders);
1445 /* Do a poke status over all folders */
1446 while (!tny_iterator_is_done (iter_all_folders) &&
1447 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1448 TnyFolder *folder = NULL;
1450 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1452 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1453 /* Get a reference to the INBOX */
1454 inbox = g_object_ref (folder);
1456 /* Issue a poke status over the folder */
1458 tny_folder_poke_status (folder);
1461 /* Free and go to next */
1462 g_object_unref (folder);
1463 tny_iterator_next (iter_all_folders);
1465 g_object_unref (iter_all_folders);
1467 /* Refresh the INBOX */
1469 /* Refresh the folder. Our observer receives
1470 * the new emails during folder refreshes, so
1471 * we can use observer->new_headers
1473 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1474 tny_folder_add_observer (inbox, info->inbox_observer);
1476 /* Refresh the INBOX */
1477 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1478 g_object_unref (inbox);
1480 /* We could not perform the inbox refresh but
1481 we'll try to send mails anyway */
1482 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1488 modest_mail_operation_update_account (ModestMailOperation *self,
1489 const gchar *account_name,
1491 RetrieveAllCallback retrieve_all_cb,
1492 UpdateAccountCallback callback,
1495 UpdateAccountInfo *info = NULL;
1496 ModestMailOperationPrivate *priv = NULL;
1497 ModestTnyAccountStore *account_store = NULL;
1498 TnyStoreAccount *store_account = NULL;
1500 ModestMailOperationState *state;
1502 /* Init mail operation */
1503 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1506 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1507 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1509 /* Get the store account */
1510 account_store = modest_runtime_get_account_store ();
1511 store_account = (TnyStoreAccount *)
1512 modest_tny_account_store_get_server_account (account_store,
1514 TNY_ACCOUNT_TYPE_STORE);
1515 priv->account = g_object_ref (store_account);
1517 /* Create the helper object */
1518 info = g_slice_new0 (UpdateAccountInfo);
1519 info->pending_calls = 1;
1520 info->folders = tny_simple_list_new ();
1521 info->mail_op = g_object_ref (self);
1522 info->poke_all = poke_all;
1523 info->account_name = g_strdup (account_name);
1524 info->callback = callback;
1525 info->user_data = user_data;
1526 info->retrieve_all_cb = retrieve_all_cb;
1528 /* Set account busy */
1529 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1530 modest_mail_operation_notify_start (self);
1532 /* notify about the start of the operation */
1533 state = modest_mail_operation_clone_state (self);
1537 /* Start notifying progress */
1538 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1539 g_slice_free (ModestMailOperationState, state);
1541 /* Get all folders and continue in the callback */
1542 folders = tny_simple_list_new ();
1543 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1545 recurse_folders_async_cb,
1550 * Used to notify the queue from the main
1551 * loop. We call it inside an idle call to achieve that
1554 idle_notify_queue (gpointer data)
1556 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1558 gdk_threads_enter ();
1559 modest_mail_operation_notify_end (mail_op);
1560 gdk_threads_leave ();
1561 g_object_unref (mail_op);
1567 compare_headers_by_date (gconstpointer a,
1570 TnyHeader **header1, **header2;
1571 time_t sent1, sent2;
1573 header1 = (TnyHeader **) a;
1574 header2 = (TnyHeader **) b;
1576 sent1 = tny_header_get_date_sent (*header1);
1577 sent2 = tny_header_get_date_sent (*header2);
1579 /* We want the most recent ones (greater time_t) at the
1588 /* ******************************************************************* */
1589 /* ************************** STORE ACTIONS ************************* */
1590 /* ******************************************************************* */
1593 ModestMailOperation *mail_op;
1594 CreateFolderUserCallback callback;
1600 create_folder_cb (TnyFolderStore *parent_folder,
1602 TnyFolder *new_folder,
1606 ModestMailOperationPrivate *priv;
1607 CreateFolderInfo *info;
1609 info = (CreateFolderInfo *) user_data;
1610 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1612 if (canceled || err) {
1613 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1615 priv->error = g_error_copy (err);
1617 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1618 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1621 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1624 /* The user will unref the new_folder */
1626 info->callback (info->mail_op, parent_folder,
1627 new_folder, info->user_data);
1629 /* Notify about operation end */
1630 modest_mail_operation_notify_end (info->mail_op);
1633 g_object_unref (info->mail_op);
1634 g_slice_free (CreateFolderInfo, info);
1638 modest_mail_operation_create_folder (ModestMailOperation *self,
1639 TnyFolderStore *parent,
1641 CreateFolderUserCallback callback,
1644 ModestMailOperationPrivate *priv;
1646 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1647 g_return_if_fail (name);
1649 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1650 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1651 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1652 g_object_ref (parent) :
1653 modest_tny_folder_get_account (TNY_FOLDER (parent));
1655 /* Check for already existing folder */
1656 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1657 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1658 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1659 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1660 _CS("ckdg_ib_folder_already_exists"));
1664 if (TNY_IS_FOLDER (parent)) {
1665 /* Check folder rules */
1666 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1667 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1668 /* Set status failed and set an error */
1669 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1670 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1671 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1672 _("mail_in_ui_folder_create_error"));
1676 if (!strcmp (name, " ") || strchr (name, '/')) {
1677 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1678 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1679 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1680 _("mail_in_ui_folder_create_error"));
1684 CreateFolderInfo *info;
1686 info = g_slice_new0 (CreateFolderInfo);
1687 info->mail_op = g_object_ref (self);
1688 info->callback = callback;
1689 info->user_data = user_data;
1691 modest_mail_operation_notify_start (self);
1693 /* Create the folder */
1694 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1697 /* Call the user callback anyway */
1699 callback (self, parent, NULL, user_data);
1700 /* Notify about operation end */
1701 modest_mail_operation_notify_end (self);
1706 modest_mail_operation_remove_folder (ModestMailOperation *self,
1708 gboolean remove_to_trash)
1710 TnyAccount *account;
1711 ModestMailOperationPrivate *priv;
1712 ModestTnyFolderRules rules;
1714 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1715 g_return_if_fail (TNY_IS_FOLDER (folder));
1717 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1719 /* Check folder rules */
1720 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1721 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1722 /* Set status failed and set an error */
1723 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1724 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1725 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1726 _("mail_in_ui_folder_delete_error"));
1730 /* Get the account */
1731 account = modest_tny_folder_get_account (folder);
1732 priv->account = g_object_ref(account);
1733 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1735 /* Delete folder or move to trash */
1736 if (remove_to_trash) {
1737 TnyFolder *trash_folder = NULL;
1738 trash_folder = modest_tny_account_get_special_folder (account,
1739 TNY_FOLDER_TYPE_TRASH);
1740 /* TODO: error_handling */
1742 modest_mail_operation_notify_start (self);
1743 modest_mail_operation_xfer_folder (self, folder,
1744 TNY_FOLDER_STORE (trash_folder),
1746 g_object_unref (trash_folder);
1748 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1751 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1753 modest_mail_operation_notify_start (self);
1754 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1755 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1758 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1760 g_object_unref (parent);
1762 g_warning ("%s: could not get parent folder", __FUNCTION__);
1764 g_object_unref (G_OBJECT (account));
1767 /* Notify about operation end */
1768 modest_mail_operation_notify_end (self);
1772 transfer_folder_status_cb (GObject *obj,
1776 ModestMailOperation *self;
1777 ModestMailOperationPrivate *priv;
1778 ModestMailOperationState *state;
1779 XFerFolderAsyncHelper *helper;
1781 g_return_if_fail (status != NULL);
1782 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1784 helper = (XFerFolderAsyncHelper *) user_data;
1785 g_return_if_fail (helper != NULL);
1787 self = helper->mail_op;
1788 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1790 priv->done = status->position;
1791 priv->total = status->of_total;
1793 state = modest_mail_operation_clone_state (self);
1795 /* This is not a GDK lock because we are a Tinymail callback
1796 * which is already GDK locked by Tinymail */
1798 /* no gdk_threads_enter (), CHECKED */
1800 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1802 /* no gdk_threads_leave (), CHECKED */
1804 g_slice_free (ModestMailOperationState, state);
1809 transfer_folder_cb (TnyFolder *folder,
1811 TnyFolderStore *into,
1812 TnyFolder *new_folder,
1816 XFerFolderAsyncHelper *helper;
1817 ModestMailOperation *self = NULL;
1818 ModestMailOperationPrivate *priv = NULL;
1820 helper = (XFerFolderAsyncHelper *) user_data;
1821 g_return_if_fail (helper != NULL);
1823 self = helper->mail_op;
1824 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1827 priv->error = g_error_copy (err);
1829 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1830 } else if (cancelled) {
1831 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1832 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1833 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1834 _("Transference of %s was cancelled."),
1835 tny_folder_get_name (folder));
1838 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1841 /* Notify about operation end */
1842 modest_mail_operation_notify_end (self);
1844 /* If user defined callback function was defined, call it */
1845 if (helper->user_callback) {
1847 /* This is not a GDK lock because we are a Tinymail callback
1848 * which is already GDK locked by Tinymail */
1850 /* no gdk_threads_enter (), CHECKED */
1851 helper->user_callback (self, new_folder, helper->user_data);
1852 /* no gdk_threads_leave () , CHECKED */
1856 g_object_unref (helper->mail_op);
1857 g_slice_free (XFerFolderAsyncHelper, helper);
1862 * This function checks if the new name is a valid name for our local
1863 * folders account. The new name could not be the same than then name
1864 * of any of the mandatory local folders
1866 * We can not rely on tinymail because tinymail does not check the
1867 * name of the virtual folders that the account could have in the case
1868 * that we're doing a rename (because it directly calls Camel which
1869 * knows nothing about our virtual folders).
1871 * In the case of an actual copy/move (i.e. move/copy a folder between
1872 * accounts) tinymail uses the tny_folder_store_create_account which
1873 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1874 * checks the new name of the folder, so this call in that case
1875 * wouldn't be needed. *But* NOTE that if tinymail changes its
1876 * implementation (if folder transfers within the same account is no
1877 * longer implemented as a rename) this call will allow Modest to work
1880 * If the new name is not valid, this function will set the status to
1881 * failed and will set also an error in the mail operation
1884 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1885 TnyFolderStore *into,
1886 const gchar *new_name)
1888 if (TNY_IS_ACCOUNT (into) &&
1889 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1890 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1892 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1893 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1894 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1895 _CS("ckdg_ib_folder_already_exists"));
1902 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1904 TnyFolderStore *parent,
1905 gboolean delete_original,
1906 XferFolderAsyncUserCallback user_callback,
1909 ModestMailOperationPrivate *priv = NULL;
1910 ModestTnyFolderRules parent_rules = 0, rules;
1911 XFerFolderAsyncHelper *helper = NULL;
1912 const gchar *folder_name = NULL;
1913 const gchar *error_msg;
1915 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1916 g_return_if_fail (TNY_IS_FOLDER (folder));
1917 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1919 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1920 folder_name = tny_folder_get_name (folder);
1922 /* Set the error msg */
1923 error_msg = _("mail_in_ui_folder_move_target_error");
1925 /* Get account and set it into mail_operation */
1926 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1927 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1928 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1930 /* Get folder rules */
1931 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1932 if (TNY_IS_FOLDER (parent))
1933 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1935 /* Apply operation constraints */
1936 if ((gpointer) parent == (gpointer) folder ||
1937 (!TNY_IS_FOLDER_STORE (parent)) ||
1938 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1941 } else if (TNY_IS_FOLDER (parent) &&
1942 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
1946 } else if (TNY_IS_FOLDER (parent) &&
1947 TNY_IS_FOLDER_STORE (folder) &&
1948 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
1949 TNY_FOLDER_STORE (folder))) {
1950 /* Do not move a parent into a child */
1952 } else if (TNY_IS_FOLDER_STORE (parent) &&
1953 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
1954 /* Check that the new folder name is not used by any
1957 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
1958 /* Check that the new folder name is not used by any
1959 special local folder */
1962 /* Create the helper */
1963 helper = g_slice_new0 (XFerFolderAsyncHelper);
1964 helper->mail_op = g_object_ref (self);
1965 helper->user_callback = user_callback;
1966 helper->user_data = user_data;
1968 /* Move/Copy folder */
1969 modest_mail_operation_notify_start (self);
1970 tny_folder_copy_async (folder,
1972 tny_folder_get_name (folder),
1975 transfer_folder_status_cb,
1981 /* Set status failed and set an error */
1982 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1983 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1984 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1987 /* Call the user callback if exists */
1989 user_callback (self, NULL, user_data);
1991 /* Notify the queue */
1992 modest_mail_operation_notify_end (self);
1996 modest_mail_operation_rename_folder (ModestMailOperation *self,
1999 XferFolderAsyncUserCallback user_callback,
2002 ModestMailOperationPrivate *priv;
2003 ModestTnyFolderRules rules;
2004 XFerFolderAsyncHelper *helper;
2006 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2007 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2008 g_return_if_fail (name);
2010 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2012 /* Get account and set it into mail_operation */
2013 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2014 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2016 /* Check folder rules */
2017 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2018 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2020 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2023 TnyFolderStore *into;
2025 into = tny_folder_get_folder_store (folder);
2027 /* Check that the new folder name is not used by any
2028 special local folder */
2029 if (new_name_valid_if_local_account (priv, into, name)) {
2030 /* Create the helper */
2031 helper = g_slice_new0 (XFerFolderAsyncHelper);
2032 helper->mail_op = g_object_ref(self);
2033 helper->user_callback = user_callback;
2034 helper->user_data = user_data;
2036 /* Rename. Camel handles folder subscription/unsubscription */
2037 modest_mail_operation_notify_start (self);
2038 tny_folder_copy_async (folder, into, name, TRUE,
2040 transfer_folder_status_cb,
2045 g_object_unref (into);
2050 /* Set status failed and set an error */
2051 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2052 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2053 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2054 _("FIXME: unable to rename"));
2057 user_callback (self, NULL, user_data);
2059 /* Notify about operation end */
2060 modest_mail_operation_notify_end (self);
2063 /* ******************************************************************* */
2064 /* ************************** MSG ACTIONS ************************* */
2065 /* ******************************************************************* */
2068 modest_mail_operation_get_msg (ModestMailOperation *self,
2070 GetMsgAsyncUserCallback user_callback,
2073 GetMsgInfo *helper = NULL;
2075 ModestMailOperationPrivate *priv;
2077 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2078 g_return_if_fail (TNY_IS_HEADER (header));
2080 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2081 folder = tny_header_get_folder (header);
2083 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2087 /* Get account and set it into mail_operation */
2088 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2090 /* Check for cached messages */
2091 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2092 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2094 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2096 /* Create the helper */
2097 helper = g_slice_new0 (GetMsgInfo);
2098 helper->header = g_object_ref (header);
2099 helper->mail_op = g_object_ref (self);
2100 helper->user_callback = user_callback;
2101 helper->user_data = user_data;
2102 helper->destroy_notify = NULL;
2103 helper->last_total_bytes = 0;
2104 helper->sum_total_bytes = 0;
2105 helper->total_bytes = tny_header_get_message_size (header);
2107 modest_mail_operation_notify_start (self);
2109 /* notify about the start of the operation */
2110 ModestMailOperationState *state;
2111 state = modest_mail_operation_clone_state (self);
2114 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2117 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2119 g_object_unref (G_OBJECT (folder));
2123 get_msg_status_cb (GObject *obj,
2127 GetMsgInfo *helper = NULL;
2129 g_return_if_fail (status != NULL);
2130 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2132 helper = (GetMsgInfo *) user_data;
2133 g_return_if_fail (helper != NULL);
2135 /* Notify progress */
2136 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2137 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2141 get_msg_async_cb (TnyFolder *folder,
2147 GetMsgInfo *info = NULL;
2148 ModestMailOperationPrivate *priv = NULL;
2151 info = (GetMsgInfo *) user_data;
2153 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2156 if (info->more_msgs) {
2157 tny_iterator_next (info->more_msgs);
2158 finished = (tny_iterator_is_done (info->more_msgs));
2160 finished = (priv->done == priv->total) ? TRUE : FALSE;
2164 if (canceled || err) {
2165 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2167 priv->error = g_error_copy ((const GError *) err);
2168 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2171 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2172 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2175 } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
2176 /* Set the success status before calling the user callback */
2177 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2178 } else if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED) {
2184 /* Call the user callback */
2185 if (info->user_callback)
2186 info->user_callback (info->mail_op, info->header, canceled,
2187 msg, err, info->user_data);
2189 /* Notify about operation end if this is the last callback */
2191 /* Free user data */
2192 if (info->destroy_notify)
2193 info->destroy_notify (info->user_data);
2195 /* Notify about operation end */
2196 modest_mail_operation_notify_end (info->mail_op);
2199 if (info->more_msgs)
2200 g_object_unref (info->more_msgs);
2201 g_object_unref (info->header);
2202 g_object_unref (info->mail_op);
2203 g_slice_free (GetMsgInfo, info);
2204 } else if (info->more_msgs) {
2205 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->more_msgs));
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 TnyIterator *iterator = tny_list_create_iterator (header_list);
2244 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iterator));
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);
2253 g_object_unref (iterator);
2256 msg_list_size = compute_message_list_size (header_list);
2258 modest_mail_operation_notify_start (self);
2259 iter = tny_list_create_iterator (header_list);
2260 if (!tny_iterator_is_done (iter)) {
2261 /* notify about the start of the operation */
2262 ModestMailOperationState *state;
2263 state = modest_mail_operation_clone_state (self);
2266 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2269 GetMsgInfo *msg_info = NULL;
2270 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2271 TnyFolder *folder = tny_header_get_folder (header);
2273 /* Create the message info */
2274 msg_info = g_slice_new0 (GetMsgInfo);
2275 msg_info->mail_op = g_object_ref (self);
2276 msg_info->header = g_object_ref (header);
2277 msg_info->more_msgs = g_object_ref (iter);
2278 msg_info->user_callback = user_callback;
2279 msg_info->user_data = user_data;
2280 msg_info->destroy_notify = notify;
2281 msg_info->last_total_bytes = 0;
2282 msg_info->sum_total_bytes = 0;
2283 msg_info->total_bytes = msg_list_size;
2285 /* The callback will call it per each header */
2286 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2288 /* Free and go on */
2289 g_object_unref (header);
2290 g_object_unref (folder);
2291 g_slice_free (ModestMailOperationState, state);
2293 g_object_unref (iter);
2298 modest_mail_operation_remove_msg (ModestMailOperation *self,
2300 gboolean remove_to_trash /*ignored*/)
2303 ModestMailOperationPrivate *priv;
2305 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2306 g_return_if_fail (TNY_IS_HEADER (header));
2308 if (remove_to_trash)
2309 g_warning ("remove to trash is not implemented");
2311 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2312 folder = tny_header_get_folder (header);
2314 /* Get account and set it into mail_operation */
2315 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2316 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2317 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2319 /* remove message from folder */
2320 tny_folder_remove_msg (folder, header, &(priv->error));
2322 gboolean expunge, leave_on_server;
2323 const gchar *account_name;
2324 TnyAccount *account;
2325 ModestTransportStoreProtocol account_proto;
2327 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2328 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2330 modest_mail_operation_notify_start (self);
2332 /* Get leave on server setting */
2333 account = tny_folder_get_account (folder);
2334 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2336 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2339 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2341 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2342 modest_tny_folder_is_remote_folder (folder) == FALSE)
2348 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2351 g_object_unref (account);
2357 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2359 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2362 g_object_unref (G_OBJECT (folder));
2364 /* Notify about operation end */
2365 modest_mail_operation_notify_end (self);
2369 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2371 gboolean remove_to_trash /*ignored*/)
2373 TnyFolder *folder = NULL;
2374 ModestMailOperationPrivate *priv;
2375 TnyIterator *iter = NULL;
2376 TnyHeader *header = NULL;
2377 TnyList *remove_headers = NULL;
2378 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2380 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2381 g_return_if_fail (TNY_IS_LIST (headers));
2383 if (remove_to_trash)
2384 g_warning ("remove to trash is not implemented");
2386 if (tny_list_get_length(headers) == 0) {
2387 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2388 goto cleanup; /* nothing to do */
2391 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2392 remove_headers = g_object_ref(headers);
2394 /* Get folder from first header and sync it */
2395 iter = tny_list_create_iterator (headers);
2396 header = TNY_HEADER (tny_iterator_get_current (iter));
2398 folder = tny_header_get_folder (header);
2399 if (!TNY_IS_FOLDER(folder)) {
2400 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2404 /* Don't remove messages that are being sent */
2405 if (modest_tny_folder_is_local_folder (folder)) {
2406 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2408 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2409 TnyTransportAccount *traccount = NULL;
2410 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2411 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2413 ModestTnySendQueueStatus status;
2414 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2415 TnyIterator *iter = tny_list_create_iterator(headers);
2416 g_object_unref(remove_headers);
2417 remove_headers = TNY_LIST(tny_simple_list_new());
2418 while (!tny_iterator_is_done(iter)) {
2420 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2421 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2422 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2423 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2424 tny_list_append(remove_headers, G_OBJECT(hdr));
2426 g_object_unref(hdr);
2428 tny_iterator_next(iter);
2430 g_object_unref(iter);
2431 g_object_unref(traccount);
2435 /* Get account and set it into mail_operation */
2436 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2437 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2438 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2440 /* remove message from folder */
2441 modest_mail_operation_notify_start (self);
2443 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2445 gboolean expunge, leave_on_server;
2446 const gchar *account_name;
2448 TnyAccount *account;
2449 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2451 account = tny_folder_get_account (folder);
2452 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2454 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2457 proto = tny_account_get_proto (account);
2459 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2462 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2463 modest_tny_folder_is_remote_folder (folder) == FALSE)
2469 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2471 g_object_unref (account);
2477 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2479 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2484 g_object_unref (remove_headers);
2486 g_object_unref (header);
2488 g_object_unref (iter);
2490 g_object_unref (folder);
2492 /* Notify about operation end */
2493 modest_mail_operation_notify_end (self);
2497 notify_progress_of_multiple_messages (ModestMailOperation *self,
2499 gint *last_total_bytes,
2500 gint *sum_total_bytes,
2502 gboolean increment_done)
2504 ModestMailOperationPrivate *priv;
2505 ModestMailOperationState *state;
2506 gboolean is_num_bytes = FALSE;
2508 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2510 /* We know that tinymail sends us information about
2511 * transferred bytes with this particular message
2513 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2514 * I just added the 'if' so we don't get runtime warning)
2516 if (status->message)
2517 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2519 state = modest_mail_operation_clone_state (self);
2520 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2521 /* We know that we're in a different message when the
2522 total number of bytes to transfer is different. Of
2523 course it could fail if we're transferring messages
2524 of the same size, but this is a workarround */
2525 if (status->of_total != *last_total_bytes) {
2526 /* We need to increment the done when there is
2527 no information about each individual
2528 message, we need to do this in message
2529 transfers, and we don't do it for getting
2533 *sum_total_bytes += *last_total_bytes;
2534 *last_total_bytes = status->of_total;
2536 state->bytes_done += status->position + *sum_total_bytes;
2537 state->bytes_total = total_bytes;
2539 /* Notify the status change. Only notify about changes
2540 referred to bytes */
2541 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2545 g_slice_free (ModestMailOperationState, state);
2549 transfer_msgs_status_cb (GObject *obj,
2553 XFerMsgsAsyncHelper *helper;
2555 g_return_if_fail (status != NULL);
2556 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2558 helper = (XFerMsgsAsyncHelper *) user_data;
2559 g_return_if_fail (helper != NULL);
2561 /* Notify progress */
2562 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2563 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2568 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2570 XFerMsgsAsyncHelper *helper;
2571 ModestMailOperation *self;
2572 ModestMailOperationPrivate *priv;
2573 gboolean finished = TRUE;
2575 helper = (XFerMsgsAsyncHelper *) user_data;
2576 self = helper->mail_op;
2578 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2581 priv->error = g_error_copy (err);
2583 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2584 } else if (cancelled) {
2585 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2586 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2587 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2588 _("Error trying to refresh the contents of %s"),
2589 tny_folder_get_name (folder));
2590 } else if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
2591 if (helper->more_msgs) {
2592 /* We'll transfer the next message in the list */
2593 tny_iterator_next (helper->more_msgs);
2594 if (!tny_iterator_is_done (helper->more_msgs)) {
2595 GObject *next_header;
2596 g_object_unref (helper->headers);
2597 helper->headers = tny_simple_list_new ();
2598 next_header = tny_iterator_get_current (helper->more_msgs);
2599 tny_list_append (helper->headers, next_header);
2600 g_object_unref (next_header);
2607 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2613 /* Update folder counts */
2614 tny_folder_poke_status (folder);
2615 tny_folder_poke_status (helper->dest_folder);
2617 /* Notify about operation end */
2618 modest_mail_operation_notify_end (self);
2620 /* If user defined callback function was defined, call it */
2621 if (helper->user_callback) {
2622 /* This is not a GDK lock because we are a Tinymail callback and
2623 * Tinymail already acquires the Gdk lock */
2625 /* no gdk_threads_enter (), CHECKED */
2626 helper->user_callback (self, helper->user_data);
2627 /* no gdk_threads_leave (), CHECKED */
2631 if (helper->more_msgs)
2632 g_object_unref (helper->more_msgs);
2633 if (helper->headers)
2634 g_object_unref (helper->headers);
2635 if (helper->dest_folder)
2636 g_object_unref (helper->dest_folder);
2637 if (helper->mail_op)
2638 g_object_unref (helper->mail_op);
2639 g_slice_free (XFerMsgsAsyncHelper, helper);
2641 /* Transfer more messages */
2642 tny_folder_transfer_msgs_async (folder,
2644 helper->dest_folder,
2647 transfer_msgs_status_cb,
2653 compute_message_list_size (TnyList *headers)
2658 iter = tny_list_create_iterator (headers);
2659 while (!tny_iterator_is_done (iter)) {
2660 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2661 size += tny_header_get_message_size (header);
2662 g_object_unref (header);
2663 tny_iterator_next (iter);
2665 g_object_unref (iter);
2671 compute_message_array_size (GPtrArray *headers)
2676 for (i = 0; i < headers->len; i++) {
2677 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2678 size += tny_header_get_message_size (header);
2686 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2689 gboolean delete_original,
2690 XferMsgsAsyncUserCallback user_callback,
2693 ModestMailOperationPrivate *priv = NULL;
2694 TnyIterator *iter = NULL;
2695 TnyFolder *src_folder = NULL;
2696 XFerMsgsAsyncHelper *helper = NULL;
2697 TnyHeader *header = NULL;
2698 ModestTnyFolderRules rules = 0;
2699 TnyAccount *dst_account = NULL;
2701 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2702 g_return_if_fail (headers && TNY_IS_LIST (headers));
2703 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2705 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2706 priv->total = tny_list_get_length (headers);
2708 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2709 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2711 /* Apply folder rules */
2712 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2713 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2714 /* Set status failed and set an error */
2715 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2716 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2717 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2718 _CS("ckct_ib_unable_to_paste_here"));
2719 /* Notify the queue */
2720 modest_mail_operation_notify_end (self);
2724 /* Get source folder */
2725 iter = tny_list_create_iterator (headers);
2726 header = TNY_HEADER (tny_iterator_get_current (iter));
2728 src_folder = tny_header_get_folder (header);
2729 g_object_unref (header);
2731 g_object_unref (iter);
2733 if (src_folder == NULL) {
2734 /* Notify the queue */
2735 modest_mail_operation_notify_end (self);
2737 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2742 /* Check folder source and destination */
2743 if (src_folder == folder) {
2744 /* Set status failed and set an error */
2745 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2746 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2747 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2748 _("mail_in_ui_folder_copy_target_error"));
2750 /* Notify the queue */
2751 modest_mail_operation_notify_end (self);
2754 g_object_unref (src_folder);
2758 /* Create the helper */
2759 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2760 helper->mail_op = g_object_ref(self);
2761 helper->dest_folder = g_object_ref(folder);
2762 helper->user_callback = user_callback;
2763 helper->user_data = user_data;
2764 helper->delete = delete_original;
2765 helper->last_total_bytes = 0;
2766 helper->sum_total_bytes = 0;
2767 helper->total_bytes = compute_message_list_size (headers);
2769 /* Get account and set it into mail_operation */
2770 priv->account = modest_tny_folder_get_account (src_folder);
2771 dst_account = modest_tny_folder_get_account (folder);
2773 if (priv->account == dst_account) {
2774 /* Transfer all messages at once using the fast
2775 * method. Note that depending on the server this
2776 * might not be that fast, and might not be
2777 * user-cancellable either */
2778 helper->headers = g_object_ref (headers);
2779 helper->more_msgs = NULL;
2781 /* Transfer messages one by one so the user can cancel
2784 helper->headers = tny_simple_list_new ();
2785 helper->more_msgs = tny_list_create_iterator (headers);
2786 hdr = tny_iterator_get_current (helper->more_msgs);
2787 tny_list_append (helper->headers, hdr);
2788 g_object_unref (hdr);
2791 modest_mail_operation_notify_start (self);
2792 tny_folder_transfer_msgs_async (src_folder,
2797 transfer_msgs_status_cb,
2799 g_object_unref (src_folder);
2800 g_object_unref (dst_account);
2805 on_refresh_folder (TnyFolder *folder,
2810 RefreshAsyncHelper *helper = NULL;
2811 ModestMailOperation *self = NULL;
2812 ModestMailOperationPrivate *priv = NULL;
2814 helper = (RefreshAsyncHelper *) user_data;
2815 self = helper->mail_op;
2816 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2818 g_return_if_fail(priv!=NULL);
2821 priv->error = g_error_copy (error);
2822 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2827 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2828 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2829 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2830 _("Error trying to refresh the contents of %s"),
2831 tny_folder_get_name (folder));
2835 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2838 /* Call user defined callback, if it exists */
2839 if (helper->user_callback) {
2841 /* This is not a GDK lock because we are a Tinymail callback and
2842 * Tinymail already acquires the Gdk lock */
2843 helper->user_callback (self, folder, helper->user_data);
2847 g_slice_free (RefreshAsyncHelper, helper);
2849 /* Notify about operation end */
2850 modest_mail_operation_notify_end (self);
2851 g_object_unref(self);
2855 on_refresh_folder_status_update (GObject *obj,
2859 RefreshAsyncHelper *helper = NULL;
2860 ModestMailOperation *self = NULL;
2861 ModestMailOperationPrivate *priv = NULL;
2862 ModestMailOperationState *state;
2864 g_return_if_fail (user_data != NULL);
2865 g_return_if_fail (status != NULL);
2866 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2868 helper = (RefreshAsyncHelper *) user_data;
2869 self = helper->mail_op;
2870 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2872 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2874 priv->done = status->position;
2875 priv->total = status->of_total;
2877 state = modest_mail_operation_clone_state (self);
2879 /* This is not a GDK lock because we are a Tinymail callback and
2880 * Tinymail already acquires the Gdk lock */
2881 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2883 g_slice_free (ModestMailOperationState, state);
2887 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2889 RefreshAsyncUserCallback user_callback,
2892 ModestMailOperationPrivate *priv = NULL;
2893 RefreshAsyncHelper *helper = NULL;
2895 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2897 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2899 /* Get account and set it into mail_operation */
2900 priv->account = modest_tny_folder_get_account (folder);
2901 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2903 /* Create the helper */
2904 helper = g_slice_new0 (RefreshAsyncHelper);
2905 helper->mail_op = g_object_ref(self);
2906 helper->user_callback = user_callback;
2907 helper->user_data = user_data;
2909 /* Refresh the folder. TODO: tinymail could issue a status
2910 updates before the callback call then this could happen. We
2911 must review the design */
2912 modest_mail_operation_notify_start (self);
2914 /* notify that the operation was started */
2915 ModestMailOperationState *state;
2916 state = modest_mail_operation_clone_state (self);
2919 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2922 /* FIXME: we're leaking the state here, or? valgrind thinks so */
2924 tny_folder_refresh_async (folder,
2926 on_refresh_folder_status_update,
2931 run_queue_stop (ModestTnySendQueue *queue,
2932 ModestMailOperation *self)
2934 ModestMailOperationPrivate *priv;
2936 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2937 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2938 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2940 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2942 modest_mail_operation_notify_end (self);
2943 g_signal_handlers_disconnect_by_func (queue, run_queue_stop, self);
2944 g_object_unref (self);
2947 modest_mail_operation_run_queue (ModestMailOperation *self,
2948 ModestTnySendQueue *queue)
2950 ModestMailOperationPrivate *priv;
2952 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2953 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2954 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2956 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2957 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
2958 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
2960 modest_mail_operation_notify_start (self);
2961 g_object_ref (self);
2962 g_signal_connect ((gpointer) queue, "queue-stop", G_CALLBACK (run_queue_stop), (gpointer) self);
2966 sync_folder_finish_callback (TnyFolder *self, gboolean cancelled, GError *err, ModestMailOperation *mail_op)
2968 ModestMailOperationPrivate *priv;
2970 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
2972 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2973 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2975 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2977 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2979 modest_mail_operation_notify_end (mail_op);
2980 g_object_unref (mail_op);
2984 modest_mail_operation_sync_folder (ModestMailOperation *self,
2985 TnyFolder *folder, gboolean expunge)
2987 ModestMailOperationPrivate *priv;
2989 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2990 g_return_if_fail (TNY_IS_FOLDER (folder));
2991 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2993 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2994 priv->account = TNY_ACCOUNT (tny_folder_get_account (folder));
2995 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
2997 modest_mail_operation_notify_start (self);
2998 g_object_ref (self);
2999 tny_folder_sync_async (folder, expunge, (TnyFolderCallback) sync_folder_finish_callback, NULL, self);
3003 modest_mail_operation_notify_start (ModestMailOperation *self)
3005 ModestMailOperationPrivate *priv = NULL;
3007 g_return_if_fail (self);
3009 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3011 /* Ensure that all the fields are filled correctly */
3012 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
3014 /* Notify the observers about the mail operation. We do not
3015 wrapp this emission because we assume that this function is
3016 always called from within the main lock */
3017 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
3022 * It's used by the mail operation queue to notify the observers
3023 * attached to that signal that the operation finished. We need to use
3024 * that because tinymail does not give us the progress of a given
3025 * operation when it finishes (it directly calls the operation
3029 modest_mail_operation_notify_end (ModestMailOperation *self)
3031 ModestMailOperationPrivate *priv = NULL;
3033 g_return_if_fail (self);
3035 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3037 /* Notify the observers about the mail operation end. We do
3038 not wrapp this emission because we assume that this
3039 function is always called from within the main lock */
3040 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3042 /* Remove the error user data */
3043 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3044 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3048 modest_mail_operation_get_account (ModestMailOperation *self)
3050 ModestMailOperationPrivate *priv = NULL;
3052 g_return_val_if_fail (self, NULL);
3054 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3056 return (priv->account) ? g_object_ref (priv->account) : NULL;
3060 modest_mail_operation_noop (ModestMailOperation *self)
3062 ModestMailOperationPrivate *priv = NULL;
3064 g_return_if_fail (self);
3066 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3067 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3068 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3072 /* This mail operation does nothing actually */
3073 modest_mail_operation_notify_start (self);
3074 modest_mail_operation_notify_end (self);
3079 modest_mail_operation_to_string (ModestMailOperation *self)
3081 const gchar *type, *status, *account_id;
3082 ModestMailOperationPrivate *priv = NULL;
3084 g_return_val_if_fail (self, NULL);
3086 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3088 /* new operations don't have anything interesting */
3089 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3090 return g_strdup_printf ("%p <new operation>", self);
3092 switch (priv->op_type) {
3093 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3094 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3095 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3096 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3097 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3098 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3099 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3100 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3101 default: type = "UNEXPECTED"; break;
3104 switch (priv->status) {
3105 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3106 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3107 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3108 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3109 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3110 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3111 default: status= "UNEXPECTED"; break;
3114 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3116 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3117 priv->done, priv->total,
3118 priv->error && priv->error->message ? priv->error->message : "");