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;
139 ModestMailOperation *mail_op;
140 GDestroyNotify destroy_notify;
141 gint last_total_bytes;
142 gint sum_total_bytes;
147 ModestMailOperation *mail_op;
149 gulong msg_sent_handler;
150 gulong error_happened_handler;
153 static void send_mail_msg_sent_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
154 guint nth, guint total, gpointer userdata);
155 static void send_mail_error_happened_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
156 GError *error, gpointer userdata);
157 static void common_send_mail_operation_end (TnySendQueue *queue, TnyMsg *msg,
160 typedef struct _RefreshAsyncHelper {
161 ModestMailOperation *mail_op;
162 RefreshAsyncUserCallback user_callback;
164 } RefreshAsyncHelper;
166 typedef struct _XFerMsgsAsyncHelper
168 ModestMailOperation *mail_op;
170 TnyFolder *dest_folder;
171 XferMsgsAsyncUserCallback user_callback;
174 gint last_total_bytes;
175 gint sum_total_bytes;
177 } XFerMsgsAsyncHelper;
179 typedef struct _XFerFolderAsyncHelper
181 ModestMailOperation *mail_op;
182 XferFolderAsyncUserCallback user_callback;
184 } XFerFolderAsyncHelper;
186 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
190 static void modest_mail_operation_create_msg (ModestMailOperation *self,
191 const gchar *from, const gchar *to,
192 const gchar *cc, const gchar *bcc,
193 const gchar *subject, const gchar *plain_body,
194 const gchar *html_body, const GList *attachments_list,
195 const GList *images_list,
196 TnyHeaderFlags priority_flags,
197 ModestMailOperationCreateMsgCallback callback,
200 static gboolean idle_notify_queue (gpointer data);
203 ModestMailOperation *mail_op;
211 GList *attachments_list;
213 TnyHeaderFlags priority_flags;
214 ModestMailOperationCreateMsgCallback callback;
220 ModestMailOperation *mail_op;
222 ModestMailOperationCreateMsgCallback callback;
227 static GObjectClass *parent_class = NULL;
229 static guint signals[NUM_SIGNALS] = {0};
232 modest_mail_operation_get_type (void)
234 static GType my_type = 0;
236 static const GTypeInfo my_info = {
237 sizeof(ModestMailOperationClass),
238 NULL, /* base init */
239 NULL, /* base finalize */
240 (GClassInitFunc) modest_mail_operation_class_init,
241 NULL, /* class finalize */
242 NULL, /* class data */
243 sizeof(ModestMailOperation),
245 (GInstanceInitFunc) modest_mail_operation_init,
248 my_type = g_type_register_static (G_TYPE_OBJECT,
249 "ModestMailOperation",
256 modest_mail_operation_class_init (ModestMailOperationClass *klass)
258 GObjectClass *gobject_class;
259 gobject_class = (GObjectClass*) klass;
261 parent_class = g_type_class_peek_parent (klass);
262 gobject_class->finalize = modest_mail_operation_finalize;
264 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
267 * ModestMailOperation::progress-changed
268 * @self: the #MailOperation that emits the signal
269 * @user_data: user data set when the signal handler was connected
271 * Emitted when the progress of a mail operation changes
273 signals[PROGRESS_CHANGED_SIGNAL] =
274 g_signal_new ("progress-changed",
275 G_TYPE_FROM_CLASS (gobject_class),
277 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
279 g_cclosure_marshal_VOID__POINTER,
280 G_TYPE_NONE, 1, G_TYPE_POINTER);
284 * This signal is issued whenever a mail operation starts, and
285 * starts mean when the tinymail operation is issued. This
286 * means that it could happen that something wrong happens and
287 * the tinymail function is never called. In this situation a
288 * operation-finished will be issued without any
291 signals[OPERATION_STARTED_SIGNAL] =
292 g_signal_new ("operation-started",
293 G_TYPE_FROM_CLASS (gobject_class),
295 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
297 g_cclosure_marshal_VOID__VOID,
302 * This signal is issued whenever a mail operation
303 * finishes. Note that this signal could be issued without any
304 * previous "operation-started" signal, because this last one
305 * is only issued when the tinymail operation is successfully
308 signals[OPERATION_FINISHED_SIGNAL] =
309 g_signal_new ("operation-finished",
310 G_TYPE_FROM_CLASS (gobject_class),
312 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
314 g_cclosure_marshal_VOID__VOID,
319 modest_mail_operation_init (ModestMailOperation *obj)
321 ModestMailOperationPrivate *priv;
323 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
325 priv->account = NULL;
326 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
327 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
332 priv->error_checking = NULL;
333 priv->error_checking_user_data = NULL;
337 modest_mail_operation_finalize (GObject *obj)
339 ModestMailOperationPrivate *priv;
341 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
346 g_error_free (priv->error);
350 g_object_unref (priv->source);
354 g_object_unref (priv->account);
355 priv->account = NULL;
359 G_OBJECT_CLASS(parent_class)->finalize (obj);
363 modest_mail_operation_new (GObject *source)
365 ModestMailOperation *obj;
366 ModestMailOperationPrivate *priv;
368 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
369 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
372 priv->source = g_object_ref(source);
378 modest_mail_operation_new_with_error_handling (GObject *source,
379 ErrorCheckingUserCallback error_handler,
381 ErrorCheckingUserDataDestroyer error_handler_destroyer)
383 ModestMailOperation *obj;
384 ModestMailOperationPrivate *priv;
386 obj = modest_mail_operation_new (source);
387 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
389 g_return_val_if_fail (error_handler != NULL, obj);
390 priv->error_checking = error_handler;
391 priv->error_checking_user_data = user_data;
392 priv->error_checking_user_data_destroyer = error_handler_destroyer;
398 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
400 ModestMailOperationPrivate *priv;
402 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
404 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
405 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
407 /* Call the user callback */
408 if (priv->error_checking != NULL)
409 priv->error_checking (self, priv->error_checking_user_data);
413 ModestMailOperationTypeOperation
414 modest_mail_operation_get_type_operation (ModestMailOperation *self)
416 ModestMailOperationPrivate *priv;
418 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
419 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
421 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
423 return priv->op_type;
427 modest_mail_operation_is_mine (ModestMailOperation *self,
430 ModestMailOperationPrivate *priv;
432 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
435 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
436 if (priv->source == NULL) return FALSE;
438 return priv->source == me;
442 modest_mail_operation_get_source (ModestMailOperation *self)
444 ModestMailOperationPrivate *priv;
446 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
449 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
451 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
455 return (priv->source) ? g_object_ref (priv->source) : NULL;
458 ModestMailOperationStatus
459 modest_mail_operation_get_status (ModestMailOperation *self)
461 ModestMailOperationPrivate *priv;
463 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
464 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
465 MODEST_MAIL_OPERATION_STATUS_INVALID);
467 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
469 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
470 return MODEST_MAIL_OPERATION_STATUS_INVALID;
477 modest_mail_operation_get_error (ModestMailOperation *self)
479 ModestMailOperationPrivate *priv;
481 g_return_val_if_fail (self, NULL);
482 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
484 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
487 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
495 modest_mail_operation_cancel (ModestMailOperation *self)
497 ModestMailOperationPrivate *priv;
498 gboolean canceled = FALSE;
500 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
502 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
504 /* Note that if we call cancel with an already canceled mail
505 operation the progress changed signal won't be emitted */
506 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
510 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
512 /* Cancel the mail operation */
513 g_return_val_if_fail (priv->account, FALSE);
514 tny_account_cancel (priv->account);
516 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
517 ModestTnySendQueue *queue;
518 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
520 /* Cancel the sending of the following next messages */
521 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, NULL);
528 modest_mail_operation_get_task_done (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_get_task_total (ModestMailOperation *self)
542 ModestMailOperationPrivate *priv;
544 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
547 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
552 modest_mail_operation_is_finished (ModestMailOperation *self)
554 ModestMailOperationPrivate *priv;
555 gboolean retval = FALSE;
557 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
560 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
562 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
563 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
564 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
565 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
575 * Creates an image of the current state of a mail operation, the
576 * caller must free it
578 static ModestMailOperationState *
579 modest_mail_operation_clone_state (ModestMailOperation *self)
581 ModestMailOperationState *state;
582 ModestMailOperationPrivate *priv;
584 /* FIXME: this should be fixed properly
586 * in some cases, priv was NULL, so checking here to
589 g_return_val_if_fail (self, NULL);
590 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
591 g_return_val_if_fail (priv, NULL);
596 state = g_slice_new (ModestMailOperationState);
598 state->status = priv->status;
599 state->op_type = priv->op_type;
600 state->done = priv->done;
601 state->total = priv->total;
602 state->finished = modest_mail_operation_is_finished (self);
603 state->bytes_done = 0;
604 state->bytes_total = 0;
609 /* ******************************************************************* */
610 /* ************************** SEND ACTIONS ************************* */
611 /* ******************************************************************* */
614 modest_mail_operation_send_mail (ModestMailOperation *self,
615 TnyTransportAccount *transport_account,
618 TnySendQueue *send_queue = NULL;
619 ModestMailOperationPrivate *priv;
622 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
623 g_return_if_fail (transport_account && TNY_IS_TRANSPORT_ACCOUNT (transport_account));
624 g_return_if_fail (msg && TNY_IS_MSG (msg));
626 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
628 /* Get account and set it into mail_operation */
629 priv->account = g_object_ref (transport_account);
630 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
634 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
635 if (!TNY_IS_SEND_QUEUE(send_queue)) {
636 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
637 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
638 "modest: could not find send queue for account\n");
639 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
640 modest_mail_operation_notify_end (self);
643 /* Add the msg to the queue */
644 modest_mail_operation_notify_start (self);
646 info = g_slice_new0 (SendMsgInfo);
648 info->mail_op = g_object_ref (self);
649 info->msg = g_object_ref (msg);
650 info->msg_sent_handler = g_signal_connect (G_OBJECT (send_queue), "msg-sent",
651 G_CALLBACK (send_mail_msg_sent_handler), info);
652 info->error_happened_handler = g_signal_connect (G_OBJECT (send_queue), "error-happened",
653 G_CALLBACK (send_mail_error_happened_handler), info);
655 modest_tny_send_queue_add (MODEST_TNY_SEND_QUEUE(send_queue),
659 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
665 common_send_mail_operation_end (TnySendQueue *queue, TnyMsg *msg,
668 g_signal_handler_disconnect (queue, info->msg_sent_handler);
669 g_signal_handler_disconnect (queue, info->error_happened_handler);
671 g_object_unref (info->msg);
672 modest_mail_operation_notify_end (info->mail_op);
673 g_object_unref (info->mail_op);
675 g_slice_free (SendMsgInfo, info);
679 send_mail_msg_sent_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
680 guint nth, guint total, gpointer userdata)
682 SendMsgInfo *info = (SendMsgInfo *) userdata;
683 TnyHeader *hdr1, *hdr2;
684 const char *msgid1, *msgid2;
685 hdr1 = tny_msg_get_header(msg);
686 hdr2 = tny_msg_get_header(info->msg);
687 msgid1 = tny_header_get_message_id(hdr1);
688 msgid2 = tny_header_get_message_id(hdr2);
689 if (msgid1 == NULL) msgid1 = "(null)";
690 if (msgid2 == NULL) msgid2 = "(null)";
692 if (!strcmp (msgid1, msgid2)) {
693 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
694 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
696 common_send_mail_operation_end (queue, msg, info);
698 g_object_unref(G_OBJECT(hdr1));
699 g_object_unref(G_OBJECT(hdr2));
703 send_mail_error_happened_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
704 GError *error, gpointer userdata)
706 SendMsgInfo *info = (SendMsgInfo *) userdata;
707 TnyHeader *hdr1, *hdr2;
708 const char *msgid1, *msgid2;
710 if (!TNY_IS_MSG(msg)) {
711 g_warning ("%s: did not receive a valid msg", __FUNCTION__);
715 hdr1 = tny_msg_get_header(msg);
716 hdr2 = tny_msg_get_header(info->msg);
717 msgid1 = tny_header_get_message_id(hdr1);
718 msgid2 = tny_header_get_message_id(hdr2);
719 if (msgid1 == NULL) msgid1 = "(null)";
720 if (msgid2 == NULL) msgid2 = "(null)";
722 if (!strcmp (msgid1, msgid2)) {
723 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
724 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
725 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
726 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
727 "modest: send mail failed\n");
729 common_send_mail_operation_end (queue, msg, info);
731 g_object_unref(G_OBJECT(hdr1));
732 g_object_unref(G_OBJECT(hdr2));
737 idle_create_msg_cb (gpointer idle_data)
739 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
741 /* This is a GDK lock because we are an idle callback and
742 * info->callback can contain Gtk+ code */
744 gdk_threads_enter (); /* CHECKED */
745 info->callback (info->mail_op, info->msg, info->userdata);
747 g_object_unref (info->mail_op);
749 g_object_unref (info->msg);
750 g_slice_free (CreateMsgIdleInfo, info);
751 gdk_threads_leave (); /* CHECKED */
757 create_msg_thread (gpointer thread_data)
759 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
760 TnyMsg *new_msg = NULL;
761 ModestMailOperationPrivate *priv;
763 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
764 if (info->html_body == NULL) {
765 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
766 info->bcc, info->subject, info->plain_body,
767 info->attachments_list);
769 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
770 info->bcc, info->subject, info->html_body,
771 info->plain_body, info->attachments_list,
778 /* Set priority flags in message */
779 header = tny_msg_get_header (new_msg);
780 tny_header_set_flag (header, info->priority_flags);
782 /* Set attachment flags in message */
783 if (info->attachments_list != NULL)
784 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
786 g_object_unref (G_OBJECT(header));
788 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
789 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
790 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
791 "modest: failed to create a new msg\n");
799 g_free (info->plain_body);
800 g_free (info->html_body);
801 g_free (info->subject);
802 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
803 g_list_free (info->attachments_list);
804 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
805 g_list_free (info->images_list);
807 if (info->callback) {
808 CreateMsgIdleInfo *idle_info;
809 idle_info = g_slice_new0 (CreateMsgIdleInfo);
810 idle_info->mail_op = g_object_ref (info->mail_op);
811 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
812 idle_info->callback = info->callback;
813 idle_info->userdata = info->userdata;
814 g_idle_add (idle_create_msg_cb, idle_info);
816 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
819 g_object_unref (info->mail_op);
820 g_slice_free (CreateMsgInfo, info);
821 if (new_msg) g_object_unref(new_msg);
827 modest_mail_operation_create_msg (ModestMailOperation *self,
828 const gchar *from, const gchar *to,
829 const gchar *cc, const gchar *bcc,
830 const gchar *subject, const gchar *plain_body,
831 const gchar *html_body,
832 const GList *attachments_list,
833 const GList *images_list,
834 TnyHeaderFlags priority_flags,
835 ModestMailOperationCreateMsgCallback callback,
838 ModestMailOperationPrivate *priv;
839 CreateMsgInfo *info = NULL;
841 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
843 info = g_slice_new0 (CreateMsgInfo);
844 info->mail_op = g_object_ref (self);
846 info->from = g_strdup (from);
847 info->to = g_strdup (to);
848 info->cc = g_strdup (cc);
849 info->bcc = g_strdup (bcc);
850 info->subject = g_strdup (subject);
851 info->plain_body = g_strdup (plain_body);
852 info->html_body = g_strdup (html_body);
853 info->attachments_list = g_list_copy ((GList *) attachments_list);
854 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
855 info->images_list = g_list_copy ((GList *) images_list);
856 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
857 info->priority_flags = priority_flags;
859 info->callback = callback;
860 info->userdata = userdata;
862 g_thread_create (create_msg_thread, info, FALSE, NULL);
867 TnyTransportAccount *transport_account;
872 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
876 ModestMailOperationPrivate *priv = NULL;
877 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
878 TnyFolder *draft_folder = NULL;
879 TnyFolder *outbox_folder = NULL;
880 TnyHeader *header = NULL;
887 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
890 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
891 modest_mail_operation_notify_end (self);
895 /* Call mail operation */
896 modest_mail_operation_send_mail (self, info->transport_account, msg);
898 if (info->draft_msg != NULL) {
899 TnyFolder *folder = NULL;
900 TnyFolder *src_folder = NULL;
901 TnyFolderType folder_type;
902 TnyTransportAccount *transport_account = NULL;
904 /* To remove the old mail from its source folder, we need to get the
905 * transport account of the original draft message (the transport account
906 * might have been changed by the user) */
907 header = tny_msg_get_header (info->draft_msg);
908 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
909 modest_runtime_get_account_store(), header);
910 if (transport_account == NULL)
911 transport_account = g_object_ref(info->transport_account);
912 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
913 TNY_FOLDER_TYPE_DRAFTS);
914 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
915 TNY_FOLDER_TYPE_OUTBOX);
916 g_object_unref(transport_account);
919 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
923 if (!outbox_folder) {
924 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
929 folder = tny_msg_get_folder (info->draft_msg);
930 if (folder == NULL) goto end;
931 folder_type = modest_tny_folder_guess_folder_type (folder);
933 if (folder_type == TNY_FOLDER_TYPE_INVALID)
934 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
936 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
937 src_folder = outbox_folder;
939 src_folder = draft_folder;
941 /* Note: This can fail (with a warning) if the message is not really already in a folder,
942 * because this function requires it to have a UID. */
943 tny_folder_remove_msg (src_folder, header, NULL);
945 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
946 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
948 g_object_unref (folder);
953 g_object_unref (header);
957 g_object_unref (info->draft_msg);
959 g_object_unref (draft_folder);
961 g_object_unref (outbox_folder);
962 if (info->transport_account)
963 g_object_unref (info->transport_account);
964 g_slice_free (SendNewMailInfo, info);
968 modest_mail_operation_send_new_mail (ModestMailOperation *self,
969 TnyTransportAccount *transport_account,
971 const gchar *from, const gchar *to,
972 const gchar *cc, const gchar *bcc,
973 const gchar *subject, const gchar *plain_body,
974 const gchar *html_body,
975 const GList *attachments_list,
976 const GList *images_list,
977 TnyHeaderFlags priority_flags)
979 ModestMailOperationPrivate *priv = NULL;
980 SendNewMailInfo *info;
982 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
983 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
985 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
986 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
987 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
988 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
990 /* Check parametters */
992 /* Set status failed and set an error */
993 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
994 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
995 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
996 _("Error trying to send a mail. You need to set at least one recipient"));
999 info = g_slice_new0 (SendNewMailInfo);
1000 info->transport_account = transport_account;
1001 if (transport_account)
1002 g_object_ref (transport_account);
1003 info->draft_msg = draft_msg;
1005 g_object_ref (draft_msg);
1008 modest_mail_operation_notify_start (self);
1009 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1010 attachments_list, images_list, priority_flags,
1011 modest_mail_operation_send_new_mail_cb, info);
1017 TnyTransportAccount *transport_account;
1019 SaveToDraftstCallback callback;
1023 ModestMailOperation *mailop;
1024 } SaveToDraftsAddMsgInfo;
1027 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
1032 ModestMailOperationPrivate *priv = NULL;
1033 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
1035 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1038 g_warning ("%s: priv->error != NULL", __FUNCTION__);
1039 g_error_free(priv->error);
1042 priv->error = (err == NULL) ? NULL : g_error_copy(err);
1044 if ((!priv->error) && (info->draft_msg != NULL)) {
1045 TnyHeader *header = tny_msg_get_header (info->draft_msg);
1046 TnyFolder *src_folder = tny_header_get_folder (header);
1048 /* Remove the old draft */
1049 tny_folder_remove_msg (src_folder, header, NULL);
1051 /* Synchronize to expunge and to update the msg counts */
1052 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1053 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1055 g_object_unref (G_OBJECT(header));
1056 g_object_unref (G_OBJECT(src_folder));
1060 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1062 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1064 /* Call the user callback */
1066 info->callback (info->mailop, info->msg, info->user_data);
1068 if (info->transport_account)
1069 g_object_unref (G_OBJECT(info->transport_account));
1070 if (info->draft_msg)
1071 g_object_unref (G_OBJECT (info->draft_msg));
1073 g_object_unref (G_OBJECT(info->drafts));
1075 g_object_unref (G_OBJECT (info->msg));
1077 modest_mail_operation_notify_end (info->mailop);
1078 g_object_unref(info->mailop);
1079 g_slice_free (SaveToDraftsAddMsgInfo, info);
1084 TnyTransportAccount *transport_account;
1086 SaveToDraftstCallback callback;
1091 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1095 TnyFolder *drafts = NULL;
1096 ModestMailOperationPrivate *priv = NULL;
1097 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1099 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1102 if (!(priv->error)) {
1103 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1104 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1105 "modest: failed to create a new msg\n");
1108 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1109 TNY_FOLDER_TYPE_DRAFTS);
1110 if (!drafts && !(priv->error)) {
1111 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1112 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1113 "modest: failed to create a new msg\n");
1118 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1119 cb_info->transport_account = g_object_ref(info->transport_account);
1120 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1121 cb_info->callback = info->callback;
1122 cb_info->user_data = info->user_data;
1123 cb_info->drafts = g_object_ref(drafts);
1124 cb_info->msg = g_object_ref(msg);
1125 cb_info->mailop = g_object_ref(self);
1126 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1129 /* Call the user callback */
1130 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1132 info->callback (self, msg, info->user_data);
1133 modest_mail_operation_notify_end (self);
1137 g_object_unref (G_OBJECT(drafts));
1138 if (info->draft_msg)
1139 g_object_unref (G_OBJECT (info->draft_msg));
1140 if (info->transport_account)
1141 g_object_unref (G_OBJECT(info->transport_account));
1142 g_slice_free (SaveToDraftsInfo, info);
1146 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1147 TnyTransportAccount *transport_account,
1149 const gchar *from, const gchar *to,
1150 const gchar *cc, const gchar *bcc,
1151 const gchar *subject, const gchar *plain_body,
1152 const gchar *html_body,
1153 const GList *attachments_list,
1154 const GList *images_list,
1155 TnyHeaderFlags priority_flags,
1156 SaveToDraftstCallback callback,
1159 ModestMailOperationPrivate *priv = NULL;
1160 SaveToDraftsInfo *info = NULL;
1162 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1163 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1165 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1167 /* Get account and set it into mail_operation */
1168 priv->account = g_object_ref (transport_account);
1169 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1171 info = g_slice_new0 (SaveToDraftsInfo);
1172 info->transport_account = g_object_ref (transport_account);
1173 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1174 info->callback = callback;
1175 info->user_data = user_data;
1177 modest_mail_operation_notify_start (self);
1178 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1179 attachments_list, images_list, priority_flags,
1180 modest_mail_operation_save_to_drafts_cb, info);
1185 ModestMailOperation *mail_op;
1186 TnyMimePart *mime_part;
1188 GetMimePartSizeCallback callback;
1190 } GetMimePartSizeInfo;
1192 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1193 /* We use this folder observer to track the headers that have been
1194 * added to a folder */
1197 TnyList *new_headers;
1198 } InternalFolderObserver;
1201 GObjectClass parent;
1202 } InternalFolderObserverClass;
1204 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1206 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1207 internal_folder_observer,
1209 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1213 foreach_add_item (gpointer header, gpointer user_data)
1215 tny_list_prepend (TNY_LIST (user_data),
1216 g_object_ref (G_OBJECT (header)));
1219 /* This is the method that looks for new messages in a folder */
1221 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1223 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1225 TnyFolderChangeChanged changed;
1227 changed = tny_folder_change_get_changed (change);
1229 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1232 /* Get added headers */
1233 list = tny_simple_list_new ();
1234 tny_folder_change_get_added_headers (change, list);
1236 /* Add them to the folder observer */
1237 tny_list_foreach (list, foreach_add_item,
1238 derived->new_headers);
1240 g_object_unref (G_OBJECT (list));
1245 internal_folder_observer_init (InternalFolderObserver *self)
1247 self->new_headers = tny_simple_list_new ();
1250 internal_folder_observer_finalize (GObject *object)
1252 InternalFolderObserver *self;
1254 self = (InternalFolderObserver *) object;
1255 g_object_unref (self->new_headers);
1257 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1260 tny_folder_observer_init (TnyFolderObserverIface *iface)
1262 iface->update_func = internal_folder_observer_update;
1265 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1267 GObjectClass *object_class;
1269 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1270 object_class = (GObjectClass*) klass;
1271 object_class->finalize = internal_folder_observer_finalize;
1276 ModestMailOperation *mail_op;
1277 gchar *account_name;
1278 UpdateAccountCallback callback;
1283 TnyFolderObserver *inbox_observer;
1284 RetrieveAllCallback retrieve_all_cb;
1285 } UpdateAccountInfo;
1289 destroy_update_account_info (UpdateAccountInfo *info)
1291 g_free (info->account_name);
1292 g_object_unref (info->folders);
1293 g_object_unref (info->mail_op);
1294 g_slice_free (UpdateAccountInfo, info);
1298 update_account_get_msg_async_cb (TnyFolder *folder,
1304 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1306 /* Just delete the helper. Don't do anything with the new
1307 msg. There is also no need to check for errors */
1308 g_object_unref (msg_info->mail_op);
1309 g_object_unref (msg_info->header);
1310 g_slice_free (GetMsgInfo, msg_info);
1314 guint error_handler;
1316 ModestMailOperation *mail_op;
1317 } UpdateAccountSendQueueFlushInfo;
1320 update_account_finalize (TnySendQueue *queue,
1321 UpdateAccountSendQueueFlushInfo *info)
1323 ModestMailOperationPrivate *priv;
1325 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1328 /* The last one finish the mail operation */
1329 if (priv->done == priv->total) {
1331 modest_mail_operation_notify_end (info->mail_op);
1334 g_object_unref (info->mail_op);
1335 g_signal_handler_disconnect (queue, info->error_handler);
1336 g_signal_handler_disconnect (queue, info->sent_handler);
1337 g_slice_free (UpdateAccountSendQueueFlushInfo, info);
1342 update_account_on_msg_sent_cb (TnySendQueue *queue,
1349 UpdateAccountSendQueueFlushInfo *info;
1350 info = (UpdateAccountSendQueueFlushInfo *) user_data;
1352 update_account_finalize (queue, info);
1356 update_account_on_error_happened_cb (TnySendQueue *queue,
1362 UpdateAccountSendQueueFlushInfo *info;
1363 info = (UpdateAccountSendQueueFlushInfo *) user_data;
1365 update_account_finalize (queue, info);
1370 inbox_refreshed_cb (TnyFolder *inbox,
1375 UpdateAccountInfo *info;
1376 ModestMailOperationPrivate *priv;
1377 TnyIterator *new_headers_iter;
1378 GPtrArray *new_headers_array = NULL;
1379 gint max_size, retrieve_limit, i;
1380 ModestAccountMgr *mgr;
1381 ModestAccountRetrieveType retrieve_type;
1382 TnyList *new_headers = NULL;
1383 gboolean headers_only, ignore_limit;
1384 TnyTransportAccount *transport_account;
1385 gboolean end_operation;
1387 info = (UpdateAccountInfo *) user_data;
1388 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1389 mgr = modest_runtime_get_account_mgr ();
1391 if (canceled || err || !inbox) {
1392 /* Try to send anyway */
1396 /* Get the message max size */
1397 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1398 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1400 max_size = G_MAXINT;
1402 max_size = max_size * KB;
1404 /* Create the new headers array. We need it to sort the
1405 new headers by date */
1406 new_headers_array = g_ptr_array_new ();
1407 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1408 while (!tny_iterator_is_done (new_headers_iter)) {
1409 TnyHeader *header = NULL;
1411 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1412 /* Apply per-message size limits */
1413 if (tny_header_get_message_size (header) < max_size)
1414 g_ptr_array_add (new_headers_array, g_object_ref (header));
1416 g_object_unref (header);
1417 tny_iterator_next (new_headers_iter);
1419 g_object_unref (new_headers_iter);
1420 tny_folder_remove_observer (inbox, info->inbox_observer);
1421 g_object_unref (info->inbox_observer);
1422 info->inbox_observer = NULL;
1424 /* Update the last updated key, even if we don't have to get new headers */
1425 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1427 if (new_headers_array->len == 0)
1430 /* Get per-account message amount retrieval limit */
1431 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1432 if (retrieve_limit == 0)
1433 retrieve_limit = G_MAXINT;
1435 /* Get per-account retrieval type */
1436 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1437 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1440 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1442 /* Ask the users if they want to retrieve all the messages
1443 even though the limit was exceeded */
1444 ignore_limit = FALSE;
1445 if (new_headers_array->len > retrieve_limit) {
1446 /* Ask the user if a callback has been specified and
1447 if the mail operation has a source (this means that
1448 was invoked by the user and not automatically by a
1450 if (info->retrieve_all_cb && priv->source)
1451 ignore_limit = info->retrieve_all_cb (priv->source,
1452 new_headers_array->len,
1456 if (!headers_only) {
1458 const gint msg_list_size = compute_message_array_size (new_headers_array);
1462 priv->total = new_headers_array->len;
1464 priv->total = MIN (new_headers_array->len, retrieve_limit);
1465 while (msg_num < priv->total) {
1466 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1467 TnyFolder *folder = tny_header_get_folder (header);
1468 GetMsgInfo *msg_info;
1470 /* Create the message info */
1471 msg_info = g_slice_new0 (GetMsgInfo);
1472 msg_info->mail_op = g_object_ref (info->mail_op);
1473 msg_info->header = g_object_ref (header);
1474 msg_info->total_bytes = msg_list_size;
1476 /* Get message in an async way */
1477 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1478 get_msg_status_cb, msg_info);
1480 g_object_unref (folder);
1486 /* Copy the headers to a list and free the array */
1487 new_headers = tny_simple_list_new ();
1488 for (i=0; i < new_headers_array->len; i++) {
1489 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1490 tny_list_append (new_headers, G_OBJECT (header));
1492 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1493 g_ptr_array_free (new_headers_array, FALSE);
1496 /* Get the transport account */
1497 transport_account = (TnyTransportAccount *)
1498 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1499 info->account_name);
1501 if (transport_account) {
1502 ModestTnySendQueue *send_queue;
1506 send_queue = modest_runtime_get_send_queue (transport_account);
1508 /* Get outbox folder */
1509 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1510 num_messages = tny_folder_get_all_count (outbox);
1511 g_object_unref (outbox);
1513 if (num_messages == 0) {
1514 end_operation = TRUE;
1516 UpdateAccountSendQueueFlushInfo *send_info;
1518 end_operation = FALSE;
1521 priv->total = num_messages;
1522 g_object_unref (priv->account);
1523 priv->account = TNY_ACCOUNT (transport_account);
1525 /* Create the info object */
1526 send_info = g_slice_new (UpdateAccountSendQueueFlushInfo);
1527 send_info->error_handler = g_signal_connect (send_queue, "error-happened",
1528 G_CALLBACK (update_account_on_error_happened_cb),
1530 send_info->sent_handler = g_signal_connect (send_queue, "msg-sent",
1531 G_CALLBACK (update_account_on_msg_sent_cb),
1533 send_info->mail_op = g_object_ref (info->mail_op);
1535 /* Reenable suspended items */
1536 modest_tny_send_queue_wakeup (MODEST_TNY_SEND_QUEUE (send_queue));
1539 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (send_queue));
1542 end_operation = TRUE;
1545 /* Check if the operation was a success */
1547 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1549 /* Set the account back to not busy */
1550 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1552 /* Call the user callback */
1554 info->callback (info->mail_op, new_headers, info->user_data);
1556 /* Notify about operation end */
1558 modest_mail_operation_notify_end (info->mail_op);
1562 g_object_unref (new_headers);
1563 destroy_update_account_info (info);
1567 recurse_folders_async_cb (TnyFolderStore *folder_store,
1573 UpdateAccountInfo *info;
1574 ModestMailOperationPrivate *priv;
1576 info = (UpdateAccountInfo *) user_data;
1577 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1579 if (err || canceled) {
1580 /* Try to continue anyway */
1582 TnyIterator *iter = tny_list_create_iterator (list);
1583 while (!tny_iterator_is_done (iter)) {
1584 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1585 TnyList *folders = tny_simple_list_new ();
1587 /* Add to the list of all folders */
1588 tny_list_append (info->folders, (GObject *) folder);
1590 /* Add pending call */
1591 info->pending_calls++;
1593 tny_folder_store_get_folders_async (folder, folders, NULL,
1594 recurse_folders_async_cb,
1597 g_object_unref (G_OBJECT (folder));
1599 tny_iterator_next (iter);
1601 g_object_unref (G_OBJECT (iter));
1602 g_object_unref (G_OBJECT (list));
1605 /* Remove my own pending call */
1606 info->pending_calls--;
1608 /* This means that we have all the folders */
1609 if (info->pending_calls == 0) {
1610 TnyIterator *iter_all_folders;
1611 TnyFolder *inbox = NULL;
1613 iter_all_folders = tny_list_create_iterator (info->folders);
1615 /* Do a poke status over all folders */
1616 while (!tny_iterator_is_done (iter_all_folders) &&
1617 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1618 TnyFolder *folder = NULL;
1620 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1622 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1623 /* Get a reference to the INBOX */
1624 inbox = g_object_ref (folder);
1626 /* Issue a poke status over the folder */
1628 tny_folder_poke_status (folder);
1631 /* Free and go to next */
1632 g_object_unref (folder);
1633 tny_iterator_next (iter_all_folders);
1635 g_object_unref (iter_all_folders);
1637 /* Refresh the INBOX */
1639 /* Refresh the folder. Our observer receives
1640 * the new emails during folder refreshes, so
1641 * we can use observer->new_headers
1643 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1644 tny_folder_add_observer (inbox, info->inbox_observer);
1646 /* Refresh the INBOX */
1647 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1648 g_object_unref (inbox);
1650 /* We could not perform the inbox refresh but
1651 we'll try to send mails anyway */
1652 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1658 modest_mail_operation_update_account (ModestMailOperation *self,
1659 const gchar *account_name,
1661 RetrieveAllCallback retrieve_all_cb,
1662 UpdateAccountCallback callback,
1665 UpdateAccountInfo *info = NULL;
1666 ModestMailOperationPrivate *priv = NULL;
1667 ModestTnyAccountStore *account_store = NULL;
1668 TnyStoreAccount *store_account = NULL;
1670 ModestMailOperationState *state;
1672 /* Init mail operation */
1673 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1676 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1677 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1679 /* Get the store account */
1680 account_store = modest_runtime_get_account_store ();
1681 store_account = (TnyStoreAccount *)
1682 modest_tny_account_store_get_server_account (account_store,
1684 TNY_ACCOUNT_TYPE_STORE);
1685 priv->account = g_object_ref (store_account);
1687 /* Create the helper object */
1688 info = g_slice_new0 (UpdateAccountInfo);
1689 info->pending_calls = 1;
1690 info->folders = tny_simple_list_new ();
1691 info->mail_op = g_object_ref (self);
1692 info->poke_all = poke_all;
1693 info->account_name = g_strdup (account_name);
1694 info->callback = callback;
1695 info->user_data = user_data;
1696 info->retrieve_all_cb = retrieve_all_cb;
1698 /* Set account busy */
1699 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1700 modest_mail_operation_notify_start (self);
1702 /* notify about the start of the operation */
1703 state = modest_mail_operation_clone_state (self);
1707 /* Start notifying progress */
1708 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1709 g_slice_free (ModestMailOperationState, state);
1711 /* Get all folders and continue in the callback */
1712 folders = tny_simple_list_new ();
1713 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1715 recurse_folders_async_cb,
1720 * Used to notify the queue from the main
1721 * loop. We call it inside an idle call to achieve that
1724 idle_notify_queue (gpointer data)
1726 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1728 gdk_threads_enter ();
1729 modest_mail_operation_notify_end (mail_op);
1730 gdk_threads_leave ();
1731 g_object_unref (mail_op);
1737 compare_headers_by_date (gconstpointer a,
1740 TnyHeader **header1, **header2;
1741 time_t sent1, sent2;
1743 header1 = (TnyHeader **) a;
1744 header2 = (TnyHeader **) b;
1746 sent1 = tny_header_get_date_sent (*header1);
1747 sent2 = tny_header_get_date_sent (*header2);
1749 /* We want the most recent ones (greater time_t) at the
1758 /* ******************************************************************* */
1759 /* ************************** STORE ACTIONS ************************* */
1760 /* ******************************************************************* */
1763 ModestMailOperation *mail_op;
1764 CreateFolderUserCallback callback;
1770 create_folder_cb (TnyFolderStore *parent_folder,
1772 TnyFolder *new_folder,
1776 ModestMailOperationPrivate *priv;
1777 CreateFolderInfo *info;
1779 info = (CreateFolderInfo *) user_data;
1780 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1782 if (canceled || err) {
1783 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1785 priv->error = g_error_copy (err);
1787 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1788 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1791 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1794 /* The user will unref the new_folder */
1796 info->callback (info->mail_op, parent_folder,
1797 new_folder, info->user_data);
1799 /* Notify about operation end */
1800 modest_mail_operation_notify_end (info->mail_op);
1803 g_object_unref (info->mail_op);
1804 g_slice_free (CreateFolderInfo, info);
1808 modest_mail_operation_create_folder (ModestMailOperation *self,
1809 TnyFolderStore *parent,
1811 CreateFolderUserCallback callback,
1814 ModestMailOperationPrivate *priv;
1816 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1817 g_return_if_fail (name);
1819 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1820 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1821 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1822 g_object_ref (parent) :
1823 modest_tny_folder_get_account (TNY_FOLDER (parent));
1825 /* Check for already existing folder */
1826 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1827 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1828 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1829 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1830 _CS("ckdg_ib_folder_already_exists"));
1834 if (TNY_IS_FOLDER (parent)) {
1835 /* Check folder rules */
1836 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1837 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1838 /* Set status failed and set an error */
1839 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1840 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1841 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1842 _("mail_in_ui_folder_create_error"));
1846 if (!strcmp (name, " ") || strchr (name, '/')) {
1847 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1848 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1849 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1850 _("mail_in_ui_folder_create_error"));
1854 CreateFolderInfo *info;
1856 info = g_slice_new0 (CreateFolderInfo);
1857 info->mail_op = g_object_ref (self);
1858 info->callback = callback;
1859 info->user_data = user_data;
1861 modest_mail_operation_notify_start (self);
1863 /* Create the folder */
1864 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1867 /* Call the user callback anyway */
1869 callback (self, parent, NULL, user_data);
1870 /* Notify about operation end */
1871 modest_mail_operation_notify_end (self);
1876 modest_mail_operation_remove_folder (ModestMailOperation *self,
1878 gboolean remove_to_trash)
1880 TnyAccount *account;
1881 ModestMailOperationPrivate *priv;
1882 ModestTnyFolderRules rules;
1884 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1885 g_return_if_fail (TNY_IS_FOLDER (folder));
1887 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1889 /* Check folder rules */
1890 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1891 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1892 /* Set status failed and set an error */
1893 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1894 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1895 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1896 _("mail_in_ui_folder_delete_error"));
1900 /* Get the account */
1901 account = modest_tny_folder_get_account (folder);
1902 priv->account = g_object_ref(account);
1903 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1905 /* Delete folder or move to trash */
1906 if (remove_to_trash) {
1907 TnyFolder *trash_folder = NULL;
1908 trash_folder = modest_tny_account_get_special_folder (account,
1909 TNY_FOLDER_TYPE_TRASH);
1910 /* TODO: error_handling */
1912 modest_mail_operation_notify_start (self);
1913 modest_mail_operation_xfer_folder (self, folder,
1914 TNY_FOLDER_STORE (trash_folder),
1916 g_object_unref (trash_folder);
1918 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1921 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1923 modest_mail_operation_notify_start (self);
1924 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1925 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1928 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1930 g_object_unref (parent);
1932 g_warning ("%s: could not get parent folder", __FUNCTION__);
1934 g_object_unref (G_OBJECT (account));
1937 /* Notify about operation end */
1938 modest_mail_operation_notify_end (self);
1942 transfer_folder_status_cb (GObject *obj,
1946 ModestMailOperation *self;
1947 ModestMailOperationPrivate *priv;
1948 ModestMailOperationState *state;
1949 XFerFolderAsyncHelper *helper;
1951 g_return_if_fail (status != NULL);
1952 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1954 helper = (XFerFolderAsyncHelper *) user_data;
1955 g_return_if_fail (helper != NULL);
1957 self = helper->mail_op;
1958 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1960 priv->done = status->position;
1961 priv->total = status->of_total;
1963 state = modest_mail_operation_clone_state (self);
1965 /* This is not a GDK lock because we are a Tinymail callback
1966 * which is already GDK locked by Tinymail */
1968 /* no gdk_threads_enter (), CHECKED */
1970 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1972 /* no gdk_threads_leave (), CHECKED */
1974 g_slice_free (ModestMailOperationState, state);
1979 transfer_folder_cb (TnyFolder *folder,
1981 TnyFolderStore *into,
1982 TnyFolder *new_folder,
1986 XFerFolderAsyncHelper *helper;
1987 ModestMailOperation *self = NULL;
1988 ModestMailOperationPrivate *priv = NULL;
1990 helper = (XFerFolderAsyncHelper *) user_data;
1991 g_return_if_fail (helper != NULL);
1993 self = helper->mail_op;
1994 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1997 priv->error = g_error_copy (err);
1999 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2000 } else if (cancelled) {
2001 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2002 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2003 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2004 _("Transference of %s was cancelled."),
2005 tny_folder_get_name (folder));
2008 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2011 /* Notify about operation end */
2012 modest_mail_operation_notify_end (self);
2014 /* If user defined callback function was defined, call it */
2015 if (helper->user_callback) {
2017 /* This is not a GDK lock because we are a Tinymail callback
2018 * which is already GDK locked by Tinymail */
2020 /* no gdk_threads_enter (), CHECKED */
2021 helper->user_callback (self, new_folder, helper->user_data);
2022 /* no gdk_threads_leave () , CHECKED */
2026 g_object_unref (helper->mail_op);
2027 g_slice_free (XFerFolderAsyncHelper, helper);
2032 * This function checks if the new name is a valid name for our local
2033 * folders account. The new name could not be the same than then name
2034 * of any of the mandatory local folders
2036 * We can not rely on tinymail because tinymail does not check the
2037 * name of the virtual folders that the account could have in the case
2038 * that we're doing a rename (because it directly calls Camel which
2039 * knows nothing about our virtual folders).
2041 * In the case of an actual copy/move (i.e. move/copy a folder between
2042 * accounts) tinymail uses the tny_folder_store_create_account which
2043 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
2044 * checks the new name of the folder, so this call in that case
2045 * wouldn't be needed. *But* NOTE that if tinymail changes its
2046 * implementation (if folder transfers within the same account is no
2047 * longer implemented as a rename) this call will allow Modest to work
2050 * If the new name is not valid, this function will set the status to
2051 * failed and will set also an error in the mail operation
2054 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
2055 TnyFolderStore *into,
2056 const gchar *new_name)
2058 if (TNY_IS_ACCOUNT (into) &&
2059 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
2060 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
2062 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2063 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2064 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2065 _CS("ckdg_ib_folder_already_exists"));
2072 modest_mail_operation_xfer_folder (ModestMailOperation *self,
2074 TnyFolderStore *parent,
2075 gboolean delete_original,
2076 XferFolderAsyncUserCallback user_callback,
2079 ModestMailOperationPrivate *priv = NULL;
2080 ModestTnyFolderRules parent_rules = 0, rules;
2081 XFerFolderAsyncHelper *helper = NULL;
2082 const gchar *folder_name = NULL;
2083 const gchar *error_msg;
2085 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2086 g_return_if_fail (TNY_IS_FOLDER (folder));
2087 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2089 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2090 folder_name = tny_folder_get_name (folder);
2092 /* Set the error msg */
2093 error_msg = _("mail_in_ui_folder_move_target_error");
2095 /* Get account and set it into mail_operation */
2096 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2097 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2098 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2100 /* Get folder rules */
2101 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2102 if (TNY_IS_FOLDER (parent))
2103 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2105 /* Apply operation constraints */
2106 if ((gpointer) parent == (gpointer) folder ||
2107 (!TNY_IS_FOLDER_STORE (parent)) ||
2108 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
2111 } else if (TNY_IS_FOLDER (parent) &&
2112 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2116 } else if (TNY_IS_FOLDER (parent) &&
2117 TNY_IS_FOLDER_STORE (folder) &&
2118 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2119 TNY_FOLDER_STORE (folder))) {
2120 /* Do not move a parent into a child */
2122 } else if (TNY_IS_FOLDER_STORE (parent) &&
2123 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2124 /* Check that the new folder name is not used by any
2127 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2128 /* Check that the new folder name is not used by any
2129 special local folder */
2132 /* Create the helper */
2133 helper = g_slice_new0 (XFerFolderAsyncHelper);
2134 helper->mail_op = g_object_ref (self);
2135 helper->user_callback = user_callback;
2136 helper->user_data = user_data;
2138 /* Move/Copy folder */
2139 modest_mail_operation_notify_start (self);
2140 tny_folder_copy_async (folder,
2142 tny_folder_get_name (folder),
2145 transfer_folder_status_cb,
2151 /* Set status failed and set an error */
2152 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2153 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2154 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2157 /* Call the user callback if exists */
2159 user_callback (self, NULL, user_data);
2161 /* Notify the queue */
2162 modest_mail_operation_notify_end (self);
2166 modest_mail_operation_rename_folder (ModestMailOperation *self,
2169 XferFolderAsyncUserCallback user_callback,
2172 ModestMailOperationPrivate *priv;
2173 ModestTnyFolderRules rules;
2174 XFerFolderAsyncHelper *helper;
2176 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2177 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2178 g_return_if_fail (name);
2180 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2182 /* Get account and set it into mail_operation */
2183 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2184 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2186 /* Check folder rules */
2187 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2188 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2190 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2193 TnyFolderStore *into;
2195 into = tny_folder_get_folder_store (folder);
2197 /* Check that the new folder name is not used by any
2198 special local folder */
2199 if (new_name_valid_if_local_account (priv, into, name)) {
2200 /* Create the helper */
2201 helper = g_slice_new0 (XFerFolderAsyncHelper);
2202 helper->mail_op = g_object_ref(self);
2203 helper->user_callback = user_callback;
2204 helper->user_data = user_data;
2206 /* Rename. Camel handles folder subscription/unsubscription */
2207 modest_mail_operation_notify_start (self);
2208 tny_folder_copy_async (folder, into, name, TRUE,
2210 transfer_folder_status_cb,
2215 g_object_unref (into);
2220 /* Set status failed and set an error */
2221 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2222 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2223 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2224 _("FIXME: unable to rename"));
2227 user_callback (self, NULL, user_data);
2229 /* Notify about operation end */
2230 modest_mail_operation_notify_end (self);
2233 /* ******************************************************************* */
2234 /* ************************** MSG ACTIONS ************************* */
2235 /* ******************************************************************* */
2238 modest_mail_operation_get_msg (ModestMailOperation *self,
2240 GetMsgAsyncUserCallback user_callback,
2243 GetMsgInfo *helper = NULL;
2245 ModestMailOperationPrivate *priv;
2247 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2248 g_return_if_fail (TNY_IS_HEADER (header));
2250 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2251 folder = tny_header_get_folder (header);
2253 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2257 /* Get account and set it into mail_operation */
2258 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2260 /* Check for cached messages */
2261 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2262 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2264 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2266 /* Create the helper */
2267 helper = g_slice_new0 (GetMsgInfo);
2268 helper->header = g_object_ref (header);
2269 helper->mail_op = g_object_ref (self);
2270 helper->user_callback = user_callback;
2271 helper->user_data = user_data;
2272 helper->destroy_notify = NULL;
2273 helper->last_total_bytes = 0;
2274 helper->sum_total_bytes = 0;
2275 helper->total_bytes = tny_header_get_message_size (header);
2277 modest_mail_operation_notify_start (self);
2279 /* notify about the start of the operation */
2280 ModestMailOperationState *state;
2281 state = modest_mail_operation_clone_state (self);
2284 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2287 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2289 g_object_unref (G_OBJECT (folder));
2293 get_msg_status_cb (GObject *obj,
2297 GetMsgInfo *helper = NULL;
2299 g_return_if_fail (status != NULL);
2300 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2302 helper = (GetMsgInfo *) user_data;
2303 g_return_if_fail (helper != NULL);
2305 /* Notify progress */
2306 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2307 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2311 get_msg_async_cb (TnyFolder *folder,
2317 GetMsgInfo *info = NULL;
2318 ModestMailOperationPrivate *priv = NULL;
2321 info = (GetMsgInfo *) user_data;
2323 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2325 finished = (priv->done == priv->total) ? TRUE : FALSE;
2328 if (canceled || err) {
2329 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2331 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2332 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2335 /* Set the success status before calling the user callback */
2336 if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2337 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2341 /* Call the user callback */
2342 if (info->user_callback)
2343 info->user_callback (info->mail_op, info->header, canceled,
2344 msg, err, info->user_data);
2346 /* Notify about operation end if this is the last callback */
2348 /* Free user data */
2349 if (info->destroy_notify)
2350 info->destroy_notify (info->user_data);
2352 /* Notify about operation end */
2353 modest_mail_operation_notify_end (info->mail_op);
2357 g_object_unref (info->header);
2358 g_object_unref (info->mail_op);
2359 g_slice_free (GetMsgInfo, info);
2363 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2364 TnyList *header_list,
2365 GetMsgAsyncUserCallback user_callback,
2367 GDestroyNotify notify)
2369 ModestMailOperationPrivate *priv = NULL;
2371 TnyIterator *iter = NULL;
2373 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2375 /* Init mail operation */
2376 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2377 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2378 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2380 priv->total = tny_list_get_length(header_list);
2382 /* Get account and set it into mail_operation */
2383 if (tny_list_get_length (header_list) >= 1) {
2384 iter = tny_list_create_iterator (header_list);
2385 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2387 TnyFolder *folder = tny_header_get_folder (header);
2389 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2390 g_object_unref (folder);
2392 g_object_unref (header);
2395 if (tny_list_get_length (header_list) == 1) {
2396 g_object_unref (iter);
2401 msg_list_size = compute_message_list_size (header_list);
2403 modest_mail_operation_notify_start (self);
2404 iter = tny_list_create_iterator (header_list);
2405 while (!tny_iterator_is_done (iter)) {
2406 /* notify about the start of the operation */
2407 ModestMailOperationState *state;
2408 state = modest_mail_operation_clone_state (self);
2411 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2414 GetMsgInfo *msg_info = NULL;
2415 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2416 TnyFolder *folder = tny_header_get_folder (header);
2418 /* Create the message info */
2419 msg_info = g_slice_new0 (GetMsgInfo);
2420 msg_info->mail_op = g_object_ref (self);
2421 msg_info->header = g_object_ref (header);
2422 msg_info->user_callback = user_callback;
2423 msg_info->user_data = user_data;
2424 msg_info->destroy_notify = notify;
2425 msg_info->last_total_bytes = 0;
2426 msg_info->sum_total_bytes = 0;
2427 msg_info->total_bytes = msg_list_size;
2429 /* The callback will call it per each header */
2430 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2432 /* Free and go on */
2433 g_object_unref (header);
2434 g_object_unref (folder);
2435 tny_iterator_next (iter);
2437 g_object_unref (iter);
2442 modest_mail_operation_remove_msg (ModestMailOperation *self,
2444 gboolean remove_to_trash /*ignored*/)
2447 ModestMailOperationPrivate *priv;
2449 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2450 g_return_if_fail (TNY_IS_HEADER (header));
2452 if (remove_to_trash)
2453 g_warning ("remove to trash is not implemented");
2455 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2456 folder = tny_header_get_folder (header);
2458 /* Get account and set it into mail_operation */
2459 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2460 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2461 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2463 /* remove message from folder */
2464 tny_folder_remove_msg (folder, header, &(priv->error));
2466 gboolean expunge, leave_on_server;
2467 const gchar *account_name;
2468 TnyAccount *account;
2469 ModestTransportStoreProtocol account_proto;
2471 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2472 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2474 modest_mail_operation_notify_start (self);
2476 /* Get leave on server setting */
2477 account = tny_folder_get_account (folder);
2478 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2480 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2483 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2485 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2486 modest_tny_folder_is_remote_folder (folder) == FALSE)
2492 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2495 g_object_unref (account);
2501 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2503 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2506 g_object_unref (G_OBJECT (folder));
2508 /* Notify about operation end */
2509 modest_mail_operation_notify_end (self);
2513 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2515 gboolean remove_to_trash /*ignored*/)
2517 TnyFolder *folder = NULL;
2518 ModestMailOperationPrivate *priv;
2519 TnyIterator *iter = NULL;
2520 TnyHeader *header = NULL;
2521 TnyList *remove_headers = NULL;
2522 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2524 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2525 g_return_if_fail (TNY_IS_LIST (headers));
2527 if (remove_to_trash)
2528 g_warning ("remove to trash is not implemented");
2530 if (tny_list_get_length(headers) == 0) {
2531 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2532 goto cleanup; /* nothing to do */
2535 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2536 remove_headers = g_object_ref(headers);
2538 /* Get folder from first header and sync it */
2539 iter = tny_list_create_iterator (headers);
2540 header = TNY_HEADER (tny_iterator_get_current (iter));
2542 folder = tny_header_get_folder (header);
2543 if (!TNY_IS_FOLDER(folder)) {
2544 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2548 /* Don't remove messages that are being sent */
2549 if (modest_tny_folder_is_local_folder (folder)) {
2550 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2552 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2553 TnyTransportAccount *traccount = NULL;
2554 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2555 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2557 ModestTnySendQueueStatus status;
2558 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2559 TnyIterator *iter = tny_list_create_iterator(headers);
2560 g_object_unref(remove_headers);
2561 remove_headers = TNY_LIST(tny_simple_list_new());
2562 while (!tny_iterator_is_done(iter)) {
2564 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2565 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2566 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2567 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2568 tny_list_append(remove_headers, G_OBJECT(hdr));
2570 g_object_unref(hdr);
2572 tny_iterator_next(iter);
2574 g_object_unref(iter);
2575 g_object_unref(traccount);
2579 /* Get account and set it into mail_operation */
2580 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2581 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2582 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2584 /* remove message from folder */
2585 modest_mail_operation_notify_start (self);
2587 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2589 gboolean expunge, leave_on_server;
2590 const gchar *account_name;
2592 TnyAccount *account;
2593 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2595 account = tny_folder_get_account (folder);
2596 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2598 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2601 proto = tny_account_get_proto (account);
2603 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2606 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2607 modest_tny_folder_is_remote_folder (folder) == FALSE)
2613 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2615 g_object_unref (account);
2621 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2623 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2628 g_object_unref (remove_headers);
2630 g_object_unref (header);
2632 g_object_unref (iter);
2634 g_object_unref (folder);
2636 /* Notify about operation end */
2637 modest_mail_operation_notify_end (self);
2641 notify_progress_of_multiple_messages (ModestMailOperation *self,
2643 gint *last_total_bytes,
2644 gint *sum_total_bytes,
2646 gboolean increment_done)
2648 ModestMailOperationPrivate *priv;
2649 ModestMailOperationState *state;
2650 gboolean is_num_bytes = FALSE;
2652 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2654 /* We know that tinymail sends us information about
2655 * transferred bytes with this particular message
2657 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2658 * I just added the 'if' so we don't get runtime warning)
2660 if (status->message)
2661 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2663 state = modest_mail_operation_clone_state (self);
2664 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2665 /* We know that we're in a different message when the
2666 total number of bytes to transfer is different. Of
2667 course it could fail if we're transferring messages
2668 of the same size, but this is a workarround */
2669 if (status->of_total != *last_total_bytes) {
2670 /* We need to increment the done when there is
2671 no information about each individual
2672 message, we need to do this in message
2673 transfers, and we don't do it for getting
2677 *sum_total_bytes += *last_total_bytes;
2678 *last_total_bytes = status->of_total;
2680 state->bytes_done += status->position + *sum_total_bytes;
2681 state->bytes_total = total_bytes;
2683 /* Notify the status change. Only notify about changes
2684 referred to bytes */
2685 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2689 g_slice_free (ModestMailOperationState, state);
2693 transfer_msgs_status_cb (GObject *obj,
2697 XFerMsgsAsyncHelper *helper;
2699 g_return_if_fail (status != NULL);
2700 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2702 helper = (XFerMsgsAsyncHelper *) user_data;
2703 g_return_if_fail (helper != NULL);
2705 /* Notify progress */
2706 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2707 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2712 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2714 XFerMsgsAsyncHelper *helper;
2715 ModestMailOperation *self;
2716 ModestMailOperationPrivate *priv;
2717 TnyIterator *iter = NULL;
2718 TnyHeader *header = NULL;
2720 helper = (XFerMsgsAsyncHelper *) user_data;
2721 self = helper->mail_op;
2723 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2726 priv->error = g_error_copy (err);
2728 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2729 } else if (cancelled) {
2730 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2731 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2732 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2733 _("Error trying to refresh the contents of %s"),
2734 tny_folder_get_name (folder));
2737 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2739 /* Update folder counts */
2740 tny_folder_poke_status (folder);
2741 tny_folder_poke_status (helper->dest_folder);
2745 /* Mark headers as deleted and seen */
2746 if ((helper->delete) &&
2747 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2748 iter = tny_list_create_iterator (helper->headers);
2749 while (!tny_iterator_is_done (iter)) {
2750 header = TNY_HEADER (tny_iterator_get_current (iter));
2751 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2752 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2753 g_object_unref (header);
2755 tny_iterator_next (iter);
2760 /* Notify about operation end */
2761 modest_mail_operation_notify_end (self);
2763 /* If user defined callback function was defined, call it */
2764 if (helper->user_callback) {
2765 /* This is not a GDK lock because we are a Tinymail callback and
2766 * Tinymail already acquires the Gdk lock */
2768 /* no gdk_threads_enter (), CHECKED */
2769 helper->user_callback (self, helper->user_data);
2770 /* no gdk_threads_leave (), CHECKED */
2774 if (helper->headers)
2775 g_object_unref (helper->headers);
2776 if (helper->dest_folder)
2777 g_object_unref (helper->dest_folder);
2778 if (helper->mail_op)
2779 g_object_unref (helper->mail_op);
2781 g_object_unref (folder);
2783 g_object_unref (iter);
2784 g_slice_free (XFerMsgsAsyncHelper, helper);
2788 compute_message_list_size (TnyList *headers)
2793 iter = tny_list_create_iterator (headers);
2794 while (!tny_iterator_is_done (iter)) {
2795 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2796 size += tny_header_get_message_size (header);
2797 g_object_unref (header);
2798 tny_iterator_next (iter);
2800 g_object_unref (iter);
2806 compute_message_array_size (GPtrArray *headers)
2811 for (i = 0; i < headers->len; i++) {
2812 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2813 size += tny_header_get_message_size (header);
2821 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2824 gboolean delete_original,
2825 XferMsgsAsyncUserCallback user_callback,
2828 ModestMailOperationPrivate *priv = NULL;
2829 TnyIterator *iter = NULL;
2830 TnyFolder *src_folder = NULL;
2831 XFerMsgsAsyncHelper *helper = NULL;
2832 TnyHeader *header = NULL;
2833 ModestTnyFolderRules rules = 0;
2835 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2836 g_return_if_fail (headers && TNY_IS_LIST (headers));
2837 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2839 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2840 priv->total = tny_list_get_length (headers);
2842 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2843 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2845 /* Apply folder rules */
2846 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2847 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2848 /* Set status failed and set an error */
2849 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2850 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2851 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2852 _CS("ckct_ib_unable_to_paste_here"));
2853 /* Notify the queue */
2854 modest_mail_operation_notify_end (self);
2858 /* Get source folder */
2859 iter = tny_list_create_iterator (headers);
2860 header = TNY_HEADER (tny_iterator_get_current (iter));
2862 src_folder = tny_header_get_folder (header);
2863 g_object_unref (header);
2865 g_object_unref (iter);
2867 if (src_folder == NULL) {
2868 /* Notify the queue */
2869 modest_mail_operation_notify_end (self);
2871 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2876 /* Check folder source and destination */
2877 if (src_folder == folder) {
2878 /* Set status failed and set an error */
2879 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2880 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2881 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2882 _("mail_in_ui_folder_copy_target_error"));
2884 /* Notify the queue */
2885 modest_mail_operation_notify_end (self);
2888 g_object_unref (src_folder);
2892 /* Create the helper */
2893 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2894 helper->mail_op = g_object_ref(self);
2895 helper->dest_folder = g_object_ref(folder);
2896 helper->headers = g_object_ref(headers);
2897 helper->user_callback = user_callback;
2898 helper->user_data = user_data;
2899 helper->delete = delete_original;
2900 helper->last_total_bytes = 0;
2901 helper->sum_total_bytes = 0;
2902 helper->total_bytes = compute_message_list_size (headers);
2904 /* Get account and set it into mail_operation */
2905 priv->account = modest_tny_folder_get_account (src_folder);
2907 /* Transfer messages */
2908 modest_mail_operation_notify_start (self);
2909 tny_folder_transfer_msgs_async (src_folder,
2914 transfer_msgs_status_cb,
2920 on_refresh_folder (TnyFolder *folder,
2925 RefreshAsyncHelper *helper = NULL;
2926 ModestMailOperation *self = NULL;
2927 ModestMailOperationPrivate *priv = NULL;
2929 helper = (RefreshAsyncHelper *) user_data;
2930 self = helper->mail_op;
2931 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2933 g_return_if_fail(priv!=NULL);
2936 priv->error = g_error_copy (error);
2937 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2942 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2943 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2944 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2945 _("Error trying to refresh the contents of %s"),
2946 tny_folder_get_name (folder));
2950 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2953 /* Call user defined callback, if it exists */
2954 if (helper->user_callback) {
2956 /* This is not a GDK lock because we are a Tinymail callback and
2957 * Tinymail already acquires the Gdk lock */
2958 helper->user_callback (self, folder, helper->user_data);
2962 g_slice_free (RefreshAsyncHelper, helper);
2964 /* Notify about operation end */
2965 modest_mail_operation_notify_end (self);
2966 g_object_unref(self);
2970 on_refresh_folder_status_update (GObject *obj,
2974 RefreshAsyncHelper *helper = NULL;
2975 ModestMailOperation *self = NULL;
2976 ModestMailOperationPrivate *priv = NULL;
2977 ModestMailOperationState *state;
2979 g_return_if_fail (user_data != NULL);
2980 g_return_if_fail (status != NULL);
2981 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2983 helper = (RefreshAsyncHelper *) user_data;
2984 self = helper->mail_op;
2985 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2987 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2989 priv->done = status->position;
2990 priv->total = status->of_total;
2992 state = modest_mail_operation_clone_state (self);
2994 /* This is not a GDK lock because we are a Tinymail callback and
2995 * Tinymail already acquires the Gdk lock */
2996 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2998 g_slice_free (ModestMailOperationState, state);
3002 modest_mail_operation_refresh_folder (ModestMailOperation *self,
3004 RefreshAsyncUserCallback user_callback,
3007 ModestMailOperationPrivate *priv = NULL;
3008 RefreshAsyncHelper *helper = NULL;
3010 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3012 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3014 /* Get account and set it into mail_operation */
3015 priv->account = modest_tny_folder_get_account (folder);
3016 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3018 /* Create the helper */
3019 helper = g_slice_new0 (RefreshAsyncHelper);
3020 helper->mail_op = g_object_ref(self);
3021 helper->user_callback = user_callback;
3022 helper->user_data = user_data;
3024 /* Refresh the folder. TODO: tinymail could issue a status
3025 updates before the callback call then this could happen. We
3026 must review the design */
3027 modest_mail_operation_notify_start (self);
3029 /* notify that the operation was started */
3030 ModestMailOperationState *state;
3031 state = modest_mail_operation_clone_state (self);
3034 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3037 tny_folder_refresh_async (folder,
3039 on_refresh_folder_status_update,
3045 modest_mail_operation_notify_start (ModestMailOperation *self)
3047 ModestMailOperationPrivate *priv = NULL;
3049 g_return_if_fail (self);
3051 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3053 /* Ensure that all the fields are filled correctly */
3054 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
3056 /* Notify the observers about the mail operation. We do not
3057 wrapp this emission because we assume that this function is
3058 always called from within the main lock */
3059 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
3064 * It's used by the mail operation queue to notify the observers
3065 * attached to that signal that the operation finished. We need to use
3066 * that because tinymail does not give us the progress of a given
3067 * operation when it finishes (it directly calls the operation
3071 modest_mail_operation_notify_end (ModestMailOperation *self)
3073 ModestMailOperationPrivate *priv = NULL;
3075 g_return_if_fail (self);
3077 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3079 /* Notify the observers about the mail operation end. We do
3080 not wrapp this emission because we assume that this
3081 function is always called from within the main lock */
3082 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3084 /* Remove the error user data */
3085 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3086 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3090 modest_mail_operation_get_account (ModestMailOperation *self)
3092 ModestMailOperationPrivate *priv = NULL;
3094 g_return_val_if_fail (self, NULL);
3096 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3098 return (priv->account) ? g_object_ref (priv->account) : NULL;
3102 modest_mail_operation_noop (ModestMailOperation *self)
3104 ModestMailOperationPrivate *priv = NULL;
3106 g_return_if_fail (self);
3108 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3109 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3110 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3114 /* This mail operation does nothing actually */
3115 modest_mail_operation_notify_start (self);
3116 modest_mail_operation_notify_end (self);
3121 modest_mail_operation_to_string (ModestMailOperation *self)
3123 const gchar *type, *status, *account_id;
3124 ModestMailOperationPrivate *priv = NULL;
3126 g_return_val_if_fail (self, NULL);
3128 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3130 /* new operations don't have anything interesting */
3131 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3132 return g_strdup_printf ("%p <new operation>", self);
3134 switch (priv->op_type) {
3135 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3136 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3137 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3138 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3139 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3140 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3141 default: type = "UNEXPECTED"; break;
3144 switch (priv->status) {
3145 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3146 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3147 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3148 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3149 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3150 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3151 default: status= "UNEXPECTED"; break;
3154 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3156 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3157 priv->done, priv->total,
3158 priv->error && priv->error->message ? priv->error->message : "");