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"
64 * Remove all these #ifdef stuff when the tinymail's idle calls become
67 #define TINYMAIL_IDLES_NOT_LOCKED_YET 1
69 /* 'private'/'protected' functions */
70 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
71 static void modest_mail_operation_init (ModestMailOperation *obj);
72 static void modest_mail_operation_finalize (GObject *obj);
74 static void get_msg_async_cb (TnyFolder *folder,
80 static void get_msg_status_cb (GObject *obj,
84 static void modest_mail_operation_notify_start (ModestMailOperation *self);
85 static void modest_mail_operation_notify_end (ModestMailOperation *self);
87 static void notify_progress_of_multiple_messages (ModestMailOperation *self,
89 gint *last_total_bytes,
90 gint *sum_total_bytes,
92 gboolean increment_done);
94 static guint compute_message_list_size (TnyList *headers);
96 static guint compute_message_array_size (GPtrArray *headers);
98 static int compare_headers_by_date (gconstpointer a,
101 enum _ModestMailOperationSignals
103 PROGRESS_CHANGED_SIGNAL,
104 OPERATION_STARTED_SIGNAL,
105 OPERATION_FINISHED_SIGNAL,
109 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
110 struct _ModestMailOperationPrivate {
116 ErrorCheckingUserCallback error_checking;
117 gpointer error_checking_user_data;
118 ErrorCheckingUserDataDestroyer error_checking_user_data_destroyer;
119 ModestMailOperationStatus status;
120 ModestMailOperationTypeOperation op_type;
123 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
124 MODEST_TYPE_MAIL_OPERATION, \
125 ModestMailOperationPrivate))
127 #define CHECK_EXCEPTION(priv, new_status) if (priv->error) {\
128 priv->status = new_status;\
133 GetMsgAsyncUserCallback user_callback;
136 ModestMailOperation *mail_op;
137 GDestroyNotify destroy_notify;
138 gint last_total_bytes;
139 gint sum_total_bytes;
144 ModestMailOperation *mail_op;
146 gulong msg_sent_handler;
147 gulong error_happened_handler;
150 static void send_mail_msg_sent_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
151 guint nth, guint total, gpointer userdata);
152 static void send_mail_error_happened_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
153 GError *error, gpointer userdata);
154 static void common_send_mail_operation_end (TnySendQueue *queue, TnyMsg *msg,
157 typedef struct _RefreshAsyncHelper {
158 ModestMailOperation *mail_op;
159 RefreshAsyncUserCallback user_callback;
161 } RefreshAsyncHelper;
163 typedef struct _XFerMsgsAsyncHelper
165 ModestMailOperation *mail_op;
167 TnyFolder *dest_folder;
168 XferMsgsAsyncUserCallback user_callback;
171 gint last_total_bytes;
172 gint sum_total_bytes;
174 } XFerMsgsAsyncHelper;
176 typedef struct _XFerFolderAsyncHelper
178 ModestMailOperation *mail_op;
179 XferFolderAsyncUserCallback user_callback;
181 } XFerFolderAsyncHelper;
183 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
187 static void modest_mail_operation_create_msg (ModestMailOperation *self,
188 const gchar *from, const gchar *to,
189 const gchar *cc, const gchar *bcc,
190 const gchar *subject, const gchar *plain_body,
191 const gchar *html_body, const GList *attachments_list,
192 const GList *images_list,
193 TnyHeaderFlags priority_flags,
194 ModestMailOperationCreateMsgCallback callback,
197 static gboolean idle_notify_queue (gpointer data);
200 ModestMailOperation *mail_op;
208 GList *attachments_list;
210 TnyHeaderFlags priority_flags;
211 ModestMailOperationCreateMsgCallback callback;
217 ModestMailOperation *mail_op;
219 ModestMailOperationCreateMsgCallback callback;
224 static GObjectClass *parent_class = NULL;
226 static guint signals[NUM_SIGNALS] = {0};
229 modest_mail_operation_get_type (void)
231 static GType my_type = 0;
233 static const GTypeInfo my_info = {
234 sizeof(ModestMailOperationClass),
235 NULL, /* base init */
236 NULL, /* base finalize */
237 (GClassInitFunc) modest_mail_operation_class_init,
238 NULL, /* class finalize */
239 NULL, /* class data */
240 sizeof(ModestMailOperation),
242 (GInstanceInitFunc) modest_mail_operation_init,
245 my_type = g_type_register_static (G_TYPE_OBJECT,
246 "ModestMailOperation",
253 modest_mail_operation_class_init (ModestMailOperationClass *klass)
255 GObjectClass *gobject_class;
256 gobject_class = (GObjectClass*) klass;
258 parent_class = g_type_class_peek_parent (klass);
259 gobject_class->finalize = modest_mail_operation_finalize;
261 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
264 * ModestMailOperation::progress-changed
265 * @self: the #MailOperation that emits the signal
266 * @user_data: user data set when the signal handler was connected
268 * Emitted when the progress of a mail operation changes
270 signals[PROGRESS_CHANGED_SIGNAL] =
271 g_signal_new ("progress-changed",
272 G_TYPE_FROM_CLASS (gobject_class),
274 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
276 g_cclosure_marshal_VOID__POINTER,
277 G_TYPE_NONE, 1, G_TYPE_POINTER);
281 * This signal is issued whenever a mail operation starts, and
282 * starts mean when the tinymail operation is issued. This
283 * means that it could happen that something wrong happens and
284 * the tinymail function is never called. In this situation a
285 * operation-finished will be issued without any
288 signals[OPERATION_STARTED_SIGNAL] =
289 g_signal_new ("operation-started",
290 G_TYPE_FROM_CLASS (gobject_class),
292 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
294 g_cclosure_marshal_VOID__VOID,
299 * This signal is issued whenever a mail operation
300 * finishes. Note that this signal could be issued without any
301 * previous "operation-started" signal, because this last one
302 * is only issued when the tinymail operation is successfully
305 signals[OPERATION_FINISHED_SIGNAL] =
306 g_signal_new ("operation-finished",
307 G_TYPE_FROM_CLASS (gobject_class),
309 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
311 g_cclosure_marshal_VOID__VOID,
316 modest_mail_operation_init (ModestMailOperation *obj)
318 ModestMailOperationPrivate *priv;
320 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
322 priv->account = NULL;
323 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
324 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
329 priv->error_checking = NULL;
330 priv->error_checking_user_data = NULL;
334 modest_mail_operation_finalize (GObject *obj)
336 ModestMailOperationPrivate *priv;
338 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
343 g_error_free (priv->error);
347 g_object_unref (priv->source);
351 g_object_unref (priv->account);
352 priv->account = NULL;
356 G_OBJECT_CLASS(parent_class)->finalize (obj);
360 modest_mail_operation_new (GObject *source)
362 ModestMailOperation *obj;
363 ModestMailOperationPrivate *priv;
365 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
366 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
369 priv->source = g_object_ref(source);
375 modest_mail_operation_new_with_error_handling (GObject *source,
376 ErrorCheckingUserCallback error_handler,
378 ErrorCheckingUserDataDestroyer error_handler_destroyer)
380 ModestMailOperation *obj;
381 ModestMailOperationPrivate *priv;
383 obj = modest_mail_operation_new (source);
384 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
386 g_return_val_if_fail (error_handler != NULL, obj);
387 priv->error_checking = error_handler;
388 priv->error_checking_user_data = user_data;
389 priv->error_checking_user_data_destroyer = error_handler_destroyer;
395 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
397 ModestMailOperationPrivate *priv;
399 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
401 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
402 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
404 /* Call the user callback */
405 if (priv->error_checking != NULL)
406 priv->error_checking (self, priv->error_checking_user_data);
410 ModestMailOperationTypeOperation
411 modest_mail_operation_get_type_operation (ModestMailOperation *self)
413 ModestMailOperationPrivate *priv;
415 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
416 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
418 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
420 return priv->op_type;
424 modest_mail_operation_is_mine (ModestMailOperation *self,
427 ModestMailOperationPrivate *priv;
429 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
432 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
433 if (priv->source == NULL) return FALSE;
435 return priv->source == me;
439 modest_mail_operation_get_source (ModestMailOperation *self)
441 ModestMailOperationPrivate *priv;
443 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
446 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
448 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
452 return (priv->source) ? g_object_ref (priv->source) : NULL;
455 ModestMailOperationStatus
456 modest_mail_operation_get_status (ModestMailOperation *self)
458 ModestMailOperationPrivate *priv;
460 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
461 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
462 MODEST_MAIL_OPERATION_STATUS_INVALID);
464 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
466 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
467 return MODEST_MAIL_OPERATION_STATUS_INVALID;
474 modest_mail_operation_get_error (ModestMailOperation *self)
476 ModestMailOperationPrivate *priv;
478 g_return_val_if_fail (self, NULL);
479 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
481 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
484 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
492 modest_mail_operation_cancel (ModestMailOperation *self)
494 ModestMailOperationPrivate *priv;
495 gboolean canceled = FALSE;
497 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
499 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
501 /* Note that if we call cancel with an already canceled mail
502 operation the progress changed signal won't be emitted */
503 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
507 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
509 /* Cancel the mail operation. We need to wrap it between this
510 start/stop operations to allow following calls to the
512 g_return_val_if_fail (priv->account, FALSE);
514 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
515 ModestTnySendQueue *queue;
516 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
517 /* Cancel sending without removing the item */
518 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), FALSE, NULL);
520 /* Cancel operation */
521 tny_account_cancel (priv->account);
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)) {
724 g_warning ("%s: %s\n", __FUNCTION__, error->message);
725 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
726 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
727 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
728 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
729 "modest: send mail failed\n");
731 common_send_mail_operation_end (queue, msg, info);
733 g_object_unref(G_OBJECT(hdr1));
734 g_object_unref(G_OBJECT(hdr2));
739 idle_create_msg_cb (gpointer idle_data)
741 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
743 /* This is a GDK lock because we are an idle callback and
744 * info->callback can contain Gtk+ code */
746 gdk_threads_enter (); /* CHECKED */
747 info->callback (info->mail_op, info->msg, info->userdata);
749 g_object_unref (info->mail_op);
751 g_object_unref (info->msg);
752 g_slice_free (CreateMsgIdleInfo, info);
753 gdk_threads_leave (); /* CHECKED */
759 create_msg_thread (gpointer thread_data)
761 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
762 TnyMsg *new_msg = NULL;
763 ModestMailOperationPrivate *priv;
765 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
766 if (info->html_body == NULL) {
767 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
768 info->bcc, info->subject, info->plain_body,
769 info->attachments_list);
771 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
772 info->bcc, info->subject, info->html_body,
773 info->plain_body, info->attachments_list,
780 /* Set priority flags in message */
781 header = tny_msg_get_header (new_msg);
782 tny_header_set_flag (header, info->priority_flags);
784 /* Set attachment flags in message */
785 if (info->attachments_list != NULL)
786 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
788 g_object_unref (G_OBJECT(header));
790 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
791 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
792 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
793 "modest: failed to create a new msg\n");
801 g_free (info->plain_body);
802 g_free (info->html_body);
803 g_free (info->subject);
804 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
805 g_list_free (info->attachments_list);
806 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
807 g_list_free (info->images_list);
809 if (info->callback) {
810 CreateMsgIdleInfo *idle_info;
811 idle_info = g_slice_new0 (CreateMsgIdleInfo);
812 idle_info->mail_op = g_object_ref (info->mail_op);
813 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
814 idle_info->callback = info->callback;
815 idle_info->userdata = info->userdata;
816 g_idle_add (idle_create_msg_cb, idle_info);
818 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
821 g_object_unref (info->mail_op);
822 g_slice_free (CreateMsgInfo, info);
823 if (new_msg) g_object_unref(new_msg);
828 modest_mail_operation_create_msg (ModestMailOperation *self,
829 const gchar *from, const gchar *to,
830 const gchar *cc, const gchar *bcc,
831 const gchar *subject, const gchar *plain_body,
832 const gchar *html_body,
833 const GList *attachments_list,
834 const GList *images_list,
835 TnyHeaderFlags priority_flags,
836 ModestMailOperationCreateMsgCallback callback,
839 CreateMsgInfo *info = NULL;
841 info = g_slice_new0 (CreateMsgInfo);
842 info->mail_op = g_object_ref (self);
844 info->from = g_strdup (from);
845 info->to = g_strdup (to);
846 info->cc = g_strdup (cc);
847 info->bcc = g_strdup (bcc);
848 info->subject = g_strdup (subject);
849 info->plain_body = g_strdup (plain_body);
850 info->html_body = g_strdup (html_body);
851 info->attachments_list = g_list_copy ((GList *) attachments_list);
852 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
853 info->images_list = g_list_copy ((GList *) images_list);
854 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
855 info->priority_flags = priority_flags;
857 info->callback = callback;
858 info->userdata = userdata;
860 g_thread_create (create_msg_thread, info, FALSE, NULL);
865 TnyTransportAccount *transport_account;
870 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
874 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
875 TnyFolder *draft_folder = NULL;
876 TnyFolder *outbox_folder = NULL;
877 TnyHeader *header = NULL;
884 /* Call mail operation */
885 modest_mail_operation_send_mail (self, info->transport_account, msg);
887 if (info->draft_msg != NULL) {
888 TnyFolder *folder = NULL;
889 TnyFolder *src_folder = NULL;
890 TnyFolderType folder_type;
891 TnyTransportAccount *transport_account = NULL;
893 /* To remove the old mail from its source folder, we need to get the
894 * transport account of the original draft message (the transport account
895 * might have been changed by the user) */
896 header = tny_msg_get_header (info->draft_msg);
897 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
898 modest_runtime_get_account_store(), header);
899 if (transport_account == NULL)
900 transport_account = g_object_ref(info->transport_account);
901 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
902 TNY_FOLDER_TYPE_DRAFTS);
903 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
904 TNY_FOLDER_TYPE_OUTBOX);
905 g_object_unref(transport_account);
908 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
912 if (!outbox_folder) {
913 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
918 folder = tny_msg_get_folder (info->draft_msg);
919 if (folder == NULL) goto end;
920 folder_type = modest_tny_folder_guess_folder_type (folder);
922 if (folder_type == TNY_FOLDER_TYPE_INVALID)
923 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
925 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
926 src_folder = outbox_folder;
928 src_folder = draft_folder;
930 /* Note: This can fail (with a warning) if the message is not really already in a folder,
931 * because this function requires it to have a UID. */
932 tny_folder_remove_msg (src_folder, header, NULL);
934 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
935 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
937 g_object_unref (folder);
942 g_object_unref (header);
946 g_object_unref (info->draft_msg);
948 g_object_unref (draft_folder);
950 g_object_unref (outbox_folder);
951 if (info->transport_account)
952 g_object_unref (info->transport_account);
953 g_slice_free (SendNewMailInfo, info);
957 modest_mail_operation_send_new_mail (ModestMailOperation *self,
958 TnyTransportAccount *transport_account,
960 const gchar *from, const gchar *to,
961 const gchar *cc, const gchar *bcc,
962 const gchar *subject, const gchar *plain_body,
963 const gchar *html_body,
964 const GList *attachments_list,
965 const GList *images_list,
966 TnyHeaderFlags priority_flags)
968 ModestMailOperationPrivate *priv = NULL;
969 SendNewMailInfo *info;
971 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
972 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
974 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
975 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
976 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
977 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
979 /* Check parametters */
981 /* Set status failed and set an error */
982 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
983 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
984 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
985 _("Error trying to send a mail. You need to set at least one recipient"));
988 info = g_slice_new0 (SendNewMailInfo);
989 info->transport_account = transport_account;
990 if (transport_account)
991 g_object_ref (transport_account);
992 info->draft_msg = draft_msg;
994 g_object_ref (draft_msg);
997 modest_mail_operation_notify_start (self);
998 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
999 attachments_list, images_list, priority_flags,
1000 modest_mail_operation_send_new_mail_cb, info);
1006 TnyTransportAccount *transport_account;
1008 SaveToDraftstCallback callback;
1012 ModestMailOperation *mailop;
1013 } SaveToDraftsAddMsgInfo;
1016 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
1021 ModestMailOperationPrivate *priv = NULL;
1022 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
1024 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1027 g_warning ("%s: priv->error != NULL", __FUNCTION__);
1028 g_error_free(priv->error);
1031 priv->error = (err == NULL) ? NULL : g_error_copy(err);
1033 if ((!priv->error) && (info->draft_msg != NULL)) {
1034 TnyHeader *header = tny_msg_get_header (info->draft_msg);
1035 TnyFolder *src_folder = tny_header_get_folder (header);
1037 /* Remove the old draft */
1038 tny_folder_remove_msg (src_folder, header, NULL);
1040 /* Synchronize to expunge and to update the msg counts */
1041 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1042 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1044 g_object_unref (G_OBJECT(header));
1045 g_object_unref (G_OBJECT(src_folder));
1049 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1051 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1053 /* Call the user callback */
1055 info->callback (info->mailop, info->msg, info->user_data);
1057 if (info->transport_account)
1058 g_object_unref (G_OBJECT(info->transport_account));
1059 if (info->draft_msg)
1060 g_object_unref (G_OBJECT (info->draft_msg));
1062 g_object_unref (G_OBJECT(info->drafts));
1064 g_object_unref (G_OBJECT (info->msg));
1066 modest_mail_operation_notify_end (info->mailop);
1067 g_object_unref(info->mailop);
1068 g_slice_free (SaveToDraftsAddMsgInfo, info);
1073 TnyTransportAccount *transport_account;
1075 SaveToDraftstCallback callback;
1080 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1084 TnyFolder *drafts = NULL;
1085 ModestMailOperationPrivate *priv = NULL;
1086 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1088 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1091 if (!(priv->error)) {
1092 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1093 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1094 "modest: failed to create a new msg\n");
1097 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1098 TNY_FOLDER_TYPE_DRAFTS);
1099 if (!drafts && !(priv->error)) {
1100 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1101 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1102 "modest: failed to create a new msg\n");
1107 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1108 cb_info->transport_account = g_object_ref(info->transport_account);
1109 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1110 cb_info->callback = info->callback;
1111 cb_info->user_data = info->user_data;
1112 cb_info->drafts = g_object_ref(drafts);
1113 cb_info->msg = g_object_ref(msg);
1114 cb_info->mailop = g_object_ref(self);
1115 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1118 /* Call the user callback */
1119 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1121 info->callback (self, msg, info->user_data);
1122 modest_mail_operation_notify_end (self);
1126 g_object_unref (G_OBJECT(drafts));
1127 if (info->draft_msg)
1128 g_object_unref (G_OBJECT (info->draft_msg));
1129 if (info->transport_account)
1130 g_object_unref (G_OBJECT(info->transport_account));
1131 g_slice_free (SaveToDraftsInfo, info);
1135 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1136 TnyTransportAccount *transport_account,
1138 const gchar *from, const gchar *to,
1139 const gchar *cc, const gchar *bcc,
1140 const gchar *subject, const gchar *plain_body,
1141 const gchar *html_body,
1142 const GList *attachments_list,
1143 const GList *images_list,
1144 TnyHeaderFlags priority_flags,
1145 SaveToDraftstCallback callback,
1148 ModestMailOperationPrivate *priv = NULL;
1149 SaveToDraftsInfo *info = NULL;
1151 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1152 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1154 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1156 /* Get account and set it into mail_operation */
1157 priv->account = g_object_ref (transport_account);
1158 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1160 info = g_slice_new0 (SaveToDraftsInfo);
1161 info->transport_account = g_object_ref (transport_account);
1162 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1163 info->callback = callback;
1164 info->user_data = user_data;
1166 modest_mail_operation_notify_start (self);
1167 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1168 attachments_list, images_list, priority_flags,
1169 modest_mail_operation_save_to_drafts_cb, info);
1174 ModestMailOperation *mail_op;
1175 TnyMimePart *mime_part;
1177 GetMimePartSizeCallback callback;
1179 } GetMimePartSizeInfo;
1181 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1182 /* We use this folder observer to track the headers that have been
1183 * added to a folder */
1186 TnyList *new_headers;
1187 } InternalFolderObserver;
1190 GObjectClass parent;
1191 } InternalFolderObserverClass;
1193 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1195 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1196 internal_folder_observer,
1198 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1202 foreach_add_item (gpointer header, gpointer user_data)
1204 tny_list_prepend (TNY_LIST (user_data),
1205 g_object_ref (G_OBJECT (header)));
1208 /* This is the method that looks for new messages in a folder */
1210 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1212 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1214 TnyFolderChangeChanged changed;
1216 changed = tny_folder_change_get_changed (change);
1218 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1221 /* Get added headers */
1222 list = tny_simple_list_new ();
1223 tny_folder_change_get_added_headers (change, list);
1225 /* Add them to the folder observer */
1226 tny_list_foreach (list, foreach_add_item,
1227 derived->new_headers);
1229 g_object_unref (G_OBJECT (list));
1234 internal_folder_observer_init (InternalFolderObserver *self)
1236 self->new_headers = tny_simple_list_new ();
1239 internal_folder_observer_finalize (GObject *object)
1241 InternalFolderObserver *self;
1243 self = (InternalFolderObserver *) object;
1244 g_object_unref (self->new_headers);
1246 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1249 tny_folder_observer_init (TnyFolderObserverIface *iface)
1251 iface->update_func = internal_folder_observer_update;
1254 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1256 GObjectClass *object_class;
1258 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1259 object_class = (GObjectClass*) klass;
1260 object_class->finalize = internal_folder_observer_finalize;
1265 ModestMailOperation *mail_op;
1266 gchar *account_name;
1267 UpdateAccountCallback callback;
1272 TnyFolderObserver *inbox_observer;
1273 RetrieveAllCallback retrieve_all_cb;
1274 } UpdateAccountInfo;
1278 destroy_update_account_info (UpdateAccountInfo *info)
1280 g_free (info->account_name);
1281 g_object_unref (info->folders);
1282 g_object_unref (info->mail_op);
1283 g_slice_free (UpdateAccountInfo, info);
1287 update_account_get_msg_async_cb (TnyFolder *folder,
1293 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1295 /* Just delete the helper. Don't do anything with the new
1296 msg. There is also no need to check for errors */
1297 g_object_unref (msg_info->mail_op);
1298 g_object_unref (msg_info->header);
1299 g_slice_free (GetMsgInfo, msg_info);
1304 inbox_refreshed_cb (TnyFolder *inbox,
1309 UpdateAccountInfo *info;
1310 ModestMailOperationPrivate *priv;
1311 TnyIterator *new_headers_iter;
1312 GPtrArray *new_headers_array = NULL;
1313 gint max_size, retrieve_limit, i;
1314 ModestAccountMgr *mgr;
1315 ModestAccountRetrieveType retrieve_type;
1316 TnyList *new_headers = NULL;
1317 gboolean headers_only, ignore_limit;
1318 TnyTransportAccount *transport_account;
1319 ModestTnySendQueue *send_queue;
1321 info = (UpdateAccountInfo *) user_data;
1322 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1323 mgr = modest_runtime_get_account_mgr ();
1325 if (canceled || err || !inbox) {
1326 /* Try to send anyway */
1330 /* Get the message max size */
1331 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1332 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1334 max_size = G_MAXINT;
1336 max_size = max_size * KB;
1338 /* Create the new headers array. We need it to sort the
1339 new headers by date */
1340 new_headers_array = g_ptr_array_new ();
1341 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1342 while (!tny_iterator_is_done (new_headers_iter)) {
1343 TnyHeader *header = NULL;
1345 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1346 /* Apply per-message size limits */
1347 if (tny_header_get_message_size (header) < max_size)
1348 g_ptr_array_add (new_headers_array, g_object_ref (header));
1350 g_object_unref (header);
1351 tny_iterator_next (new_headers_iter);
1353 g_object_unref (new_headers_iter);
1354 tny_folder_remove_observer (inbox, info->inbox_observer);
1355 g_object_unref (info->inbox_observer);
1356 info->inbox_observer = NULL;
1358 /* Update the last updated key, even if we don't have to get new headers */
1359 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1361 if (new_headers_array->len == 0)
1364 /* Get per-account message amount retrieval limit */
1365 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1366 if (retrieve_limit == 0)
1367 retrieve_limit = G_MAXINT;
1369 /* Get per-account retrieval type */
1370 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1371 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1374 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1376 /* Ask the users if they want to retrieve all the messages
1377 even though the limit was exceeded */
1378 ignore_limit = FALSE;
1379 if (new_headers_array->len > retrieve_limit) {
1380 /* Ask the user if a callback has been specified and
1381 if the mail operation has a source (this means that
1382 was invoked by the user and not automatically by a
1384 if (info->retrieve_all_cb && priv->source)
1385 ignore_limit = info->retrieve_all_cb (priv->source,
1386 new_headers_array->len,
1390 if (!headers_only) {
1392 const gint msg_list_size = compute_message_array_size (new_headers_array);
1396 priv->total = new_headers_array->len;
1398 priv->total = MIN (new_headers_array->len, retrieve_limit);
1399 while (msg_num < priv->total) {
1400 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1401 TnyFolder *folder = tny_header_get_folder (header);
1402 GetMsgInfo *msg_info;
1404 /* Create the message info */
1405 msg_info = g_slice_new0 (GetMsgInfo);
1406 msg_info->mail_op = g_object_ref (info->mail_op);
1407 msg_info->header = g_object_ref (header);
1408 msg_info->total_bytes = msg_list_size;
1410 /* Get message in an async way */
1411 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1412 get_msg_status_cb, msg_info);
1414 g_object_unref (folder);
1420 /* Copy the headers to a list and free the array */
1421 new_headers = tny_simple_list_new ();
1422 for (i=0; i < new_headers_array->len; i++) {
1423 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1424 tny_list_append (new_headers, G_OBJECT (header));
1426 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1427 g_ptr_array_free (new_headers_array, FALSE);
1434 /* Get the transport account */
1435 transport_account = (TnyTransportAccount *)
1436 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1437 info->account_name);
1440 send_queue = modest_runtime_get_send_queue (transport_account);
1441 modest_tny_send_queue_try_to_send (send_queue);
1443 /* Check if the operation was a success */
1445 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1447 /* Set the account back to not busy */
1448 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1450 /* Call the user callback */
1452 info->callback (info->mail_op, new_headers, info->user_data);
1454 /* Notify about operation end */
1455 modest_mail_operation_notify_end (info->mail_op);
1459 g_object_unref (new_headers);
1460 destroy_update_account_info (info);
1464 recurse_folders_async_cb (TnyFolderStore *folder_store,
1470 UpdateAccountInfo *info;
1471 ModestMailOperationPrivate *priv;
1473 info = (UpdateAccountInfo *) user_data;
1474 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1476 if (err || canceled) {
1477 /* Try to continue anyway */
1479 TnyIterator *iter = tny_list_create_iterator (list);
1480 while (!tny_iterator_is_done (iter)) {
1481 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1482 TnyList *folders = tny_simple_list_new ();
1484 /* Add to the list of all folders */
1485 tny_list_append (info->folders, (GObject *) folder);
1487 /* Add pending call */
1488 info->pending_calls++;
1490 tny_folder_store_get_folders_async (folder, folders, NULL,
1491 recurse_folders_async_cb,
1494 g_object_unref (G_OBJECT (folder));
1496 tny_iterator_next (iter);
1498 g_object_unref (G_OBJECT (iter));
1499 g_object_unref (G_OBJECT (list));
1502 /* Remove my own pending call */
1503 info->pending_calls--;
1505 /* This means that we have all the folders */
1506 if (info->pending_calls == 0) {
1507 TnyIterator *iter_all_folders;
1508 TnyFolder *inbox = NULL;
1510 iter_all_folders = tny_list_create_iterator (info->folders);
1512 /* Do a poke status over all folders */
1513 while (!tny_iterator_is_done (iter_all_folders) &&
1514 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1515 TnyFolder *folder = NULL;
1517 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1519 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1520 /* Get a reference to the INBOX */
1521 inbox = g_object_ref (folder);
1523 /* Issue a poke status over the folder */
1525 tny_folder_poke_status (folder);
1528 /* Free and go to next */
1529 g_object_unref (folder);
1530 tny_iterator_next (iter_all_folders);
1532 g_object_unref (iter_all_folders);
1534 /* Refresh the INBOX */
1536 /* Refresh the folder. Our observer receives
1537 * the new emails during folder refreshes, so
1538 * we can use observer->new_headers
1540 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1541 tny_folder_add_observer (inbox, info->inbox_observer);
1543 /* Refresh the INBOX */
1544 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1545 g_object_unref (inbox);
1547 /* We could not perform the inbox refresh but
1548 we'll try to send mails anyway */
1549 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1555 modest_mail_operation_update_account (ModestMailOperation *self,
1556 const gchar *account_name,
1558 RetrieveAllCallback retrieve_all_cb,
1559 UpdateAccountCallback callback,
1562 UpdateAccountInfo *info = NULL;
1563 ModestMailOperationPrivate *priv = NULL;
1564 ModestTnyAccountStore *account_store = NULL;
1565 TnyStoreAccount *store_account = NULL;
1568 /* Init mail operation */
1569 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1572 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1573 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1575 /* Get the store account */
1576 account_store = modest_runtime_get_account_store ();
1577 store_account = (TnyStoreAccount *)
1578 modest_tny_account_store_get_server_account (account_store,
1580 TNY_ACCOUNT_TYPE_STORE);
1581 priv->account = g_object_ref (store_account);
1583 /* Create the helper object */
1584 info = g_slice_new0 (UpdateAccountInfo);
1585 info->pending_calls = 1;
1586 info->folders = tny_simple_list_new ();
1587 info->mail_op = g_object_ref (self);
1588 info->poke_all = poke_all;
1589 info->account_name = g_strdup (account_name);
1590 info->callback = callback;
1591 info->user_data = user_data;
1592 info->retrieve_all_cb = retrieve_all_cb;
1594 /* Set account busy */
1595 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1596 modest_mail_operation_notify_start (self);
1598 /* notify about the start of the operation */
1599 ModestMailOperationState *state;
1600 state = modest_mail_operation_clone_state (self);
1604 /* Start notifying progress */
1605 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
1607 g_slice_free (ModestMailOperationState, state);
1609 /* Get all folders and continue in the callback */
1610 folders = tny_simple_list_new ();
1611 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1613 recurse_folders_async_cb,
1618 * Used to notify the queue from the main
1619 * loop. We call it inside an idle call to achieve that
1622 idle_notify_queue (gpointer data)
1624 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1626 gdk_threads_enter ();
1627 modest_mail_operation_notify_end (mail_op);
1628 gdk_threads_leave ();
1629 g_object_unref (mail_op);
1635 compare_headers_by_date (gconstpointer a,
1638 TnyHeader **header1, **header2;
1639 time_t sent1, sent2;
1641 header1 = (TnyHeader **) a;
1642 header2 = (TnyHeader **) b;
1644 sent1 = tny_header_get_date_sent (*header1);
1645 sent2 = tny_header_get_date_sent (*header2);
1647 /* We want the most recent ones (greater time_t) at the
1656 /* ******************************************************************* */
1657 /* ************************** STORE ACTIONS ************************* */
1658 /* ******************************************************************* */
1661 ModestMailOperation *mail_op;
1662 CreateFolderUserCallback callback;
1668 create_folder_cb (TnyFolderStore *parent_folder,
1670 TnyFolder *new_folder,
1674 ModestMailOperationPrivate *priv;
1675 CreateFolderInfo *info;
1677 info = (CreateFolderInfo *) user_data;
1678 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1680 if (canceled || err) {
1681 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1683 priv->error = g_error_copy (err);
1685 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1686 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1689 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1692 /* The user will unref the new_folder */
1694 info->callback (info->mail_op, parent_folder,
1695 new_folder, info->user_data);
1697 /* Notify about operation end */
1698 modest_mail_operation_notify_end (info->mail_op);
1701 g_object_unref (info->mail_op);
1702 g_slice_free (CreateFolderInfo, info);
1706 modest_mail_operation_create_folder (ModestMailOperation *self,
1707 TnyFolderStore *parent,
1709 CreateFolderUserCallback callback,
1712 ModestMailOperationPrivate *priv;
1714 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1715 g_return_if_fail (name);
1717 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1718 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1719 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1720 g_object_ref (parent) :
1721 modest_tny_folder_get_account (TNY_FOLDER (parent));
1723 /* Check for already existing folder */
1724 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1725 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1726 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1727 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1728 _CS("ckdg_ib_folder_already_exists"));
1732 if (TNY_IS_FOLDER (parent)) {
1733 /* Check folder rules */
1734 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1735 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1736 /* Set status failed and set an error */
1737 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1738 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1739 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1740 _("mail_in_ui_folder_create_error"));
1744 if (!strcmp (name, " ") || strchr (name, '/')) {
1745 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1746 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1747 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1748 _("mail_in_ui_folder_create_error"));
1752 CreateFolderInfo *info;
1754 info = g_slice_new0 (CreateFolderInfo);
1755 info->mail_op = g_object_ref (self);
1756 info->callback = callback;
1757 info->user_data = user_data;
1759 modest_mail_operation_notify_start (self);
1761 /* Create the folder */
1762 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1765 /* Call the user callback anyway */
1767 callback (self, parent, NULL, user_data);
1768 /* Notify about operation end */
1769 modest_mail_operation_notify_end (self);
1774 modest_mail_operation_remove_folder (ModestMailOperation *self,
1776 gboolean remove_to_trash)
1778 TnyAccount *account;
1779 ModestMailOperationPrivate *priv;
1780 ModestTnyFolderRules rules;
1782 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1783 g_return_if_fail (TNY_IS_FOLDER (folder));
1785 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1787 /* Check folder rules */
1788 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1789 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1790 /* Set status failed and set an error */
1791 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1792 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1793 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1794 _("mail_in_ui_folder_delete_error"));
1798 /* Get the account */
1799 account = modest_tny_folder_get_account (folder);
1800 priv->account = g_object_ref(account);
1801 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1803 /* Delete folder or move to trash */
1804 if (remove_to_trash) {
1805 TnyFolder *trash_folder = NULL;
1806 trash_folder = modest_tny_account_get_special_folder (account,
1807 TNY_FOLDER_TYPE_TRASH);
1808 /* TODO: error_handling */
1810 modest_mail_operation_notify_start (self);
1811 modest_mail_operation_xfer_folder (self, folder,
1812 TNY_FOLDER_STORE (trash_folder),
1814 g_object_unref (trash_folder);
1816 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1819 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1821 modest_mail_operation_notify_start (self);
1822 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1823 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1826 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1828 g_object_unref (parent);
1830 g_warning ("%s: could not get parent folder", __FUNCTION__);
1832 g_object_unref (G_OBJECT (account));
1835 /* Notify about operation end */
1836 modest_mail_operation_notify_end (self);
1840 transfer_folder_status_cb (GObject *obj,
1844 ModestMailOperation *self;
1845 ModestMailOperationPrivate *priv;
1846 ModestMailOperationState *state;
1847 XFerFolderAsyncHelper *helper;
1849 g_return_if_fail (status != NULL);
1850 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1852 helper = (XFerFolderAsyncHelper *) user_data;
1853 g_return_if_fail (helper != NULL);
1855 self = helper->mail_op;
1856 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1858 priv->done = status->position;
1859 priv->total = status->of_total;
1861 state = modest_mail_operation_clone_state (self);
1863 /* This is not a GDK lock because we are a Tinymail callback
1864 * which is already GDK locked by Tinymail */
1866 /* no gdk_threads_enter (), CHECKED */
1868 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1870 /* no gdk_threads_leave (), CHECKED */
1872 g_slice_free (ModestMailOperationState, state);
1877 transfer_folder_cb (TnyFolder *folder,
1879 TnyFolderStore *into,
1880 TnyFolder *new_folder,
1884 XFerFolderAsyncHelper *helper;
1885 ModestMailOperation *self = NULL;
1886 ModestMailOperationPrivate *priv = NULL;
1888 helper = (XFerFolderAsyncHelper *) user_data;
1889 g_return_if_fail (helper != NULL);
1891 self = helper->mail_op;
1892 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1895 priv->error = g_error_copy (err);
1897 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1898 } else if (cancelled) {
1899 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1900 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1901 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1902 _("Transference of %s was cancelled."),
1903 tny_folder_get_name (folder));
1906 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1909 /* Notify about operation end */
1910 modest_mail_operation_notify_end (self);
1912 /* If user defined callback function was defined, call it */
1913 if (helper->user_callback) {
1915 /* This is not a GDK lock because we are a Tinymail callback
1916 * which is already GDK locked by Tinymail */
1918 /* no gdk_threads_enter (), CHECKED */
1919 helper->user_callback (self, new_folder, helper->user_data);
1920 /* no gdk_threads_leave () , CHECKED */
1924 g_object_unref (helper->mail_op);
1925 g_slice_free (XFerFolderAsyncHelper, helper);
1930 * This function checks if the new name is a valid name for our local
1931 * folders account. The new name could not be the same than then name
1932 * of any of the mandatory local folders
1934 * We can not rely on tinymail because tinymail does not check the
1935 * name of the virtual folders that the account could have in the case
1936 * that we're doing a rename (because it directly calls Camel which
1937 * knows nothing about our virtual folders).
1939 * In the case of an actual copy/move (i.e. move/copy a folder between
1940 * accounts) tinymail uses the tny_folder_store_create_account which
1941 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1942 * checks the new name of the folder, so this call in that case
1943 * wouldn't be needed. *But* NOTE that if tinymail changes its
1944 * implementation (if folder transfers within the same account is no
1945 * longer implemented as a rename) this call will allow Modest to work
1948 * If the new name is not valid, this function will set the status to
1949 * failed and will set also an error in the mail operation
1952 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1953 TnyFolderStore *into,
1954 const gchar *new_name)
1956 if (TNY_IS_ACCOUNT (into) &&
1957 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1958 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1960 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1961 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1962 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1963 _CS("ckdg_ib_folder_already_exists"));
1970 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1972 TnyFolderStore *parent,
1973 gboolean delete_original,
1974 XferFolderAsyncUserCallback user_callback,
1977 ModestMailOperationPrivate *priv = NULL;
1978 ModestTnyFolderRules parent_rules = 0, rules;
1979 XFerFolderAsyncHelper *helper = NULL;
1980 const gchar *folder_name = NULL;
1981 const gchar *error_msg;
1983 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1984 g_return_if_fail (TNY_IS_FOLDER (folder));
1985 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1987 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1988 folder_name = tny_folder_get_name (folder);
1990 /* Set the error msg */
1991 error_msg = _("mail_in_ui_folder_move_target_error");
1993 /* Get account and set it into mail_operation */
1994 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1995 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1996 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1998 /* Get folder rules */
1999 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2000 if (TNY_IS_FOLDER (parent))
2001 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2003 /* Apply operation constraints */
2004 if ((gpointer) parent == (gpointer) folder ||
2005 (!TNY_IS_FOLDER_STORE (parent)) ||
2006 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
2009 } else if (TNY_IS_FOLDER (parent) &&
2010 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2014 } else if (TNY_IS_FOLDER (parent) &&
2015 TNY_IS_FOLDER_STORE (folder) &&
2016 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2017 TNY_FOLDER_STORE (folder))) {
2018 /* Do not move a parent into a child */
2020 } else if (TNY_IS_FOLDER_STORE (parent) &&
2021 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2022 /* Check that the new folder name is not used by any
2025 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2026 /* Check that the new folder name is not used by any
2027 special local folder */
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 /* Move/Copy folder */
2037 modest_mail_operation_notify_start (self);
2038 tny_folder_copy_async (folder,
2040 tny_folder_get_name (folder),
2043 transfer_folder_status_cb,
2049 /* Set status failed and set an error */
2050 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2051 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2052 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2055 /* Call the user callback if exists */
2057 user_callback (self, NULL, user_data);
2059 /* Notify the queue */
2060 modest_mail_operation_notify_end (self);
2064 modest_mail_operation_rename_folder (ModestMailOperation *self,
2067 XferFolderAsyncUserCallback user_callback,
2070 ModestMailOperationPrivate *priv;
2071 ModestTnyFolderRules rules;
2072 XFerFolderAsyncHelper *helper;
2074 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2075 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2076 g_return_if_fail (name);
2078 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2080 /* Get account and set it into mail_operation */
2081 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2082 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2084 /* Check folder rules */
2085 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2086 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2088 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2091 TnyFolderStore *into;
2093 into = tny_folder_get_folder_store (folder);
2095 /* Check that the new folder name is not used by any
2096 special local folder */
2097 if (new_name_valid_if_local_account (priv, into, name)) {
2098 /* Create the helper */
2099 helper = g_slice_new0 (XFerFolderAsyncHelper);
2100 helper->mail_op = g_object_ref(self);
2101 helper->user_callback = user_callback;
2102 helper->user_data = user_data;
2104 /* Rename. Camel handles folder subscription/unsubscription */
2105 modest_mail_operation_notify_start (self);
2106 tny_folder_copy_async (folder, into, name, TRUE,
2108 transfer_folder_status_cb,
2113 g_object_unref (into);
2118 /* Set status failed and set an error */
2119 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2120 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2121 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2122 _("FIXME: unable to rename"));
2125 user_callback (self, NULL, user_data);
2127 /* Notify about operation end */
2128 modest_mail_operation_notify_end (self);
2131 /* ******************************************************************* */
2132 /* ************************** MSG ACTIONS ************************* */
2133 /* ******************************************************************* */
2136 modest_mail_operation_get_msg (ModestMailOperation *self,
2138 GetMsgAsyncUserCallback user_callback,
2141 GetMsgInfo *helper = NULL;
2143 ModestMailOperationPrivate *priv;
2145 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2146 g_return_if_fail (TNY_IS_HEADER (header));
2148 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2149 folder = tny_header_get_folder (header);
2151 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2155 /* Get account and set it into mail_operation */
2156 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2158 /* Check for cached messages */
2159 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2160 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2162 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2164 /* Create the helper */
2165 helper = g_slice_new0 (GetMsgInfo);
2166 helper->header = g_object_ref (header);
2167 helper->mail_op = g_object_ref (self);
2168 helper->user_callback = user_callback;
2169 helper->user_data = user_data;
2170 helper->destroy_notify = NULL;
2171 helper->last_total_bytes = 0;
2172 helper->sum_total_bytes = 0;
2173 helper->total_bytes = tny_header_get_message_size (header);
2175 modest_mail_operation_notify_start (self);
2177 /* notify about the start of the operation */
2178 ModestMailOperationState *state;
2179 state = modest_mail_operation_clone_state (self);
2182 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2185 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2187 g_object_unref (G_OBJECT (folder));
2191 get_msg_status_cb (GObject *obj,
2195 GetMsgInfo *helper = NULL;
2197 g_return_if_fail (status != NULL);
2198 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2200 helper = (GetMsgInfo *) user_data;
2201 g_return_if_fail (helper != NULL);
2203 /* Notify progress */
2204 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2205 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2209 get_msg_async_cb (TnyFolder *folder,
2215 GetMsgInfo *info = NULL;
2216 ModestMailOperationPrivate *priv = NULL;
2219 info = (GetMsgInfo *) user_data;
2221 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2223 finished = (priv->done == priv->total) ? TRUE : FALSE;
2226 if (canceled || err) {
2227 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2229 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2230 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2233 /* Set the success status before calling the user callback */
2234 if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2235 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2239 /* Call the user callback */
2240 if (info->user_callback)
2241 info->user_callback (info->mail_op, info->header, canceled,
2242 msg, err, info->user_data);
2244 /* Notify about operation end if this is the last callback */
2246 /* Free user data */
2247 if (info->destroy_notify)
2248 info->destroy_notify (info->user_data);
2250 /* Notify about operation end */
2251 modest_mail_operation_notify_end (info->mail_op);
2255 g_object_unref (info->header);
2256 g_object_unref (info->mail_op);
2257 g_slice_free (GetMsgInfo, info);
2261 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2262 TnyList *header_list,
2263 GetMsgAsyncUserCallback user_callback,
2265 GDestroyNotify notify)
2267 ModestMailOperationPrivate *priv = NULL;
2269 TnyIterator *iter = NULL;
2271 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2273 /* Init mail operation */
2274 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2275 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2276 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2278 priv->total = tny_list_get_length(header_list);
2280 /* Get account and set it into mail_operation */
2281 if (tny_list_get_length (header_list) >= 1) {
2282 iter = tny_list_create_iterator (header_list);
2283 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2285 TnyFolder *folder = tny_header_get_folder (header);
2287 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2288 g_object_unref (folder);
2290 g_object_unref (header);
2293 if (tny_list_get_length (header_list) == 1) {
2294 g_object_unref (iter);
2299 msg_list_size = compute_message_list_size (header_list);
2301 modest_mail_operation_notify_start (self);
2302 iter = tny_list_create_iterator (header_list);
2303 while (!tny_iterator_is_done (iter)) {
2304 /* notify about the start of the operation */
2305 ModestMailOperationState *state;
2306 state = modest_mail_operation_clone_state (self);
2309 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2312 GetMsgInfo *msg_info = NULL;
2313 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2314 TnyFolder *folder = tny_header_get_folder (header);
2316 /* Create the message info */
2317 msg_info = g_slice_new0 (GetMsgInfo);
2318 msg_info->mail_op = g_object_ref (self);
2319 msg_info->header = g_object_ref (header);
2320 msg_info->user_callback = user_callback;
2321 msg_info->user_data = user_data;
2322 msg_info->destroy_notify = notify;
2323 msg_info->last_total_bytes = 0;
2324 msg_info->sum_total_bytes = 0;
2325 msg_info->total_bytes = msg_list_size;
2327 /* The callback will call it per each header */
2328 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2330 /* Free and go on */
2331 g_object_unref (header);
2332 g_object_unref (folder);
2333 tny_iterator_next (iter);
2335 g_object_unref (iter);
2340 modest_mail_operation_remove_msg (ModestMailOperation *self,
2342 gboolean remove_to_trash /*ignored*/)
2345 ModestMailOperationPrivate *priv;
2347 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2348 g_return_if_fail (TNY_IS_HEADER (header));
2350 if (remove_to_trash)
2351 g_warning ("remove to trash is not implemented");
2353 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2354 folder = tny_header_get_folder (header);
2356 /* Get account and set it into mail_operation */
2357 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2358 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2359 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2361 /* remove message from folder */
2362 tny_folder_remove_msg (folder, header, &(priv->error));
2364 gboolean expunge, leave_on_server;
2365 const gchar *account_name;
2366 TnyAccount *account;
2367 ModestTransportStoreProtocol account_proto;
2369 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2370 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2372 modest_mail_operation_notify_start (self);
2374 /* Get leave on server setting */
2375 account = tny_folder_get_account (folder);
2376 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2378 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2381 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2383 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2384 modest_tny_folder_is_remote_folder (folder) == FALSE)
2390 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2393 g_object_unref (account);
2399 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2401 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2404 g_object_unref (G_OBJECT (folder));
2406 /* Notify about operation end */
2407 modest_mail_operation_notify_end (self);
2411 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2413 gboolean remove_to_trash /*ignored*/)
2415 TnyFolder *folder = NULL;
2416 ModestMailOperationPrivate *priv;
2417 TnyIterator *iter = NULL;
2418 TnyHeader *header = NULL;
2419 TnyList *remove_headers = NULL;
2420 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2422 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2423 g_return_if_fail (TNY_IS_LIST (headers));
2425 if (remove_to_trash)
2426 g_warning ("remove to trash is not implemented");
2428 if (tny_list_get_length(headers) == 0) {
2429 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2430 goto cleanup; /* nothing to do */
2433 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2434 remove_headers = g_object_ref(headers);
2436 /* Get folder from first header and sync it */
2437 iter = tny_list_create_iterator (headers);
2438 header = TNY_HEADER (tny_iterator_get_current (iter));
2440 folder = tny_header_get_folder (header);
2441 if (!TNY_IS_FOLDER(folder)) {
2442 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2446 /* Don't remove messages that are being sent */
2447 if (modest_tny_folder_is_local_folder (folder)) {
2448 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2450 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2451 TnyTransportAccount *traccount = NULL;
2452 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2453 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2455 ModestTnySendQueueStatus status;
2456 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2457 TnyIterator *iter = tny_list_create_iterator(headers);
2458 g_object_unref(remove_headers);
2459 remove_headers = TNY_LIST(tny_simple_list_new());
2460 while (!tny_iterator_is_done(iter)) {
2462 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2463 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2464 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2465 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2466 tny_list_append(remove_headers, G_OBJECT(hdr));
2468 g_object_unref(hdr);
2470 tny_iterator_next(iter);
2472 g_object_unref(iter);
2473 g_object_unref(traccount);
2477 /* Get account and set it into mail_operation */
2478 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2479 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2480 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2482 /* remove message from folder */
2483 modest_mail_operation_notify_start (self);
2485 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2487 gboolean expunge, leave_on_server;
2488 const gchar *account_name;
2490 TnyAccount *account;
2491 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2493 account = tny_folder_get_account (folder);
2494 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2496 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2499 proto = tny_account_get_proto (account);
2501 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2504 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2505 modest_tny_folder_is_remote_folder (folder) == FALSE)
2511 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2513 g_object_unref (account);
2519 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2521 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2526 g_object_unref (remove_headers);
2528 g_object_unref (header);
2530 g_object_unref (iter);
2532 g_object_unref (folder);
2534 /* Notify about operation end */
2535 modest_mail_operation_notify_end (self);
2539 notify_progress_of_multiple_messages (ModestMailOperation *self,
2541 gint *last_total_bytes,
2542 gint *sum_total_bytes,
2544 gboolean increment_done)
2546 ModestMailOperationPrivate *priv;
2547 ModestMailOperationState *state;
2548 gboolean is_num_bytes = FALSE;
2550 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2552 /* We know that tinymail sends us information about
2553 * transferred bytes with this particular message
2555 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2556 * I just added the 'if' so we don't get runtime warning)
2558 if (status->message)
2559 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2561 state = modest_mail_operation_clone_state (self);
2562 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2563 /* We know that we're in a different message when the
2564 total number of bytes to transfer is different. Of
2565 course it could fail if we're transferring messages
2566 of the same size, but this is a workarround */
2567 if (status->of_total != *last_total_bytes) {
2568 /* We need to increment the done when there is
2569 no information about each individual
2570 message, we need to do this in message
2571 transfers, and we don't do it for getting
2575 *sum_total_bytes += *last_total_bytes;
2576 *last_total_bytes = status->of_total;
2578 state->bytes_done += status->position + *sum_total_bytes;
2579 state->bytes_total = total_bytes;
2581 /* Notify the status change. Only notify about changes
2582 referred to bytes */
2583 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2587 g_slice_free (ModestMailOperationState, state);
2591 transfer_msgs_status_cb (GObject *obj,
2595 XFerMsgsAsyncHelper *helper;
2597 g_return_if_fail (status != NULL);
2598 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2600 helper = (XFerMsgsAsyncHelper *) user_data;
2601 g_return_if_fail (helper != NULL);
2603 /* Notify progress */
2604 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2605 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2610 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2612 XFerMsgsAsyncHelper *helper;
2613 ModestMailOperation *self;
2614 ModestMailOperationPrivate *priv;
2615 TnyIterator *iter = NULL;
2616 TnyHeader *header = NULL;
2618 helper = (XFerMsgsAsyncHelper *) user_data;
2619 self = helper->mail_op;
2621 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2624 priv->error = g_error_copy (err);
2626 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2627 } else if (cancelled) {
2628 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2629 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2630 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2631 _("Error trying to refresh the contents of %s"),
2632 tny_folder_get_name (folder));
2635 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2637 /* Update folder counts */
2638 tny_folder_poke_status (folder);
2639 tny_folder_poke_status (helper->dest_folder);
2643 /* Mark headers as deleted and seen */
2644 if ((helper->delete) &&
2645 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2646 iter = tny_list_create_iterator (helper->headers);
2647 while (!tny_iterator_is_done (iter)) {
2648 header = TNY_HEADER (tny_iterator_get_current (iter));
2649 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2650 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2651 g_object_unref (header);
2653 tny_iterator_next (iter);
2658 /* Notify about operation end */
2659 modest_mail_operation_notify_end (self);
2661 /* If user defined callback function was defined, call it */
2662 if (helper->user_callback) {
2663 /* This is not a GDK lock because we are a Tinymail callback and
2664 * Tinymail already acquires the Gdk lock */
2666 /* no gdk_threads_enter (), CHECKED */
2667 helper->user_callback (self, helper->user_data);
2668 /* no gdk_threads_leave (), CHECKED */
2672 if (helper->headers)
2673 g_object_unref (helper->headers);
2674 if (helper->dest_folder)
2675 g_object_unref (helper->dest_folder);
2676 if (helper->mail_op)
2677 g_object_unref (helper->mail_op);
2679 g_object_unref (folder);
2681 g_object_unref (iter);
2682 g_slice_free (XFerMsgsAsyncHelper, helper);
2686 compute_message_list_size (TnyList *headers)
2691 iter = tny_list_create_iterator (headers);
2692 while (!tny_iterator_is_done (iter)) {
2693 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2694 size += tny_header_get_message_size (header);
2695 g_object_unref (header);
2696 tny_iterator_next (iter);
2698 g_object_unref (iter);
2704 compute_message_array_size (GPtrArray *headers)
2709 for (i = 0; i < headers->len; i++) {
2710 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2711 size += tny_header_get_message_size (header);
2719 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2722 gboolean delete_original,
2723 XferMsgsAsyncUserCallback user_callback,
2726 ModestMailOperationPrivate *priv = NULL;
2727 TnyIterator *iter = NULL;
2728 TnyFolder *src_folder = NULL;
2729 XFerMsgsAsyncHelper *helper = NULL;
2730 TnyHeader *header = NULL;
2731 ModestTnyFolderRules rules = 0;
2733 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2734 g_return_if_fail (headers && TNY_IS_LIST (headers));
2735 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2737 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2738 priv->total = tny_list_get_length (headers);
2740 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2741 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2743 /* Apply folder rules */
2744 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2745 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2746 /* Set status failed and set an error */
2747 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2748 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2749 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2750 _CS("ckct_ib_unable_to_paste_here"));
2751 /* Notify the queue */
2752 modest_mail_operation_notify_end (self);
2756 /* Get source folder */
2757 iter = tny_list_create_iterator (headers);
2758 header = TNY_HEADER (tny_iterator_get_current (iter));
2760 src_folder = tny_header_get_folder (header);
2761 g_object_unref (header);
2763 g_object_unref (iter);
2765 if (src_folder == NULL) {
2766 /* Notify the queue */
2767 modest_mail_operation_notify_end (self);
2769 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2774 /* Check folder source and destination */
2775 if (src_folder == folder) {
2776 /* Set status failed and set an error */
2777 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2778 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2779 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2780 _("mail_in_ui_folder_copy_target_error"));
2782 /* Notify the queue */
2783 modest_mail_operation_notify_end (self);
2786 g_object_unref (src_folder);
2790 /* Create the helper */
2791 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2792 helper->mail_op = g_object_ref(self);
2793 helper->dest_folder = g_object_ref(folder);
2794 helper->headers = g_object_ref(headers);
2795 helper->user_callback = user_callback;
2796 helper->user_data = user_data;
2797 helper->delete = delete_original;
2798 helper->last_total_bytes = 0;
2799 helper->sum_total_bytes = 0;
2800 helper->total_bytes = compute_message_list_size (headers);
2802 /* Get account and set it into mail_operation */
2803 priv->account = modest_tny_folder_get_account (src_folder);
2805 /* Transfer messages */
2806 modest_mail_operation_notify_start (self);
2807 tny_folder_transfer_msgs_async (src_folder,
2812 transfer_msgs_status_cb,
2818 on_refresh_folder (TnyFolder *folder,
2823 RefreshAsyncHelper *helper = NULL;
2824 ModestMailOperation *self = NULL;
2825 ModestMailOperationPrivate *priv = NULL;
2827 helper = (RefreshAsyncHelper *) user_data;
2828 self = helper->mail_op;
2829 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2831 g_return_if_fail(priv!=NULL);
2834 priv->error = g_error_copy (error);
2835 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2840 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2841 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2842 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2843 _("Error trying to refresh the contents of %s"),
2844 tny_folder_get_name (folder));
2848 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2851 /* Call user defined callback, if it exists */
2852 if (helper->user_callback) {
2854 /* This is not a GDK lock because we are a Tinymail callback and
2855 * Tinymail already acquires the Gdk lock */
2856 helper->user_callback (self, folder, helper->user_data);
2860 g_slice_free (RefreshAsyncHelper, helper);
2862 /* Notify about operation end */
2863 modest_mail_operation_notify_end (self);
2864 g_object_unref(self);
2868 on_refresh_folder_status_update (GObject *obj,
2872 RefreshAsyncHelper *helper = NULL;
2873 ModestMailOperation *self = NULL;
2874 ModestMailOperationPrivate *priv = NULL;
2875 ModestMailOperationState *state;
2877 g_return_if_fail (user_data != NULL);
2878 g_return_if_fail (status != NULL);
2879 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2881 helper = (RefreshAsyncHelper *) user_data;
2882 self = helper->mail_op;
2883 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2885 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2887 priv->done = status->position;
2888 priv->total = status->of_total;
2890 state = modest_mail_operation_clone_state (self);
2892 /* This is not a GDK lock because we are a Tinymail callback and
2893 * Tinymail already acquires the Gdk lock */
2894 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2896 g_slice_free (ModestMailOperationState, state);
2900 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2902 RefreshAsyncUserCallback user_callback,
2905 ModestMailOperationPrivate *priv = NULL;
2906 RefreshAsyncHelper *helper = NULL;
2908 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2910 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2912 /* Get account and set it into mail_operation */
2913 priv->account = modest_tny_folder_get_account (folder);
2914 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2916 /* Create the helper */
2917 helper = g_slice_new0 (RefreshAsyncHelper);
2918 helper->mail_op = g_object_ref(self);
2919 helper->user_callback = user_callback;
2920 helper->user_data = user_data;
2922 /* Refresh the folder. TODO: tinymail could issue a status
2923 updates before the callback call then this could happen. We
2924 must review the design */
2925 modest_mail_operation_notify_start (self);
2927 /* notify that the operation was started */
2928 ModestMailOperationState *state;
2929 state = modest_mail_operation_clone_state (self);
2932 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2935 tny_folder_refresh_async (folder,
2937 on_refresh_folder_status_update,
2943 modest_mail_operation_notify_start (ModestMailOperation *self)
2945 ModestMailOperationPrivate *priv = NULL;
2947 g_return_if_fail (self);
2949 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2951 /* Ensure that all the fields are filled correctly */
2952 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
2954 /* Notify the observers about the mail operation. We do not
2955 wrapp this emission because we assume that this function is
2956 always called from within the main lock */
2957 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
2962 * It's used by the mail operation queue to notify the observers
2963 * attached to that signal that the operation finished. We need to use
2964 * that because tinymail does not give us the progress of a given
2965 * operation when it finishes (it directly calls the operation
2969 modest_mail_operation_notify_end (ModestMailOperation *self)
2971 ModestMailOperationPrivate *priv = NULL;
2973 g_return_if_fail (self);
2975 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2977 /* Notify the observers about the mail operation end. We do
2978 not wrapp this emission because we assume that this
2979 function is always called from within the main lock */
2980 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
2982 /* Remove the error user data */
2983 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
2984 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
2988 modest_mail_operation_get_account (ModestMailOperation *self)
2990 ModestMailOperationPrivate *priv = NULL;
2992 g_return_val_if_fail (self, NULL);
2994 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2996 return (priv->account) ? g_object_ref (priv->account) : NULL;
3000 modest_mail_operation_noop (ModestMailOperation *self)
3002 ModestMailOperationPrivate *priv = NULL;
3004 g_return_if_fail (self);
3006 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3007 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3008 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3012 /* This mail operation does nothing actually */
3013 modest_mail_operation_notify_start (self);
3014 modest_mail_operation_notify_end (self);
3019 modest_mail_operation_to_string (ModestMailOperation *self)
3021 const gchar *type, *status, *account_id;
3022 ModestMailOperationPrivate *priv = NULL;
3024 g_return_val_if_fail (self, NULL);
3026 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3028 /* new operations don't have anything interesting */
3029 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3030 return g_strdup_printf ("%p <new operation>", self);
3032 switch (priv->op_type) {
3033 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3034 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3035 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3036 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3037 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3038 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3039 default: type = "UNEXPECTED"; break;
3042 switch (priv->status) {
3043 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3044 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3045 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3046 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3047 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3048 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3049 default: status= "UNEXPECTED"; break;
3052 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3054 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3055 priv->done, priv->total,
3056 priv->error && priv->error->message ? priv->error->message : "");