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 */
510 g_return_val_if_fail (priv->account, FALSE);
511 tny_account_cancel (priv->account);
513 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
514 ModestTnySendQueue *queue;
515 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
517 /* Cancel the sending of the following next messages */
518 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, NULL);
525 modest_mail_operation_get_task_done (ModestMailOperation *self)
527 ModestMailOperationPrivate *priv;
529 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
532 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
537 modest_mail_operation_get_task_total (ModestMailOperation *self)
539 ModestMailOperationPrivate *priv;
541 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
544 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
549 modest_mail_operation_is_finished (ModestMailOperation *self)
551 ModestMailOperationPrivate *priv;
552 gboolean retval = FALSE;
554 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
557 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
559 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
560 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
561 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
562 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
572 * Creates an image of the current state of a mail operation, the
573 * caller must free it
575 static ModestMailOperationState *
576 modest_mail_operation_clone_state (ModestMailOperation *self)
578 ModestMailOperationState *state;
579 ModestMailOperationPrivate *priv;
581 /* FIXME: this should be fixed properly
583 * in some cases, priv was NULL, so checking here to
586 g_return_val_if_fail (self, NULL);
587 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
588 g_return_val_if_fail (priv, NULL);
593 state = g_slice_new (ModestMailOperationState);
595 state->status = priv->status;
596 state->op_type = priv->op_type;
597 state->done = priv->done;
598 state->total = priv->total;
599 state->finished = modest_mail_operation_is_finished (self);
600 state->bytes_done = 0;
601 state->bytes_total = 0;
606 /* ******************************************************************* */
607 /* ************************** SEND ACTIONS ************************* */
608 /* ******************************************************************* */
611 modest_mail_operation_send_mail (ModestMailOperation *self,
612 TnyTransportAccount *transport_account,
615 TnySendQueue *send_queue = NULL;
616 ModestMailOperationPrivate *priv;
619 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
620 g_return_if_fail (transport_account && TNY_IS_TRANSPORT_ACCOUNT (transport_account));
621 g_return_if_fail (msg && TNY_IS_MSG (msg));
623 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
625 /* Get account and set it into mail_operation */
626 priv->account = g_object_ref (transport_account);
627 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
631 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
632 if (!TNY_IS_SEND_QUEUE(send_queue)) {
633 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
634 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
635 "modest: could not find send queue for account\n");
636 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
637 modest_mail_operation_notify_end (self);
640 /* Add the msg to the queue */
641 modest_mail_operation_notify_start (self);
643 info = g_slice_new0 (SendMsgInfo);
645 info->mail_op = g_object_ref (self);
646 info->msg = g_object_ref (msg);
647 info->msg_sent_handler = g_signal_connect (G_OBJECT (send_queue), "msg-sent",
648 G_CALLBACK (send_mail_msg_sent_handler), info);
649 info->error_happened_handler = g_signal_connect (G_OBJECT (send_queue), "error-happened",
650 G_CALLBACK (send_mail_error_happened_handler), info);
652 modest_tny_send_queue_add (MODEST_TNY_SEND_QUEUE(send_queue),
656 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
662 common_send_mail_operation_end (TnySendQueue *queue, TnyMsg *msg,
665 g_signal_handler_disconnect (queue, info->msg_sent_handler);
666 g_signal_handler_disconnect (queue, info->error_happened_handler);
668 g_object_unref (info->msg);
669 modest_mail_operation_notify_end (info->mail_op);
670 g_object_unref (info->mail_op);
672 g_slice_free (SendMsgInfo, info);
676 send_mail_msg_sent_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
677 guint nth, guint total, gpointer userdata)
679 SendMsgInfo *info = (SendMsgInfo *) userdata;
680 TnyHeader *hdr1, *hdr2;
681 const char *msgid1, *msgid2;
682 hdr1 = tny_msg_get_header(msg);
683 hdr2 = tny_msg_get_header(info->msg);
684 msgid1 = tny_header_get_message_id(hdr1);
685 msgid2 = tny_header_get_message_id(hdr2);
686 if (msgid1 == NULL) msgid1 = "(null)";
687 if (msgid2 == NULL) msgid2 = "(null)";
689 if (!strcmp (msgid1, msgid2)) {
690 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
691 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
693 common_send_mail_operation_end (queue, msg, info);
695 g_object_unref(G_OBJECT(hdr1));
696 g_object_unref(G_OBJECT(hdr2));
700 send_mail_error_happened_handler (TnySendQueue *queue, TnyHeader *header, TnyMsg *msg,
701 GError *error, gpointer userdata)
703 SendMsgInfo *info = (SendMsgInfo *) userdata;
704 TnyHeader *hdr1, *hdr2;
705 const char *msgid1, *msgid2;
707 if (!TNY_IS_MSG(msg)) {
708 g_warning ("%s: did not receive a valid msg", __FUNCTION__);
712 hdr1 = tny_msg_get_header(msg);
713 hdr2 = tny_msg_get_header(info->msg);
714 msgid1 = tny_header_get_message_id(hdr1);
715 msgid2 = tny_header_get_message_id(hdr2);
716 if (msgid1 == NULL) msgid1 = "(null)";
717 if (msgid2 == NULL) msgid2 = "(null)";
719 if (!strcmp (msgid1, msgid2)) {
720 ModestMailOperationPrivate *priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
721 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
722 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
723 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
724 "modest: send mail failed\n");
726 common_send_mail_operation_end (queue, msg, info);
728 g_object_unref(G_OBJECT(hdr1));
729 g_object_unref(G_OBJECT(hdr2));
734 idle_create_msg_cb (gpointer idle_data)
736 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
738 /* This is a GDK lock because we are an idle callback and
739 * info->callback can contain Gtk+ code */
741 gdk_threads_enter (); /* CHECKED */
742 info->callback (info->mail_op, info->msg, info->userdata);
744 g_object_unref (info->mail_op);
746 g_object_unref (info->msg);
747 g_slice_free (CreateMsgIdleInfo, info);
748 gdk_threads_leave (); /* CHECKED */
754 create_msg_thread (gpointer thread_data)
756 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
757 TnyMsg *new_msg = NULL;
758 ModestMailOperationPrivate *priv;
760 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
761 if (info->html_body == NULL) {
762 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
763 info->bcc, info->subject, info->plain_body,
764 info->attachments_list);
766 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
767 info->bcc, info->subject, info->html_body,
768 info->plain_body, info->attachments_list,
775 /* Set priority flags in message */
776 header = tny_msg_get_header (new_msg);
777 tny_header_set_flag (header, info->priority_flags);
779 /* Set attachment flags in message */
780 if (info->attachments_list != NULL)
781 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
783 g_object_unref (G_OBJECT(header));
785 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
786 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
787 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
788 "modest: failed to create a new msg\n");
796 g_free (info->plain_body);
797 g_free (info->html_body);
798 g_free (info->subject);
799 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
800 g_list_free (info->attachments_list);
801 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
802 g_list_free (info->images_list);
804 if (info->callback) {
805 CreateMsgIdleInfo *idle_info;
806 idle_info = g_slice_new0 (CreateMsgIdleInfo);
807 idle_info->mail_op = g_object_ref (info->mail_op);
808 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
809 idle_info->callback = info->callback;
810 idle_info->userdata = info->userdata;
811 g_idle_add (idle_create_msg_cb, idle_info);
813 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
816 g_object_unref (info->mail_op);
817 g_slice_free (CreateMsgInfo, info);
818 if (new_msg) g_object_unref(new_msg);
823 modest_mail_operation_create_msg (ModestMailOperation *self,
824 const gchar *from, const gchar *to,
825 const gchar *cc, const gchar *bcc,
826 const gchar *subject, const gchar *plain_body,
827 const gchar *html_body,
828 const GList *attachments_list,
829 const GList *images_list,
830 TnyHeaderFlags priority_flags,
831 ModestMailOperationCreateMsgCallback callback,
834 CreateMsgInfo *info = NULL;
836 info = g_slice_new0 (CreateMsgInfo);
837 info->mail_op = g_object_ref (self);
839 info->from = g_strdup (from);
840 info->to = g_strdup (to);
841 info->cc = g_strdup (cc);
842 info->bcc = g_strdup (bcc);
843 info->subject = g_strdup (subject);
844 info->plain_body = g_strdup (plain_body);
845 info->html_body = g_strdup (html_body);
846 info->attachments_list = g_list_copy ((GList *) attachments_list);
847 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
848 info->images_list = g_list_copy ((GList *) images_list);
849 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
850 info->priority_flags = priority_flags;
852 info->callback = callback;
853 info->userdata = userdata;
855 g_thread_create (create_msg_thread, info, FALSE, NULL);
860 TnyTransportAccount *transport_account;
865 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
869 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
870 TnyFolder *draft_folder = NULL;
871 TnyFolder *outbox_folder = NULL;
872 TnyHeader *header = NULL;
879 /* Call mail operation */
880 modest_mail_operation_send_mail (self, info->transport_account, msg);
882 if (info->draft_msg != NULL) {
883 TnyFolder *folder = NULL;
884 TnyFolder *src_folder = NULL;
885 TnyFolderType folder_type;
886 TnyTransportAccount *transport_account = NULL;
888 /* To remove the old mail from its source folder, we need to get the
889 * transport account of the original draft message (the transport account
890 * might have been changed by the user) */
891 header = tny_msg_get_header (info->draft_msg);
892 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
893 modest_runtime_get_account_store(), header);
894 if (transport_account == NULL)
895 transport_account = g_object_ref(info->transport_account);
896 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
897 TNY_FOLDER_TYPE_DRAFTS);
898 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
899 TNY_FOLDER_TYPE_OUTBOX);
900 g_object_unref(transport_account);
903 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
907 if (!outbox_folder) {
908 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
913 folder = tny_msg_get_folder (info->draft_msg);
914 if (folder == NULL) goto end;
915 folder_type = modest_tny_folder_guess_folder_type (folder);
917 if (folder_type == TNY_FOLDER_TYPE_INVALID)
918 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
920 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
921 src_folder = outbox_folder;
923 src_folder = draft_folder;
925 /* Note: This can fail (with a warning) if the message is not really already in a folder,
926 * because this function requires it to have a UID. */
927 tny_folder_remove_msg (src_folder, header, NULL);
929 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
930 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
932 g_object_unref (folder);
937 g_object_unref (header);
941 g_object_unref (info->draft_msg);
943 g_object_unref (draft_folder);
945 g_object_unref (outbox_folder);
946 if (info->transport_account)
947 g_object_unref (info->transport_account);
948 g_slice_free (SendNewMailInfo, info);
952 modest_mail_operation_send_new_mail (ModestMailOperation *self,
953 TnyTransportAccount *transport_account,
955 const gchar *from, const gchar *to,
956 const gchar *cc, const gchar *bcc,
957 const gchar *subject, const gchar *plain_body,
958 const gchar *html_body,
959 const GList *attachments_list,
960 const GList *images_list,
961 TnyHeaderFlags priority_flags)
963 ModestMailOperationPrivate *priv = NULL;
964 SendNewMailInfo *info;
966 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
967 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
969 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
970 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
971 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
972 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
974 /* Check parametters */
976 /* Set status failed and set an error */
977 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
978 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
979 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
980 _("Error trying to send a mail. You need to set at least one recipient"));
983 info = g_slice_new0 (SendNewMailInfo);
984 info->transport_account = transport_account;
985 if (transport_account)
986 g_object_ref (transport_account);
987 info->draft_msg = draft_msg;
989 g_object_ref (draft_msg);
992 modest_mail_operation_notify_start (self);
993 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
994 attachments_list, images_list, priority_flags,
995 modest_mail_operation_send_new_mail_cb, info);
1001 TnyTransportAccount *transport_account;
1003 SaveToDraftstCallback callback;
1007 ModestMailOperation *mailop;
1008 } SaveToDraftsAddMsgInfo;
1011 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
1016 ModestMailOperationPrivate *priv = NULL;
1017 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
1019 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1022 g_warning ("%s: priv->error != NULL", __FUNCTION__);
1023 g_error_free(priv->error);
1026 priv->error = (err == NULL) ? NULL : g_error_copy(err);
1028 if ((!priv->error) && (info->draft_msg != NULL)) {
1029 TnyHeader *header = tny_msg_get_header (info->draft_msg);
1030 TnyFolder *src_folder = tny_header_get_folder (header);
1032 /* Remove the old draft */
1033 tny_folder_remove_msg (src_folder, header, NULL);
1035 /* Synchronize to expunge and to update the msg counts */
1036 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1037 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1039 g_object_unref (G_OBJECT(header));
1040 g_object_unref (G_OBJECT(src_folder));
1044 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1046 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1048 /* Call the user callback */
1050 info->callback (info->mailop, info->msg, info->user_data);
1052 if (info->transport_account)
1053 g_object_unref (G_OBJECT(info->transport_account));
1054 if (info->draft_msg)
1055 g_object_unref (G_OBJECT (info->draft_msg));
1057 g_object_unref (G_OBJECT(info->drafts));
1059 g_object_unref (G_OBJECT (info->msg));
1061 modest_mail_operation_notify_end (info->mailop);
1062 g_object_unref(info->mailop);
1063 g_slice_free (SaveToDraftsAddMsgInfo, info);
1068 TnyTransportAccount *transport_account;
1070 SaveToDraftstCallback callback;
1075 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1079 TnyFolder *drafts = NULL;
1080 ModestMailOperationPrivate *priv = NULL;
1081 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1083 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1086 if (!(priv->error)) {
1087 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1088 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1089 "modest: failed to create a new msg\n");
1092 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1093 TNY_FOLDER_TYPE_DRAFTS);
1094 if (!drafts && !(priv->error)) {
1095 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1096 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1097 "modest: failed to create a new msg\n");
1102 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1103 cb_info->transport_account = g_object_ref(info->transport_account);
1104 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1105 cb_info->callback = info->callback;
1106 cb_info->user_data = info->user_data;
1107 cb_info->drafts = g_object_ref(drafts);
1108 cb_info->msg = g_object_ref(msg);
1109 cb_info->mailop = g_object_ref(self);
1110 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1113 /* Call the user callback */
1114 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1116 info->callback (self, msg, info->user_data);
1117 modest_mail_operation_notify_end (self);
1121 g_object_unref (G_OBJECT(drafts));
1122 if (info->draft_msg)
1123 g_object_unref (G_OBJECT (info->draft_msg));
1124 if (info->transport_account)
1125 g_object_unref (G_OBJECT(info->transport_account));
1126 g_slice_free (SaveToDraftsInfo, info);
1130 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1131 TnyTransportAccount *transport_account,
1133 const gchar *from, const gchar *to,
1134 const gchar *cc, const gchar *bcc,
1135 const gchar *subject, const gchar *plain_body,
1136 const gchar *html_body,
1137 const GList *attachments_list,
1138 const GList *images_list,
1139 TnyHeaderFlags priority_flags,
1140 SaveToDraftstCallback callback,
1143 ModestMailOperationPrivate *priv = NULL;
1144 SaveToDraftsInfo *info = NULL;
1146 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1147 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1149 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1151 /* Get account and set it into mail_operation */
1152 priv->account = g_object_ref (transport_account);
1153 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1155 info = g_slice_new0 (SaveToDraftsInfo);
1156 info->transport_account = g_object_ref (transport_account);
1157 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1158 info->callback = callback;
1159 info->user_data = user_data;
1161 modest_mail_operation_notify_start (self);
1162 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1163 attachments_list, images_list, priority_flags,
1164 modest_mail_operation_save_to_drafts_cb, info);
1169 ModestMailOperation *mail_op;
1170 TnyMimePart *mime_part;
1172 GetMimePartSizeCallback callback;
1174 } GetMimePartSizeInfo;
1176 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1177 /* We use this folder observer to track the headers that have been
1178 * added to a folder */
1181 TnyList *new_headers;
1182 } InternalFolderObserver;
1185 GObjectClass parent;
1186 } InternalFolderObserverClass;
1188 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1190 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1191 internal_folder_observer,
1193 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1197 foreach_add_item (gpointer header, gpointer user_data)
1199 tny_list_prepend (TNY_LIST (user_data),
1200 g_object_ref (G_OBJECT (header)));
1203 /* This is the method that looks for new messages in a folder */
1205 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1207 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1209 TnyFolderChangeChanged changed;
1211 changed = tny_folder_change_get_changed (change);
1213 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1216 /* Get added headers */
1217 list = tny_simple_list_new ();
1218 tny_folder_change_get_added_headers (change, list);
1220 /* Add them to the folder observer */
1221 tny_list_foreach (list, foreach_add_item,
1222 derived->new_headers);
1224 g_object_unref (G_OBJECT (list));
1229 internal_folder_observer_init (InternalFolderObserver *self)
1231 self->new_headers = tny_simple_list_new ();
1234 internal_folder_observer_finalize (GObject *object)
1236 InternalFolderObserver *self;
1238 self = (InternalFolderObserver *) object;
1239 g_object_unref (self->new_headers);
1241 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1244 tny_folder_observer_init (TnyFolderObserverIface *iface)
1246 iface->update_func = internal_folder_observer_update;
1249 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1251 GObjectClass *object_class;
1253 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1254 object_class = (GObjectClass*) klass;
1255 object_class->finalize = internal_folder_observer_finalize;
1260 ModestMailOperation *mail_op;
1261 gchar *account_name;
1262 UpdateAccountCallback callback;
1267 TnyFolderObserver *inbox_observer;
1268 RetrieveAllCallback retrieve_all_cb;
1269 } UpdateAccountInfo;
1273 destroy_update_account_info (UpdateAccountInfo *info)
1275 g_free (info->account_name);
1276 g_object_unref (info->folders);
1277 g_object_unref (info->mail_op);
1278 g_slice_free (UpdateAccountInfo, info);
1282 update_account_get_msg_async_cb (TnyFolder *folder,
1288 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1290 /* Just delete the helper. Don't do anything with the new
1291 msg. There is also no need to check for errors */
1292 g_object_unref (msg_info->mail_op);
1293 g_object_unref (msg_info->header);
1294 g_slice_free (GetMsgInfo, msg_info);
1298 guint error_handler;
1300 ModestMailOperation *mail_op;
1301 } UpdateAccountSendQueueFlushInfo;
1304 update_account_finalize (TnySendQueue *queue,
1305 UpdateAccountSendQueueFlushInfo *info)
1307 ModestMailOperationPrivate *priv;
1309 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1312 /* The last one finish the mail operation */
1313 if (priv->done == priv->total) {
1315 modest_mail_operation_notify_end (info->mail_op);
1318 g_object_unref (info->mail_op);
1319 g_signal_handler_disconnect (queue, info->error_handler);
1320 g_signal_handler_disconnect (queue, info->sent_handler);
1321 g_slice_free (UpdateAccountSendQueueFlushInfo, info);
1326 update_account_on_msg_sent_cb (TnySendQueue *queue,
1333 UpdateAccountSendQueueFlushInfo *info;
1334 info = (UpdateAccountSendQueueFlushInfo *) user_data;
1336 update_account_finalize (queue, info);
1340 update_account_on_error_happened_cb (TnySendQueue *queue,
1346 UpdateAccountSendQueueFlushInfo *info;
1347 info = (UpdateAccountSendQueueFlushInfo *) user_data;
1349 update_account_finalize (queue, info);
1354 inbox_refreshed_cb (TnyFolder *inbox,
1359 UpdateAccountInfo *info;
1360 ModestMailOperationPrivate *priv;
1361 TnyIterator *new_headers_iter;
1362 GPtrArray *new_headers_array = NULL;
1363 gint max_size, retrieve_limit, i;
1364 ModestAccountMgr *mgr;
1365 ModestAccountRetrieveType retrieve_type;
1366 TnyList *new_headers = NULL;
1367 gboolean headers_only, ignore_limit;
1368 TnyTransportAccount *transport_account;
1369 gboolean end_operation;
1371 info = (UpdateAccountInfo *) user_data;
1372 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1373 mgr = modest_runtime_get_account_mgr ();
1375 if (canceled || err || !inbox) {
1376 /* Try to send anyway */
1380 /* Get the message max size */
1381 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1382 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1384 max_size = G_MAXINT;
1386 max_size = max_size * KB;
1388 /* Create the new headers array. We need it to sort the
1389 new headers by date */
1390 new_headers_array = g_ptr_array_new ();
1391 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1392 while (!tny_iterator_is_done (new_headers_iter)) {
1393 TnyHeader *header = NULL;
1395 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1396 /* Apply per-message size limits */
1397 if (tny_header_get_message_size (header) < max_size)
1398 g_ptr_array_add (new_headers_array, g_object_ref (header));
1400 g_object_unref (header);
1401 tny_iterator_next (new_headers_iter);
1403 g_object_unref (new_headers_iter);
1404 tny_folder_remove_observer (inbox, info->inbox_observer);
1405 g_object_unref (info->inbox_observer);
1406 info->inbox_observer = NULL;
1408 /* Update the last updated key, even if we don't have to get new headers */
1409 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1411 if (new_headers_array->len == 0)
1414 /* Get per-account message amount retrieval limit */
1415 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1416 if (retrieve_limit == 0)
1417 retrieve_limit = G_MAXINT;
1419 /* Get per-account retrieval type */
1420 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1421 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1424 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1426 /* Ask the users if they want to retrieve all the messages
1427 even though the limit was exceeded */
1428 ignore_limit = FALSE;
1429 if (new_headers_array->len > retrieve_limit) {
1430 /* Ask the user if a callback has been specified and
1431 if the mail operation has a source (this means that
1432 was invoked by the user and not automatically by a
1434 if (info->retrieve_all_cb && priv->source)
1435 ignore_limit = info->retrieve_all_cb (priv->source,
1436 new_headers_array->len,
1440 if (!headers_only) {
1442 const gint msg_list_size = compute_message_array_size (new_headers_array);
1446 priv->total = new_headers_array->len;
1448 priv->total = MIN (new_headers_array->len, retrieve_limit);
1449 while (msg_num < priv->total) {
1450 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1451 TnyFolder *folder = tny_header_get_folder (header);
1452 GetMsgInfo *msg_info;
1454 /* Create the message info */
1455 msg_info = g_slice_new0 (GetMsgInfo);
1456 msg_info->mail_op = g_object_ref (info->mail_op);
1457 msg_info->header = g_object_ref (header);
1458 msg_info->total_bytes = msg_list_size;
1460 /* Get message in an async way */
1461 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1462 get_msg_status_cb, msg_info);
1464 g_object_unref (folder);
1470 /* Copy the headers to a list and free the array */
1471 new_headers = tny_simple_list_new ();
1472 for (i=0; i < new_headers_array->len; i++) {
1473 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1474 tny_list_append (new_headers, G_OBJECT (header));
1476 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1477 g_ptr_array_free (new_headers_array, FALSE);
1480 /* Get the transport account */
1481 transport_account = (TnyTransportAccount *)
1482 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1483 info->account_name);
1485 if (transport_account) {
1486 ModestTnySendQueue *send_queue;
1490 send_queue = modest_runtime_get_send_queue (transport_account);
1492 /* Get outbox folder */
1493 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1494 num_messages = tny_folder_get_all_count (outbox);
1495 g_object_unref (outbox);
1497 if (num_messages == 0) {
1498 end_operation = TRUE;
1500 UpdateAccountSendQueueFlushInfo *send_info;
1502 end_operation = FALSE;
1505 priv->total = num_messages;
1506 g_object_unref (priv->account);
1507 priv->account = TNY_ACCOUNT (transport_account);
1509 /* Create the info object */
1510 send_info = g_slice_new (UpdateAccountSendQueueFlushInfo);
1511 send_info->error_handler = g_signal_connect (send_queue, "error-happened",
1512 G_CALLBACK (update_account_on_error_happened_cb),
1514 send_info->sent_handler = g_signal_connect (send_queue, "msg-sent",
1515 G_CALLBACK (update_account_on_msg_sent_cb),
1517 send_info->mail_op = g_object_ref (info->mail_op);
1519 /* Reenable suspended items */
1520 modest_tny_send_queue_wakeup (MODEST_TNY_SEND_QUEUE (send_queue));
1523 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (send_queue));
1526 end_operation = TRUE;
1529 /* Check if the operation was a success */
1531 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1533 /* Set the account back to not busy */
1534 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1536 /* Call the user callback */
1538 info->callback (info->mail_op, new_headers, info->user_data);
1540 /* Notify about operation end */
1542 modest_mail_operation_notify_end (info->mail_op);
1546 g_object_unref (new_headers);
1547 destroy_update_account_info (info);
1551 recurse_folders_async_cb (TnyFolderStore *folder_store,
1557 UpdateAccountInfo *info;
1558 ModestMailOperationPrivate *priv;
1560 info = (UpdateAccountInfo *) user_data;
1561 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1563 if (err || canceled) {
1564 /* Try to continue anyway */
1566 TnyIterator *iter = tny_list_create_iterator (list);
1567 while (!tny_iterator_is_done (iter)) {
1568 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1569 TnyList *folders = tny_simple_list_new ();
1571 /* Add to the list of all folders */
1572 tny_list_append (info->folders, (GObject *) folder);
1574 /* Add pending call */
1575 info->pending_calls++;
1577 tny_folder_store_get_folders_async (folder, folders, NULL,
1578 recurse_folders_async_cb,
1581 g_object_unref (G_OBJECT (folder));
1583 tny_iterator_next (iter);
1585 g_object_unref (G_OBJECT (iter));
1586 g_object_unref (G_OBJECT (list));
1589 /* Remove my own pending call */
1590 info->pending_calls--;
1592 /* This means that we have all the folders */
1593 if (info->pending_calls == 0) {
1594 TnyIterator *iter_all_folders;
1595 TnyFolder *inbox = NULL;
1597 iter_all_folders = tny_list_create_iterator (info->folders);
1599 /* Do a poke status over all folders */
1600 while (!tny_iterator_is_done (iter_all_folders) &&
1601 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1602 TnyFolder *folder = NULL;
1604 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1606 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1607 /* Get a reference to the INBOX */
1608 inbox = g_object_ref (folder);
1610 /* Issue a poke status over the folder */
1612 tny_folder_poke_status (folder);
1615 /* Free and go to next */
1616 g_object_unref (folder);
1617 tny_iterator_next (iter_all_folders);
1619 g_object_unref (iter_all_folders);
1621 /* Refresh the INBOX */
1623 /* Refresh the folder. Our observer receives
1624 * the new emails during folder refreshes, so
1625 * we can use observer->new_headers
1627 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1628 tny_folder_add_observer (inbox, info->inbox_observer);
1630 /* Refresh the INBOX */
1631 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1632 g_object_unref (inbox);
1634 /* We could not perform the inbox refresh but
1635 we'll try to send mails anyway */
1636 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1642 modest_mail_operation_update_account (ModestMailOperation *self,
1643 const gchar *account_name,
1645 RetrieveAllCallback retrieve_all_cb,
1646 UpdateAccountCallback callback,
1649 UpdateAccountInfo *info = NULL;
1650 ModestMailOperationPrivate *priv = NULL;
1651 ModestTnyAccountStore *account_store = NULL;
1652 TnyStoreAccount *store_account = NULL;
1654 ModestMailOperationState *state;
1656 /* Init mail operation */
1657 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1660 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1661 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1663 /* Get the store account */
1664 account_store = modest_runtime_get_account_store ();
1665 store_account = (TnyStoreAccount *)
1666 modest_tny_account_store_get_server_account (account_store,
1668 TNY_ACCOUNT_TYPE_STORE);
1669 priv->account = g_object_ref (store_account);
1671 /* Create the helper object */
1672 info = g_slice_new0 (UpdateAccountInfo);
1673 info->pending_calls = 1;
1674 info->folders = tny_simple_list_new ();
1675 info->mail_op = g_object_ref (self);
1676 info->poke_all = poke_all;
1677 info->account_name = g_strdup (account_name);
1678 info->callback = callback;
1679 info->user_data = user_data;
1680 info->retrieve_all_cb = retrieve_all_cb;
1682 /* Set account busy */
1683 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1684 modest_mail_operation_notify_start (self);
1686 /* notify about the start of the operation */
1687 state = modest_mail_operation_clone_state (self);
1691 /* Start notifying progress */
1692 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1693 g_slice_free (ModestMailOperationState, state);
1695 /* Get all folders and continue in the callback */
1696 folders = tny_simple_list_new ();
1697 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1699 recurse_folders_async_cb,
1704 * Used to notify the queue from the main
1705 * loop. We call it inside an idle call to achieve that
1708 idle_notify_queue (gpointer data)
1710 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1712 gdk_threads_enter ();
1713 modest_mail_operation_notify_end (mail_op);
1714 gdk_threads_leave ();
1715 g_object_unref (mail_op);
1721 compare_headers_by_date (gconstpointer a,
1724 TnyHeader **header1, **header2;
1725 time_t sent1, sent2;
1727 header1 = (TnyHeader **) a;
1728 header2 = (TnyHeader **) b;
1730 sent1 = tny_header_get_date_sent (*header1);
1731 sent2 = tny_header_get_date_sent (*header2);
1733 /* We want the most recent ones (greater time_t) at the
1742 /* ******************************************************************* */
1743 /* ************************** STORE ACTIONS ************************* */
1744 /* ******************************************************************* */
1747 ModestMailOperation *mail_op;
1748 CreateFolderUserCallback callback;
1754 create_folder_cb (TnyFolderStore *parent_folder,
1756 TnyFolder *new_folder,
1760 ModestMailOperationPrivate *priv;
1761 CreateFolderInfo *info;
1763 info = (CreateFolderInfo *) user_data;
1764 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1766 if (canceled || err) {
1767 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1769 priv->error = g_error_copy (err);
1771 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1772 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1775 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1778 /* The user will unref the new_folder */
1780 info->callback (info->mail_op, parent_folder,
1781 new_folder, info->user_data);
1783 /* Notify about operation end */
1784 modest_mail_operation_notify_end (info->mail_op);
1787 g_object_unref (info->mail_op);
1788 g_slice_free (CreateFolderInfo, info);
1792 modest_mail_operation_create_folder (ModestMailOperation *self,
1793 TnyFolderStore *parent,
1795 CreateFolderUserCallback callback,
1798 ModestMailOperationPrivate *priv;
1800 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1801 g_return_if_fail (name);
1803 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1804 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1805 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1806 g_object_ref (parent) :
1807 modest_tny_folder_get_account (TNY_FOLDER (parent));
1809 /* Check for already existing folder */
1810 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1811 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1812 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1813 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1814 _CS("ckdg_ib_folder_already_exists"));
1818 if (TNY_IS_FOLDER (parent)) {
1819 /* Check folder rules */
1820 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1821 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1822 /* Set status failed and set an error */
1823 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1824 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1825 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1826 _("mail_in_ui_folder_create_error"));
1830 if (!strcmp (name, " ") || strchr (name, '/')) {
1831 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1832 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1833 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1834 _("mail_in_ui_folder_create_error"));
1838 CreateFolderInfo *info;
1840 info = g_slice_new0 (CreateFolderInfo);
1841 info->mail_op = g_object_ref (self);
1842 info->callback = callback;
1843 info->user_data = user_data;
1845 modest_mail_operation_notify_start (self);
1847 /* Create the folder */
1848 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1851 /* Call the user callback anyway */
1853 callback (self, parent, NULL, user_data);
1854 /* Notify about operation end */
1855 modest_mail_operation_notify_end (self);
1860 modest_mail_operation_remove_folder (ModestMailOperation *self,
1862 gboolean remove_to_trash)
1864 TnyAccount *account;
1865 ModestMailOperationPrivate *priv;
1866 ModestTnyFolderRules rules;
1868 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1869 g_return_if_fail (TNY_IS_FOLDER (folder));
1871 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1873 /* Check folder rules */
1874 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1875 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1876 /* Set status failed and set an error */
1877 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1878 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1879 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1880 _("mail_in_ui_folder_delete_error"));
1884 /* Get the account */
1885 account = modest_tny_folder_get_account (folder);
1886 priv->account = g_object_ref(account);
1887 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1889 /* Delete folder or move to trash */
1890 if (remove_to_trash) {
1891 TnyFolder *trash_folder = NULL;
1892 trash_folder = modest_tny_account_get_special_folder (account,
1893 TNY_FOLDER_TYPE_TRASH);
1894 /* TODO: error_handling */
1896 modest_mail_operation_notify_start (self);
1897 modest_mail_operation_xfer_folder (self, folder,
1898 TNY_FOLDER_STORE (trash_folder),
1900 g_object_unref (trash_folder);
1902 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1905 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1907 modest_mail_operation_notify_start (self);
1908 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1909 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1912 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1914 g_object_unref (parent);
1916 g_warning ("%s: could not get parent folder", __FUNCTION__);
1918 g_object_unref (G_OBJECT (account));
1921 /* Notify about operation end */
1922 modest_mail_operation_notify_end (self);
1926 transfer_folder_status_cb (GObject *obj,
1930 ModestMailOperation *self;
1931 ModestMailOperationPrivate *priv;
1932 ModestMailOperationState *state;
1933 XFerFolderAsyncHelper *helper;
1935 g_return_if_fail (status != NULL);
1936 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1938 helper = (XFerFolderAsyncHelper *) user_data;
1939 g_return_if_fail (helper != NULL);
1941 self = helper->mail_op;
1942 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1944 priv->done = status->position;
1945 priv->total = status->of_total;
1947 state = modest_mail_operation_clone_state (self);
1949 /* This is not a GDK lock because we are a Tinymail callback
1950 * which is already GDK locked by Tinymail */
1952 /* no gdk_threads_enter (), CHECKED */
1954 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1956 /* no gdk_threads_leave (), CHECKED */
1958 g_slice_free (ModestMailOperationState, state);
1963 transfer_folder_cb (TnyFolder *folder,
1965 TnyFolderStore *into,
1966 TnyFolder *new_folder,
1970 XFerFolderAsyncHelper *helper;
1971 ModestMailOperation *self = NULL;
1972 ModestMailOperationPrivate *priv = NULL;
1974 helper = (XFerFolderAsyncHelper *) user_data;
1975 g_return_if_fail (helper != NULL);
1977 self = helper->mail_op;
1978 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1981 priv->error = g_error_copy (err);
1983 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1984 } else if (cancelled) {
1985 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1986 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1987 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1988 _("Transference of %s was cancelled."),
1989 tny_folder_get_name (folder));
1992 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1995 /* Notify about operation end */
1996 modest_mail_operation_notify_end (self);
1998 /* If user defined callback function was defined, call it */
1999 if (helper->user_callback) {
2001 /* This is not a GDK lock because we are a Tinymail callback
2002 * which is already GDK locked by Tinymail */
2004 /* no gdk_threads_enter (), CHECKED */
2005 helper->user_callback (self, new_folder, helper->user_data);
2006 /* no gdk_threads_leave () , CHECKED */
2010 g_object_unref (helper->mail_op);
2011 g_slice_free (XFerFolderAsyncHelper, helper);
2016 * This function checks if the new name is a valid name for our local
2017 * folders account. The new name could not be the same than then name
2018 * of any of the mandatory local folders
2020 * We can not rely on tinymail because tinymail does not check the
2021 * name of the virtual folders that the account could have in the case
2022 * that we're doing a rename (because it directly calls Camel which
2023 * knows nothing about our virtual folders).
2025 * In the case of an actual copy/move (i.e. move/copy a folder between
2026 * accounts) tinymail uses the tny_folder_store_create_account which
2027 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
2028 * checks the new name of the folder, so this call in that case
2029 * wouldn't be needed. *But* NOTE that if tinymail changes its
2030 * implementation (if folder transfers within the same account is no
2031 * longer implemented as a rename) this call will allow Modest to work
2034 * If the new name is not valid, this function will set the status to
2035 * failed and will set also an error in the mail operation
2038 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
2039 TnyFolderStore *into,
2040 const gchar *new_name)
2042 if (TNY_IS_ACCOUNT (into) &&
2043 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
2044 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
2046 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2047 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2048 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2049 _CS("ckdg_ib_folder_already_exists"));
2056 modest_mail_operation_xfer_folder (ModestMailOperation *self,
2058 TnyFolderStore *parent,
2059 gboolean delete_original,
2060 XferFolderAsyncUserCallback user_callback,
2063 ModestMailOperationPrivate *priv = NULL;
2064 ModestTnyFolderRules parent_rules = 0, rules;
2065 XFerFolderAsyncHelper *helper = NULL;
2066 const gchar *folder_name = NULL;
2067 const gchar *error_msg;
2069 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2070 g_return_if_fail (TNY_IS_FOLDER (folder));
2071 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2073 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2074 folder_name = tny_folder_get_name (folder);
2076 /* Set the error msg */
2077 error_msg = _("mail_in_ui_folder_move_target_error");
2079 /* Get account and set it into mail_operation */
2080 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2081 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2082 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2084 /* Get folder rules */
2085 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2086 if (TNY_IS_FOLDER (parent))
2087 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2089 /* Apply operation constraints */
2090 if ((gpointer) parent == (gpointer) folder ||
2091 (!TNY_IS_FOLDER_STORE (parent)) ||
2092 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
2095 } else if (TNY_IS_FOLDER (parent) &&
2096 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2100 } else if (TNY_IS_FOLDER (parent) &&
2101 TNY_IS_FOLDER_STORE (folder) &&
2102 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2103 TNY_FOLDER_STORE (folder))) {
2104 /* Do not move a parent into a child */
2106 } else if (TNY_IS_FOLDER_STORE (parent) &&
2107 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2108 /* Check that the new folder name is not used by any
2111 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2112 /* Check that the new folder name is not used by any
2113 special local folder */
2116 /* Create the helper */
2117 helper = g_slice_new0 (XFerFolderAsyncHelper);
2118 helper->mail_op = g_object_ref (self);
2119 helper->user_callback = user_callback;
2120 helper->user_data = user_data;
2122 /* Move/Copy folder */
2123 modest_mail_operation_notify_start (self);
2124 tny_folder_copy_async (folder,
2126 tny_folder_get_name (folder),
2129 transfer_folder_status_cb,
2135 /* Set status failed and set an error */
2136 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2137 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2138 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2141 /* Call the user callback if exists */
2143 user_callback (self, NULL, user_data);
2145 /* Notify the queue */
2146 modest_mail_operation_notify_end (self);
2150 modest_mail_operation_rename_folder (ModestMailOperation *self,
2153 XferFolderAsyncUserCallback user_callback,
2156 ModestMailOperationPrivate *priv;
2157 ModestTnyFolderRules rules;
2158 XFerFolderAsyncHelper *helper;
2160 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2161 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2162 g_return_if_fail (name);
2164 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2166 /* Get account and set it into mail_operation */
2167 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2168 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2170 /* Check folder rules */
2171 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2172 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2174 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2177 TnyFolderStore *into;
2179 into = tny_folder_get_folder_store (folder);
2181 /* Check that the new folder name is not used by any
2182 special local folder */
2183 if (new_name_valid_if_local_account (priv, into, name)) {
2184 /* Create the helper */
2185 helper = g_slice_new0 (XFerFolderAsyncHelper);
2186 helper->mail_op = g_object_ref(self);
2187 helper->user_callback = user_callback;
2188 helper->user_data = user_data;
2190 /* Rename. Camel handles folder subscription/unsubscription */
2191 modest_mail_operation_notify_start (self);
2192 tny_folder_copy_async (folder, into, name, TRUE,
2194 transfer_folder_status_cb,
2199 g_object_unref (into);
2204 /* Set status failed and set an error */
2205 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2206 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2207 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2208 _("FIXME: unable to rename"));
2211 user_callback (self, NULL, user_data);
2213 /* Notify about operation end */
2214 modest_mail_operation_notify_end (self);
2217 /* ******************************************************************* */
2218 /* ************************** MSG ACTIONS ************************* */
2219 /* ******************************************************************* */
2222 modest_mail_operation_get_msg (ModestMailOperation *self,
2224 GetMsgAsyncUserCallback user_callback,
2227 GetMsgInfo *helper = NULL;
2229 ModestMailOperationPrivate *priv;
2231 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2232 g_return_if_fail (TNY_IS_HEADER (header));
2234 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2235 folder = tny_header_get_folder (header);
2237 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2241 /* Get account and set it into mail_operation */
2242 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2244 /* Check for cached messages */
2245 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2246 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2248 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2250 /* Create the helper */
2251 helper = g_slice_new0 (GetMsgInfo);
2252 helper->header = g_object_ref (header);
2253 helper->mail_op = g_object_ref (self);
2254 helper->user_callback = user_callback;
2255 helper->user_data = user_data;
2256 helper->destroy_notify = NULL;
2257 helper->last_total_bytes = 0;
2258 helper->sum_total_bytes = 0;
2259 helper->total_bytes = tny_header_get_message_size (header);
2261 modest_mail_operation_notify_start (self);
2263 /* notify about the start of the operation */
2264 ModestMailOperationState *state;
2265 state = modest_mail_operation_clone_state (self);
2268 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2271 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2273 g_object_unref (G_OBJECT (folder));
2277 get_msg_status_cb (GObject *obj,
2281 GetMsgInfo *helper = NULL;
2283 g_return_if_fail (status != NULL);
2284 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2286 helper = (GetMsgInfo *) user_data;
2287 g_return_if_fail (helper != NULL);
2289 /* Notify progress */
2290 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2291 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2295 get_msg_async_cb (TnyFolder *folder,
2301 GetMsgInfo *info = NULL;
2302 ModestMailOperationPrivate *priv = NULL;
2305 info = (GetMsgInfo *) user_data;
2307 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2309 finished = (priv->done == priv->total) ? TRUE : FALSE;
2312 if (canceled || err) {
2313 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2315 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2316 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2319 /* Set the success status before calling the user callback */
2320 if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2321 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2325 /* Call the user callback */
2326 if (info->user_callback)
2327 info->user_callback (info->mail_op, info->header, canceled,
2328 msg, err, info->user_data);
2330 /* Notify about operation end if this is the last callback */
2332 /* Free user data */
2333 if (info->destroy_notify)
2334 info->destroy_notify (info->user_data);
2336 /* Notify about operation end */
2337 modest_mail_operation_notify_end (info->mail_op);
2341 g_object_unref (info->header);
2342 g_object_unref (info->mail_op);
2343 g_slice_free (GetMsgInfo, info);
2347 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2348 TnyList *header_list,
2349 GetMsgAsyncUserCallback user_callback,
2351 GDestroyNotify notify)
2353 ModestMailOperationPrivate *priv = NULL;
2355 TnyIterator *iter = NULL;
2357 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2359 /* Init mail operation */
2360 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2361 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2362 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2364 priv->total = tny_list_get_length(header_list);
2366 /* Get account and set it into mail_operation */
2367 if (tny_list_get_length (header_list) >= 1) {
2368 iter = tny_list_create_iterator (header_list);
2369 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2371 TnyFolder *folder = tny_header_get_folder (header);
2373 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2374 g_object_unref (folder);
2376 g_object_unref (header);
2379 if (tny_list_get_length (header_list) == 1) {
2380 g_object_unref (iter);
2385 msg_list_size = compute_message_list_size (header_list);
2387 modest_mail_operation_notify_start (self);
2388 iter = tny_list_create_iterator (header_list);
2389 while (!tny_iterator_is_done (iter)) {
2390 /* notify about the start of the operation */
2391 ModestMailOperationState *state;
2392 state = modest_mail_operation_clone_state (self);
2395 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2398 GetMsgInfo *msg_info = NULL;
2399 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2400 TnyFolder *folder = tny_header_get_folder (header);
2402 /* Create the message info */
2403 msg_info = g_slice_new0 (GetMsgInfo);
2404 msg_info->mail_op = g_object_ref (self);
2405 msg_info->header = g_object_ref (header);
2406 msg_info->user_callback = user_callback;
2407 msg_info->user_data = user_data;
2408 msg_info->destroy_notify = notify;
2409 msg_info->last_total_bytes = 0;
2410 msg_info->sum_total_bytes = 0;
2411 msg_info->total_bytes = msg_list_size;
2413 /* The callback will call it per each header */
2414 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2416 /* Free and go on */
2417 g_object_unref (header);
2418 g_object_unref (folder);
2419 tny_iterator_next (iter);
2421 g_object_unref (iter);
2426 modest_mail_operation_remove_msg (ModestMailOperation *self,
2428 gboolean remove_to_trash /*ignored*/)
2431 ModestMailOperationPrivate *priv;
2433 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2434 g_return_if_fail (TNY_IS_HEADER (header));
2436 if (remove_to_trash)
2437 g_warning ("remove to trash is not implemented");
2439 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2440 folder = tny_header_get_folder (header);
2442 /* Get account and set it into mail_operation */
2443 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2444 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2445 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2447 /* remove message from folder */
2448 tny_folder_remove_msg (folder, header, &(priv->error));
2450 gboolean expunge, leave_on_server;
2451 const gchar *account_name;
2452 TnyAccount *account;
2453 ModestTransportStoreProtocol account_proto;
2455 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2456 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2458 modest_mail_operation_notify_start (self);
2460 /* Get leave on server setting */
2461 account = tny_folder_get_account (folder);
2462 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2464 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2467 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2469 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2470 modest_tny_folder_is_remote_folder (folder) == FALSE)
2476 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2479 g_object_unref (account);
2485 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2487 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2490 g_object_unref (G_OBJECT (folder));
2492 /* Notify about operation end */
2493 modest_mail_operation_notify_end (self);
2497 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2499 gboolean remove_to_trash /*ignored*/)
2501 TnyFolder *folder = NULL;
2502 ModestMailOperationPrivate *priv;
2503 TnyIterator *iter = NULL;
2504 TnyHeader *header = NULL;
2505 TnyList *remove_headers = NULL;
2506 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2508 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2509 g_return_if_fail (TNY_IS_LIST (headers));
2511 if (remove_to_trash)
2512 g_warning ("remove to trash is not implemented");
2514 if (tny_list_get_length(headers) == 0) {
2515 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2516 goto cleanup; /* nothing to do */
2519 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2520 remove_headers = g_object_ref(headers);
2522 /* Get folder from first header and sync it */
2523 iter = tny_list_create_iterator (headers);
2524 header = TNY_HEADER (tny_iterator_get_current (iter));
2526 folder = tny_header_get_folder (header);
2527 if (!TNY_IS_FOLDER(folder)) {
2528 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2532 /* Don't remove messages that are being sent */
2533 if (modest_tny_folder_is_local_folder (folder)) {
2534 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2536 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2537 TnyTransportAccount *traccount = NULL;
2538 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2539 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2541 ModestTnySendQueueStatus status;
2542 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2543 TnyIterator *iter = tny_list_create_iterator(headers);
2544 g_object_unref(remove_headers);
2545 remove_headers = TNY_LIST(tny_simple_list_new());
2546 while (!tny_iterator_is_done(iter)) {
2548 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2549 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2550 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2551 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2552 tny_list_append(remove_headers, G_OBJECT(hdr));
2554 g_object_unref(hdr);
2556 tny_iterator_next(iter);
2558 g_object_unref(iter);
2559 g_object_unref(traccount);
2563 /* Get account and set it into mail_operation */
2564 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2565 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2566 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2568 /* remove message from folder */
2569 modest_mail_operation_notify_start (self);
2571 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2573 gboolean expunge, leave_on_server;
2574 const gchar *account_name;
2576 TnyAccount *account;
2577 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2579 account = tny_folder_get_account (folder);
2580 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2582 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2585 proto = tny_account_get_proto (account);
2587 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2590 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2591 modest_tny_folder_is_remote_folder (folder) == FALSE)
2597 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2599 g_object_unref (account);
2605 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2607 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2612 g_object_unref (remove_headers);
2614 g_object_unref (header);
2616 g_object_unref (iter);
2618 g_object_unref (folder);
2620 /* Notify about operation end */
2621 modest_mail_operation_notify_end (self);
2625 notify_progress_of_multiple_messages (ModestMailOperation *self,
2627 gint *last_total_bytes,
2628 gint *sum_total_bytes,
2630 gboolean increment_done)
2632 ModestMailOperationPrivate *priv;
2633 ModestMailOperationState *state;
2634 gboolean is_num_bytes = FALSE;
2636 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2638 /* We know that tinymail sends us information about
2639 * transferred bytes with this particular message
2641 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2642 * I just added the 'if' so we don't get runtime warning)
2644 if (status->message)
2645 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2647 state = modest_mail_operation_clone_state (self);
2648 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2649 /* We know that we're in a different message when the
2650 total number of bytes to transfer is different. Of
2651 course it could fail if we're transferring messages
2652 of the same size, but this is a workarround */
2653 if (status->of_total != *last_total_bytes) {
2654 /* We need to increment the done when there is
2655 no information about each individual
2656 message, we need to do this in message
2657 transfers, and we don't do it for getting
2661 *sum_total_bytes += *last_total_bytes;
2662 *last_total_bytes = status->of_total;
2664 state->bytes_done += status->position + *sum_total_bytes;
2665 state->bytes_total = total_bytes;
2667 /* Notify the status change. Only notify about changes
2668 referred to bytes */
2669 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2673 g_slice_free (ModestMailOperationState, state);
2677 transfer_msgs_status_cb (GObject *obj,
2681 XFerMsgsAsyncHelper *helper;
2683 g_return_if_fail (status != NULL);
2684 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2686 helper = (XFerMsgsAsyncHelper *) user_data;
2687 g_return_if_fail (helper != NULL);
2689 /* Notify progress */
2690 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2691 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2696 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2698 XFerMsgsAsyncHelper *helper;
2699 ModestMailOperation *self;
2700 ModestMailOperationPrivate *priv;
2701 TnyIterator *iter = NULL;
2702 TnyHeader *header = NULL;
2704 helper = (XFerMsgsAsyncHelper *) user_data;
2705 self = helper->mail_op;
2707 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2710 priv->error = g_error_copy (err);
2712 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2713 } else if (cancelled) {
2714 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2715 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2716 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2717 _("Error trying to refresh the contents of %s"),
2718 tny_folder_get_name (folder));
2721 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2723 /* Update folder counts */
2724 tny_folder_poke_status (folder);
2725 tny_folder_poke_status (helper->dest_folder);
2729 /* Mark headers as deleted and seen */
2730 if ((helper->delete) &&
2731 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2732 iter = tny_list_create_iterator (helper->headers);
2733 while (!tny_iterator_is_done (iter)) {
2734 header = TNY_HEADER (tny_iterator_get_current (iter));
2735 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2736 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2737 g_object_unref (header);
2739 tny_iterator_next (iter);
2744 /* Notify about operation end */
2745 modest_mail_operation_notify_end (self);
2747 /* If user defined callback function was defined, call it */
2748 if (helper->user_callback) {
2749 /* This is not a GDK lock because we are a Tinymail callback and
2750 * Tinymail already acquires the Gdk lock */
2752 /* no gdk_threads_enter (), CHECKED */
2753 helper->user_callback (self, helper->user_data);
2754 /* no gdk_threads_leave (), CHECKED */
2758 if (helper->headers)
2759 g_object_unref (helper->headers);
2760 if (helper->dest_folder)
2761 g_object_unref (helper->dest_folder);
2762 if (helper->mail_op)
2763 g_object_unref (helper->mail_op);
2765 g_object_unref (folder);
2767 g_object_unref (iter);
2768 g_slice_free (XFerMsgsAsyncHelper, helper);
2772 compute_message_list_size (TnyList *headers)
2777 iter = tny_list_create_iterator (headers);
2778 while (!tny_iterator_is_done (iter)) {
2779 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2780 size += tny_header_get_message_size (header);
2781 g_object_unref (header);
2782 tny_iterator_next (iter);
2784 g_object_unref (iter);
2790 compute_message_array_size (GPtrArray *headers)
2795 for (i = 0; i < headers->len; i++) {
2796 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2797 size += tny_header_get_message_size (header);
2805 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2808 gboolean delete_original,
2809 XferMsgsAsyncUserCallback user_callback,
2812 ModestMailOperationPrivate *priv = NULL;
2813 TnyIterator *iter = NULL;
2814 TnyFolder *src_folder = NULL;
2815 XFerMsgsAsyncHelper *helper = NULL;
2816 TnyHeader *header = NULL;
2817 ModestTnyFolderRules rules = 0;
2819 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2820 g_return_if_fail (headers && TNY_IS_LIST (headers));
2821 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2823 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2824 priv->total = tny_list_get_length (headers);
2826 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2827 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2829 /* Apply folder rules */
2830 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2831 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2832 /* Set status failed and set an error */
2833 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2834 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2835 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2836 _CS("ckct_ib_unable_to_paste_here"));
2837 /* Notify the queue */
2838 modest_mail_operation_notify_end (self);
2842 /* Get source folder */
2843 iter = tny_list_create_iterator (headers);
2844 header = TNY_HEADER (tny_iterator_get_current (iter));
2846 src_folder = tny_header_get_folder (header);
2847 g_object_unref (header);
2849 g_object_unref (iter);
2851 if (src_folder == NULL) {
2852 /* Notify the queue */
2853 modest_mail_operation_notify_end (self);
2855 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2860 /* Check folder source and destination */
2861 if (src_folder == folder) {
2862 /* Set status failed and set an error */
2863 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2864 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2865 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2866 _("mail_in_ui_folder_copy_target_error"));
2868 /* Notify the queue */
2869 modest_mail_operation_notify_end (self);
2872 g_object_unref (src_folder);
2876 /* Create the helper */
2877 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2878 helper->mail_op = g_object_ref(self);
2879 helper->dest_folder = g_object_ref(folder);
2880 helper->headers = g_object_ref(headers);
2881 helper->user_callback = user_callback;
2882 helper->user_data = user_data;
2883 helper->delete = delete_original;
2884 helper->last_total_bytes = 0;
2885 helper->sum_total_bytes = 0;
2886 helper->total_bytes = compute_message_list_size (headers);
2888 /* Get account and set it into mail_operation */
2889 priv->account = modest_tny_folder_get_account (src_folder);
2891 /* Transfer messages */
2892 modest_mail_operation_notify_start (self);
2893 tny_folder_transfer_msgs_async (src_folder,
2898 transfer_msgs_status_cb,
2904 on_refresh_folder (TnyFolder *folder,
2909 RefreshAsyncHelper *helper = NULL;
2910 ModestMailOperation *self = NULL;
2911 ModestMailOperationPrivate *priv = NULL;
2913 helper = (RefreshAsyncHelper *) user_data;
2914 self = helper->mail_op;
2915 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2917 g_return_if_fail(priv!=NULL);
2920 priv->error = g_error_copy (error);
2921 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2926 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2927 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2928 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2929 _("Error trying to refresh the contents of %s"),
2930 tny_folder_get_name (folder));
2934 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2937 /* Call user defined callback, if it exists */
2938 if (helper->user_callback) {
2940 /* This is not a GDK lock because we are a Tinymail callback and
2941 * Tinymail already acquires the Gdk lock */
2942 helper->user_callback (self, folder, helper->user_data);
2946 g_slice_free (RefreshAsyncHelper, helper);
2948 /* Notify about operation end */
2949 modest_mail_operation_notify_end (self);
2950 g_object_unref(self);
2954 on_refresh_folder_status_update (GObject *obj,
2958 RefreshAsyncHelper *helper = NULL;
2959 ModestMailOperation *self = NULL;
2960 ModestMailOperationPrivate *priv = NULL;
2961 ModestMailOperationState *state;
2963 g_return_if_fail (user_data != NULL);
2964 g_return_if_fail (status != NULL);
2965 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2967 helper = (RefreshAsyncHelper *) user_data;
2968 self = helper->mail_op;
2969 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2971 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2973 priv->done = status->position;
2974 priv->total = status->of_total;
2976 state = modest_mail_operation_clone_state (self);
2978 /* This is not a GDK lock because we are a Tinymail callback and
2979 * Tinymail already acquires the Gdk lock */
2980 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2982 g_slice_free (ModestMailOperationState, state);
2986 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2988 RefreshAsyncUserCallback user_callback,
2991 ModestMailOperationPrivate *priv = NULL;
2992 RefreshAsyncHelper *helper = NULL;
2994 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2996 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2998 /* Get account and set it into mail_operation */
2999 priv->account = modest_tny_folder_get_account (folder);
3000 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3002 /* Create the helper */
3003 helper = g_slice_new0 (RefreshAsyncHelper);
3004 helper->mail_op = g_object_ref(self);
3005 helper->user_callback = user_callback;
3006 helper->user_data = user_data;
3008 /* Refresh the folder. TODO: tinymail could issue a status
3009 updates before the callback call then this could happen. We
3010 must review the design */
3011 modest_mail_operation_notify_start (self);
3013 /* notify that the operation was started */
3014 ModestMailOperationState *state;
3015 state = modest_mail_operation_clone_state (self);
3018 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3021 tny_folder_refresh_async (folder,
3023 on_refresh_folder_status_update,
3029 modest_mail_operation_notify_start (ModestMailOperation *self)
3031 ModestMailOperationPrivate *priv = NULL;
3033 g_return_if_fail (self);
3035 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3037 /* Ensure that all the fields are filled correctly */
3038 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
3040 /* Notify the observers about the mail operation. We do not
3041 wrapp this emission because we assume that this function is
3042 always called from within the main lock */
3043 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
3048 * It's used by the mail operation queue to notify the observers
3049 * attached to that signal that the operation finished. We need to use
3050 * that because tinymail does not give us the progress of a given
3051 * operation when it finishes (it directly calls the operation
3055 modest_mail_operation_notify_end (ModestMailOperation *self)
3057 ModestMailOperationPrivate *priv = NULL;
3059 g_return_if_fail (self);
3061 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3063 /* Notify the observers about the mail operation end. We do
3064 not wrapp this emission because we assume that this
3065 function is always called from within the main lock */
3066 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3068 /* Remove the error user data */
3069 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3070 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3074 modest_mail_operation_get_account (ModestMailOperation *self)
3076 ModestMailOperationPrivate *priv = NULL;
3078 g_return_val_if_fail (self, NULL);
3080 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3082 return (priv->account) ? g_object_ref (priv->account) : NULL;
3086 modest_mail_operation_noop (ModestMailOperation *self)
3088 ModestMailOperationPrivate *priv = NULL;
3090 g_return_if_fail (self);
3092 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3093 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3094 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3098 /* This mail operation does nothing actually */
3099 modest_mail_operation_notify_start (self);
3100 modest_mail_operation_notify_end (self);
3105 modest_mail_operation_to_string (ModestMailOperation *self)
3107 const gchar *type, *status, *account_id;
3108 ModestMailOperationPrivate *priv = NULL;
3110 g_return_val_if_fail (self, NULL);
3112 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3114 /* new operations don't have anything interesting */
3115 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3116 return g_strdup_printf ("%p <new operation>", self);
3118 switch (priv->op_type) {
3119 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3120 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3121 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3122 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3123 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3124 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3125 default: type = "UNEXPECTED"; break;
3128 switch (priv->status) {
3129 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3130 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3131 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3132 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3133 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3134 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3135 default: status= "UNEXPECTED"; break;
3138 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3140 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3141 priv->done, priv->total,
3142 priv->error && priv->error->message ? priv->error->message : "");