1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <tny-mime-part.h>
33 #include <tny-store-account.h>
34 #include <tny-folder-store.h>
35 #include <tny-folder-store-query.h>
36 #include <tny-camel-stream.h>
37 #include <tny-camel-pop-store-account.h>
38 #include <tny-camel-pop-folder.h>
39 #include <tny-camel-imap-folder.h>
40 #include <tny-camel-mem-stream.h>
41 #include <tny-simple-list.h>
42 #include <tny-send-queue.h>
43 #include <tny-status.h>
44 #include <tny-folder-observer.h>
45 #include <camel/camel-stream-mem.h>
46 #include <glib/gi18n.h>
47 #include "modest-platform.h"
48 #include "modest-account-mgr-helpers.h"
49 #include <modest-tny-account.h>
50 #include <modest-tny-send-queue.h>
51 #include <modest-runtime.h>
52 #include "modest-text-utils.h"
53 #include "modest-tny-msg.h"
54 #include "modest-tny-folder.h"
55 #include "modest-tny-account-store.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-marshal.h"
58 #include "modest-error.h"
59 #include "modest-mail-operation.h"
60 #include <modest-count-stream.h>
61 #include <libgnomevfs/gnome-vfs.h>
62 #include "modest-utils.h"
67 * Remove all these #ifdef stuff when the tinymail's idle calls become
70 #define TINYMAIL_IDLES_NOT_LOCKED_YET 1
72 /* 'private'/'protected' functions */
73 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
74 static void modest_mail_operation_init (ModestMailOperation *obj);
75 static void modest_mail_operation_finalize (GObject *obj);
77 static void get_msg_async_cb (TnyFolder *folder,
83 static void get_msg_status_cb (GObject *obj,
87 static void modest_mail_operation_notify_start (ModestMailOperation *self);
88 static void modest_mail_operation_notify_end (ModestMailOperation *self);
90 static void notify_progress_of_multiple_messages (ModestMailOperation *self,
92 gint *last_total_bytes,
93 gint *sum_total_bytes,
95 gboolean increment_done);
97 static guint compute_message_list_size (TnyList *headers);
99 static guint compute_message_array_size (GPtrArray *headers);
101 static int compare_headers_by_date (gconstpointer a,
104 enum _ModestMailOperationSignals
106 PROGRESS_CHANGED_SIGNAL,
107 OPERATION_STARTED_SIGNAL,
108 OPERATION_FINISHED_SIGNAL,
112 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
113 struct _ModestMailOperationPrivate {
119 ErrorCheckingUserCallback error_checking;
120 gpointer error_checking_user_data;
121 ErrorCheckingUserDataDestroyer error_checking_user_data_destroyer;
122 ModestMailOperationStatus status;
123 ModestMailOperationTypeOperation op_type;
126 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
127 MODEST_TYPE_MAIL_OPERATION, \
128 ModestMailOperationPrivate))
130 #define CHECK_EXCEPTION(priv, new_status) if (priv->error) {\
131 priv->status = new_status;\
136 GetMsgAsyncUserCallback user_callback;
140 ModestMailOperation *mail_op;
141 GDestroyNotify destroy_notify;
142 gint last_total_bytes;
143 gint sum_total_bytes;
147 typedef struct _RefreshAsyncHelper {
148 ModestMailOperation *mail_op;
149 RefreshAsyncUserCallback user_callback;
151 } RefreshAsyncHelper;
153 typedef struct _XFerMsgsAsyncHelper
155 ModestMailOperation *mail_op;
157 TnyFolder *dest_folder;
158 XferMsgsAsyncUserCallback user_callback;
161 gint last_total_bytes;
162 gint sum_total_bytes;
164 } XFerMsgsAsyncHelper;
166 typedef struct _XFerFolderAsyncHelper
168 ModestMailOperation *mail_op;
169 XferFolderAsyncUserCallback user_callback;
171 } XFerFolderAsyncHelper;
173 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
177 static void modest_mail_operation_create_msg (ModestMailOperation *self,
178 const gchar *from, const gchar *to,
179 const gchar *cc, const gchar *bcc,
180 const gchar *subject, const gchar *plain_body,
181 const gchar *html_body, const GList *attachments_list,
182 const GList *images_list,
183 TnyHeaderFlags priority_flags,
184 ModestMailOperationCreateMsgCallback callback,
187 static gboolean idle_notify_queue (gpointer data);
190 ModestMailOperation *mail_op;
198 GList *attachments_list;
200 TnyHeaderFlags priority_flags;
201 ModestMailOperationCreateMsgCallback callback;
207 ModestMailOperation *mail_op;
209 ModestMailOperationCreateMsgCallback callback;
214 static GObjectClass *parent_class = NULL;
216 static guint signals[NUM_SIGNALS] = {0};
219 modest_mail_operation_get_type (void)
221 static GType my_type = 0;
223 static const GTypeInfo my_info = {
224 sizeof(ModestMailOperationClass),
225 NULL, /* base init */
226 NULL, /* base finalize */
227 (GClassInitFunc) modest_mail_operation_class_init,
228 NULL, /* class finalize */
229 NULL, /* class data */
230 sizeof(ModestMailOperation),
232 (GInstanceInitFunc) modest_mail_operation_init,
235 my_type = g_type_register_static (G_TYPE_OBJECT,
236 "ModestMailOperation",
243 modest_mail_operation_class_init (ModestMailOperationClass *klass)
245 GObjectClass *gobject_class;
246 gobject_class = (GObjectClass*) klass;
248 parent_class = g_type_class_peek_parent (klass);
249 gobject_class->finalize = modest_mail_operation_finalize;
251 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
254 * ModestMailOperation::progress-changed
255 * @self: the #MailOperation that emits the signal
256 * @user_data: user data set when the signal handler was connected
258 * Emitted when the progress of a mail operation changes
260 signals[PROGRESS_CHANGED_SIGNAL] =
261 g_signal_new ("progress-changed",
262 G_TYPE_FROM_CLASS (gobject_class),
264 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
266 g_cclosure_marshal_VOID__POINTER,
267 G_TYPE_NONE, 1, G_TYPE_POINTER);
271 * This signal is issued whenever a mail operation starts, and
272 * starts mean when the tinymail operation is issued. This
273 * means that it could happen that something wrong happens and
274 * the tinymail function is never called. In this situation a
275 * operation-finished will be issued without any
278 signals[OPERATION_STARTED_SIGNAL] =
279 g_signal_new ("operation-started",
280 G_TYPE_FROM_CLASS (gobject_class),
282 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
284 g_cclosure_marshal_VOID__VOID,
289 * This signal is issued whenever a mail operation
290 * finishes. Note that this signal could be issued without any
291 * previous "operation-started" signal, because this last one
292 * is only issued when the tinymail operation is successfully
295 signals[OPERATION_FINISHED_SIGNAL] =
296 g_signal_new ("operation-finished",
297 G_TYPE_FROM_CLASS (gobject_class),
299 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
301 g_cclosure_marshal_VOID__VOID,
306 modest_mail_operation_init (ModestMailOperation *obj)
308 ModestMailOperationPrivate *priv;
310 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
312 priv->account = NULL;
313 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
314 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
319 priv->error_checking = NULL;
320 priv->error_checking_user_data = NULL;
324 modest_mail_operation_finalize (GObject *obj)
326 ModestMailOperationPrivate *priv;
328 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
333 g_error_free (priv->error);
337 g_object_unref (priv->source);
341 g_object_unref (priv->account);
342 priv->account = NULL;
346 G_OBJECT_CLASS(parent_class)->finalize (obj);
350 modest_mail_operation_new (GObject *source)
352 ModestMailOperation *obj;
353 ModestMailOperationPrivate *priv;
355 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
356 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
359 priv->source = g_object_ref(source);
365 modest_mail_operation_new_with_error_handling (GObject *source,
366 ErrorCheckingUserCallback error_handler,
368 ErrorCheckingUserDataDestroyer error_handler_destroyer)
370 ModestMailOperation *obj;
371 ModestMailOperationPrivate *priv;
373 obj = modest_mail_operation_new (source);
374 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
376 g_return_val_if_fail (error_handler != NULL, obj);
377 priv->error_checking = error_handler;
378 priv->error_checking_user_data = user_data;
379 priv->error_checking_user_data_destroyer = error_handler_destroyer;
385 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
387 ModestMailOperationPrivate *priv;
389 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
391 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
392 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
394 /* Call the user callback */
395 if (priv->error_checking != NULL)
396 priv->error_checking (self, priv->error_checking_user_data);
400 ModestMailOperationTypeOperation
401 modest_mail_operation_get_type_operation (ModestMailOperation *self)
403 ModestMailOperationPrivate *priv;
405 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
406 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
408 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
410 return priv->op_type;
414 modest_mail_operation_is_mine (ModestMailOperation *self,
417 ModestMailOperationPrivate *priv;
419 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
422 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
423 if (priv->source == NULL) return FALSE;
425 return priv->source == me;
429 modest_mail_operation_get_source (ModestMailOperation *self)
431 ModestMailOperationPrivate *priv;
433 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
436 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
438 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
442 return (priv->source) ? g_object_ref (priv->source) : NULL;
445 ModestMailOperationStatus
446 modest_mail_operation_get_status (ModestMailOperation *self)
448 ModestMailOperationPrivate *priv;
450 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
451 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
452 MODEST_MAIL_OPERATION_STATUS_INVALID);
454 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
456 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
457 return MODEST_MAIL_OPERATION_STATUS_INVALID;
464 modest_mail_operation_get_error (ModestMailOperation *self)
466 ModestMailOperationPrivate *priv;
468 g_return_val_if_fail (self, NULL);
469 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
471 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
474 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
482 modest_mail_operation_cancel (ModestMailOperation *self)
484 ModestMailOperationPrivate *priv;
485 gboolean canceled = FALSE;
487 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
489 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
491 /* Note that if we call cancel with an already canceled mail
492 operation the progress changed signal won't be emitted */
493 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
497 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
499 /* Cancel the mail operation */
500 g_return_val_if_fail (priv->account, FALSE);
501 tny_account_cancel (priv->account);
503 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
504 ModestTnySendQueue *queue;
505 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
507 /* Cancel the sending of the following next messages */
508 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, NULL);
515 modest_mail_operation_get_task_done (ModestMailOperation *self)
517 ModestMailOperationPrivate *priv;
519 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
522 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
527 modest_mail_operation_get_task_total (ModestMailOperation *self)
529 ModestMailOperationPrivate *priv;
531 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
534 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
539 modest_mail_operation_is_finished (ModestMailOperation *self)
541 ModestMailOperationPrivate *priv;
542 gboolean retval = FALSE;
544 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
547 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
549 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
550 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
551 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
552 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
562 * Creates an image of the current state of a mail operation, the
563 * caller must free it
565 static ModestMailOperationState *
566 modest_mail_operation_clone_state (ModestMailOperation *self)
568 ModestMailOperationState *state;
569 ModestMailOperationPrivate *priv;
571 /* FIXME: this should be fixed properly
573 * in some cases, priv was NULL, so checking here to
576 g_return_val_if_fail (self, NULL);
577 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
578 g_return_val_if_fail (priv, NULL);
583 state = g_slice_new (ModestMailOperationState);
585 state->status = priv->status;
586 state->op_type = priv->op_type;
587 state->done = priv->done;
588 state->total = priv->total;
589 state->finished = modest_mail_operation_is_finished (self);
590 state->bytes_done = 0;
591 state->bytes_total = 0;
596 /* ******************************************************************* */
597 /* ************************** SEND ACTIONS ************************* */
598 /* ******************************************************************* */
601 modest_mail_operation_send_mail (ModestMailOperation *self,
602 TnyTransportAccount *transport_account,
605 TnySendQueue *send_queue = NULL;
606 ModestMailOperationPrivate *priv;
608 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
609 g_return_if_fail (transport_account && TNY_IS_TRANSPORT_ACCOUNT (transport_account));
610 g_return_if_fail (msg && TNY_IS_MSG (msg));
612 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
614 /* Get account and set it into mail_operation */
615 priv->account = g_object_ref (transport_account);
616 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
620 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
621 if (!TNY_IS_SEND_QUEUE(send_queue)) {
622 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
623 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
624 "modest: could not find send queue for account\n");
625 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
626 modest_mail_operation_notify_end (self);
629 /* Add the msg to the queue */
630 modest_mail_operation_notify_start (self);
632 tny_send_queue_add_async (send_queue, msg, NULL, NULL, NULL);
634 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
635 modest_mail_operation_notify_end (self);
642 idle_create_msg_cb (gpointer idle_data)
644 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
646 /* This is a GDK lock because we are an idle callback and
647 * info->callback can contain Gtk+ code */
649 gdk_threads_enter (); /* CHECKED */
650 info->callback (info->mail_op, info->msg, info->userdata);
652 g_object_unref (info->mail_op);
654 g_object_unref (info->msg);
655 g_slice_free (CreateMsgIdleInfo, info);
656 gdk_threads_leave (); /* CHECKED */
662 create_msg_thread (gpointer thread_data)
664 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
665 TnyMsg *new_msg = NULL;
666 ModestMailOperationPrivate *priv;
668 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
669 if (info->html_body == NULL) {
670 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
671 info->bcc, info->subject, info->plain_body,
672 info->attachments_list);
674 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
675 info->bcc, info->subject, info->html_body,
676 info->plain_body, info->attachments_list,
683 /* Set priority flags in message */
684 header = tny_msg_get_header (new_msg);
685 tny_header_set_flag (header, info->priority_flags);
687 /* Set attachment flags in message */
688 if (info->attachments_list != NULL)
689 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
691 g_object_unref (G_OBJECT(header));
693 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
694 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
695 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
696 "modest: failed to create a new msg\n");
704 g_free (info->plain_body);
705 g_free (info->html_body);
706 g_free (info->subject);
707 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
708 g_list_free (info->attachments_list);
709 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
710 g_list_free (info->images_list);
712 if (info->callback) {
713 CreateMsgIdleInfo *idle_info;
714 idle_info = g_slice_new0 (CreateMsgIdleInfo);
715 idle_info->mail_op = g_object_ref (info->mail_op);
716 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
717 idle_info->callback = info->callback;
718 idle_info->userdata = info->userdata;
719 g_idle_add (idle_create_msg_cb, idle_info);
721 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
724 g_object_unref (info->mail_op);
725 g_slice_free (CreateMsgInfo, info);
726 if (new_msg) g_object_unref(new_msg);
732 modest_mail_operation_create_msg (ModestMailOperation *self,
733 const gchar *from, const gchar *to,
734 const gchar *cc, const gchar *bcc,
735 const gchar *subject, const gchar *plain_body,
736 const gchar *html_body,
737 const GList *attachments_list,
738 const GList *images_list,
739 TnyHeaderFlags priority_flags,
740 ModestMailOperationCreateMsgCallback callback,
743 ModestMailOperationPrivate *priv;
744 CreateMsgInfo *info = NULL;
746 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
748 info = g_slice_new0 (CreateMsgInfo);
749 info->mail_op = g_object_ref (self);
751 info->from = g_strdup (from);
752 info->to = g_strdup (to);
753 info->cc = g_strdup (cc);
754 info->bcc = g_strdup (bcc);
755 info->subject = g_strdup (subject);
756 info->plain_body = g_strdup (plain_body);
757 info->html_body = g_strdup (html_body);
758 info->attachments_list = g_list_copy ((GList *) attachments_list);
759 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
760 info->images_list = g_list_copy ((GList *) images_list);
761 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
762 info->priority_flags = priority_flags;
764 info->callback = callback;
765 info->userdata = userdata;
767 g_thread_create (create_msg_thread, info, FALSE, NULL);
772 TnyTransportAccount *transport_account;
777 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
781 ModestMailOperationPrivate *priv = NULL;
782 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
783 TnyFolder *draft_folder = NULL;
784 TnyFolder *outbox_folder = NULL;
785 TnyHeader *header = NULL;
792 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
795 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
796 modest_mail_operation_notify_end (self);
800 /* Call mail operation */
801 modest_mail_operation_send_mail (self, info->transport_account, msg);
803 if (info->draft_msg != NULL) {
804 TnyFolder *folder = NULL;
805 TnyFolder *src_folder = NULL;
806 TnyFolderType folder_type;
807 TnyTransportAccount *transport_account = NULL;
809 /* To remove the old mail from its source folder, we need to get the
810 * transport account of the original draft message (the transport account
811 * might have been changed by the user) */
812 header = tny_msg_get_header (info->draft_msg);
813 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
814 modest_runtime_get_account_store(), header);
815 if (transport_account == NULL)
816 transport_account = g_object_ref(info->transport_account);
817 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
818 TNY_FOLDER_TYPE_DRAFTS);
819 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
820 TNY_FOLDER_TYPE_OUTBOX);
821 g_object_unref(transport_account);
824 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
828 if (!outbox_folder) {
829 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
834 folder = tny_msg_get_folder (info->draft_msg);
835 if (folder == NULL) goto end;
836 folder_type = modest_tny_folder_guess_folder_type (folder);
838 if (folder_type == TNY_FOLDER_TYPE_INVALID)
839 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
841 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
842 src_folder = outbox_folder;
844 src_folder = draft_folder;
846 /* Note: This can fail (with a warning) if the message is not really already in a folder,
847 * because this function requires it to have a UID. */
848 tny_folder_remove_msg (src_folder, header, NULL);
850 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
851 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
853 g_object_unref (folder);
858 g_object_unref (header);
862 g_object_unref (info->draft_msg);
864 g_object_unref (draft_folder);
866 g_object_unref (outbox_folder);
867 if (info->transport_account)
868 g_object_unref (info->transport_account);
869 g_slice_free (SendNewMailInfo, info);
873 modest_mail_operation_send_new_mail (ModestMailOperation *self,
874 TnyTransportAccount *transport_account,
876 const gchar *from, const gchar *to,
877 const gchar *cc, const gchar *bcc,
878 const gchar *subject, const gchar *plain_body,
879 const gchar *html_body,
880 const GList *attachments_list,
881 const GList *images_list,
882 TnyHeaderFlags priority_flags)
884 ModestMailOperationPrivate *priv = NULL;
885 SendNewMailInfo *info;
887 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
888 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
890 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
891 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
892 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
893 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
895 /* Check parametters */
897 /* Set status failed and set an error */
898 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
899 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
900 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
901 _("Error trying to send a mail. You need to set at least one recipient"));
904 info = g_slice_new0 (SendNewMailInfo);
905 info->transport_account = transport_account;
906 if (transport_account)
907 g_object_ref (transport_account);
908 info->draft_msg = draft_msg;
910 g_object_ref (draft_msg);
913 modest_mail_operation_notify_start (self);
914 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
915 attachments_list, images_list, priority_flags,
916 modest_mail_operation_send_new_mail_cb, info);
922 TnyTransportAccount *transport_account;
924 SaveToDraftstCallback callback;
928 ModestMailOperation *mailop;
929 } SaveToDraftsAddMsgInfo;
932 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
937 ModestMailOperationPrivate *priv = NULL;
938 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
940 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
943 g_warning ("%s: priv->error != NULL", __FUNCTION__);
944 g_error_free(priv->error);
947 priv->error = (err == NULL) ? NULL : g_error_copy(err);
949 if ((!priv->error) && (info->draft_msg != NULL)) {
950 TnyHeader *header = tny_msg_get_header (info->draft_msg);
951 TnyFolder *src_folder = tny_header_get_folder (header);
953 /* Remove the old draft */
954 tny_folder_remove_msg (src_folder, header, NULL);
956 /* Synchronize to expunge and to update the msg counts */
957 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
958 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
960 g_object_unref (G_OBJECT(header));
961 g_object_unref (G_OBJECT(src_folder));
965 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
967 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
969 /* Call the user callback */
971 info->callback (info->mailop, info->msg, info->user_data);
973 if (info->transport_account)
974 g_object_unref (G_OBJECT(info->transport_account));
976 g_object_unref (G_OBJECT (info->draft_msg));
978 g_object_unref (G_OBJECT(info->drafts));
980 g_object_unref (G_OBJECT (info->msg));
982 modest_mail_operation_notify_end (info->mailop);
983 g_object_unref(info->mailop);
984 g_slice_free (SaveToDraftsAddMsgInfo, info);
989 TnyTransportAccount *transport_account;
991 SaveToDraftstCallback callback;
996 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1000 TnyFolder *drafts = NULL;
1001 ModestMailOperationPrivate *priv = NULL;
1002 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1004 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1007 if (!(priv->error)) {
1008 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1009 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1010 "modest: failed to create a new msg\n");
1013 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1014 TNY_FOLDER_TYPE_DRAFTS);
1015 if (!drafts && !(priv->error)) {
1016 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1017 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1018 "modest: failed to create a new msg\n");
1023 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1024 cb_info->transport_account = g_object_ref(info->transport_account);
1025 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1026 cb_info->callback = info->callback;
1027 cb_info->user_data = info->user_data;
1028 cb_info->drafts = g_object_ref(drafts);
1029 cb_info->msg = g_object_ref(msg);
1030 cb_info->mailop = g_object_ref(self);
1031 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1034 /* Call the user callback */
1035 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1037 info->callback (self, msg, info->user_data);
1038 modest_mail_operation_notify_end (self);
1042 g_object_unref (G_OBJECT(drafts));
1043 if (info->draft_msg)
1044 g_object_unref (G_OBJECT (info->draft_msg));
1045 if (info->transport_account)
1046 g_object_unref (G_OBJECT(info->transport_account));
1047 g_slice_free (SaveToDraftsInfo, info);
1051 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1052 TnyTransportAccount *transport_account,
1054 const gchar *from, const gchar *to,
1055 const gchar *cc, const gchar *bcc,
1056 const gchar *subject, const gchar *plain_body,
1057 const gchar *html_body,
1058 const GList *attachments_list,
1059 const GList *images_list,
1060 TnyHeaderFlags priority_flags,
1061 SaveToDraftstCallback callback,
1064 ModestMailOperationPrivate *priv = NULL;
1065 SaveToDraftsInfo *info = NULL;
1067 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1068 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1070 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1072 /* Get account and set it into mail_operation */
1073 priv->account = g_object_ref (transport_account);
1074 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1076 info = g_slice_new0 (SaveToDraftsInfo);
1077 info->transport_account = g_object_ref (transport_account);
1078 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1079 info->callback = callback;
1080 info->user_data = user_data;
1082 modest_mail_operation_notify_start (self);
1083 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1084 attachments_list, images_list, priority_flags,
1085 modest_mail_operation_save_to_drafts_cb, info);
1090 ModestMailOperation *mail_op;
1091 TnyMimePart *mime_part;
1093 GetMimePartSizeCallback callback;
1095 } GetMimePartSizeInfo;
1097 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1098 /* We use this folder observer to track the headers that have been
1099 * added to a folder */
1102 TnyList *new_headers;
1103 } InternalFolderObserver;
1106 GObjectClass parent;
1107 } InternalFolderObserverClass;
1109 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1111 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1112 internal_folder_observer,
1114 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1118 foreach_add_item (gpointer header, gpointer user_data)
1120 tny_list_prepend (TNY_LIST (user_data),
1121 g_object_ref (G_OBJECT (header)));
1124 /* This is the method that looks for new messages in a folder */
1126 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1128 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1130 TnyFolderChangeChanged changed;
1132 changed = tny_folder_change_get_changed (change);
1134 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1137 /* Get added headers */
1138 list = tny_simple_list_new ();
1139 tny_folder_change_get_added_headers (change, list);
1141 /* Add them to the folder observer */
1142 tny_list_foreach (list, foreach_add_item,
1143 derived->new_headers);
1145 g_object_unref (G_OBJECT (list));
1150 internal_folder_observer_init (InternalFolderObserver *self)
1152 self->new_headers = tny_simple_list_new ();
1155 internal_folder_observer_finalize (GObject *object)
1157 InternalFolderObserver *self;
1159 self = (InternalFolderObserver *) object;
1160 g_object_unref (self->new_headers);
1162 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1165 tny_folder_observer_init (TnyFolderObserverIface *iface)
1167 iface->update = internal_folder_observer_update;
1170 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1172 GObjectClass *object_class;
1174 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1175 object_class = (GObjectClass*) klass;
1176 object_class->finalize = internal_folder_observer_finalize;
1181 ModestMailOperation *mail_op;
1182 gchar *account_name;
1183 UpdateAccountCallback callback;
1188 TnyFolderObserver *inbox_observer;
1189 RetrieveAllCallback retrieve_all_cb;
1190 } UpdateAccountInfo;
1194 destroy_update_account_info (UpdateAccountInfo *info)
1196 g_free (info->account_name);
1197 g_object_unref (info->folders);
1198 g_object_unref (info->mail_op);
1199 g_slice_free (UpdateAccountInfo, info);
1203 update_account_get_msg_async_cb (TnyFolder *folder,
1209 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1211 /* Just delete the helper. Don't do anything with the new
1212 msg. There is also no need to check for errors */
1213 g_object_unref (msg_info->mail_op);
1214 g_object_unref (msg_info->header);
1215 g_slice_free (GetMsgInfo, msg_info);
1219 inbox_refreshed_cb (TnyFolder *inbox,
1224 UpdateAccountInfo *info;
1225 ModestMailOperationPrivate *priv;
1226 TnyIterator *new_headers_iter;
1227 GPtrArray *new_headers_array = NULL;
1228 gint max_size, retrieve_limit, i;
1229 ModestAccountMgr *mgr;
1230 ModestAccountRetrieveType retrieve_type;
1231 TnyList *new_headers = NULL;
1232 gboolean headers_only, ignore_limit;
1233 TnyTransportAccount *transport_account;
1235 info = (UpdateAccountInfo *) user_data;
1236 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1237 mgr = modest_runtime_get_account_mgr ();
1239 if (canceled || err || !inbox) {
1240 /* Try to send anyway */
1244 /* Get the message max size */
1245 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1246 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1248 max_size = G_MAXINT;
1250 max_size = max_size * KB;
1252 /* Create the new headers array. We need it to sort the
1253 new headers by date */
1254 new_headers_array = g_ptr_array_new ();
1255 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1256 while (!tny_iterator_is_done (new_headers_iter)) {
1257 TnyHeader *header = NULL;
1259 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1260 /* Apply per-message size limits */
1261 if (tny_header_get_message_size (header) < max_size)
1262 g_ptr_array_add (new_headers_array, g_object_ref (header));
1264 g_object_unref (header);
1265 tny_iterator_next (new_headers_iter);
1267 g_object_unref (new_headers_iter);
1268 tny_folder_remove_observer (inbox, info->inbox_observer);
1269 g_object_unref (info->inbox_observer);
1270 info->inbox_observer = NULL;
1272 /* Update the last updated key, even if we don't have to get new headers */
1273 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1275 if (new_headers_array->len == 0)
1278 /* Get per-account message amount retrieval limit */
1279 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1280 if (retrieve_limit == 0)
1281 retrieve_limit = G_MAXINT;
1283 /* Get per-account retrieval type */
1284 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1285 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1288 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1290 /* Ask the users if they want to retrieve all the messages
1291 even though the limit was exceeded */
1292 ignore_limit = FALSE;
1293 if (new_headers_array->len > retrieve_limit) {
1294 /* Ask the user if a callback has been specified and
1295 if the mail operation has a source (this means that
1296 was invoked by the user and not automatically by a
1298 if (info->retrieve_all_cb && priv->source)
1299 ignore_limit = info->retrieve_all_cb (priv->source,
1300 new_headers_array->len,
1304 if (!headers_only) {
1306 const gint msg_list_size = compute_message_array_size (new_headers_array);
1310 priv->total = new_headers_array->len;
1312 priv->total = MIN (new_headers_array->len, retrieve_limit);
1313 while (msg_num < priv->total) {
1314 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1315 TnyFolder *folder = tny_header_get_folder (header);
1316 GetMsgInfo *msg_info;
1318 /* Create the message info */
1319 msg_info = g_slice_new0 (GetMsgInfo);
1320 msg_info->mail_op = g_object_ref (info->mail_op);
1321 msg_info->header = g_object_ref (header);
1322 msg_info->total_bytes = msg_list_size;
1324 /* Get message in an async way */
1325 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1326 get_msg_status_cb, msg_info);
1328 g_object_unref (folder);
1334 /* Copy the headers to a list and free the array */
1335 new_headers = tny_simple_list_new ();
1336 for (i=0; i < new_headers_array->len; i++) {
1337 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1338 tny_list_append (new_headers, G_OBJECT (header));
1340 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1341 g_ptr_array_free (new_headers_array, FALSE);
1344 /* Get the transport account */
1345 transport_account = (TnyTransportAccount *)
1346 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1347 info->account_name);
1349 if (transport_account) {
1350 ModestTnySendQueue *send_queue;
1354 send_queue = modest_runtime_get_send_queue (transport_account);
1356 /* Get outbox folder */
1357 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1358 num_messages = tny_folder_get_all_count (outbox);
1359 g_object_unref (outbox);
1361 if (num_messages != 0) {
1363 g_object_unref (priv->account);
1365 /* Reenable suspended items */
1366 modest_tny_send_queue_wakeup (MODEST_TNY_SEND_QUEUE (send_queue));
1369 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (send_queue));
1373 /* Check if the operation was a success */
1375 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1377 /* Set the account back to not busy */
1378 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1380 /* Call the user callback */
1382 info->callback (info->mail_op, new_headers, info->user_data);
1384 /* Notify about operation end */
1385 modest_mail_operation_notify_end (info->mail_op);
1389 g_object_unref (new_headers);
1390 destroy_update_account_info (info);
1394 recurse_folders_async_cb (TnyFolderStore *folder_store,
1400 UpdateAccountInfo *info;
1401 ModestMailOperationPrivate *priv;
1403 info = (UpdateAccountInfo *) user_data;
1404 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1406 if (err || canceled) {
1407 /* Try to continue anyway */
1409 TnyIterator *iter = tny_list_create_iterator (list);
1410 while (!tny_iterator_is_done (iter)) {
1411 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1412 TnyList *folders = tny_simple_list_new ();
1414 /* Add to the list of all folders */
1415 tny_list_append (info->folders, (GObject *) folder);
1417 /* Add pending call */
1418 info->pending_calls++;
1420 tny_folder_store_get_folders_async (folder, folders, NULL,
1421 recurse_folders_async_cb,
1424 g_object_unref (G_OBJECT (folder));
1426 tny_iterator_next (iter);
1428 g_object_unref (G_OBJECT (iter));
1429 g_object_unref (G_OBJECT (list));
1432 /* Remove my own pending call */
1433 info->pending_calls--;
1435 /* This means that we have all the folders */
1436 if (info->pending_calls == 0) {
1437 TnyIterator *iter_all_folders;
1438 TnyFolder *inbox = NULL;
1440 iter_all_folders = tny_list_create_iterator (info->folders);
1442 /* Do a poke status over all folders */
1443 while (!tny_iterator_is_done (iter_all_folders) &&
1444 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1445 TnyFolder *folder = NULL;
1447 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1449 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1450 /* Get a reference to the INBOX */
1451 inbox = g_object_ref (folder);
1453 /* Issue a poke status over the folder */
1455 tny_folder_poke_status (folder);
1458 /* Free and go to next */
1459 g_object_unref (folder);
1460 tny_iterator_next (iter_all_folders);
1462 g_object_unref (iter_all_folders);
1464 /* Refresh the INBOX */
1466 /* Refresh the folder. Our observer receives
1467 * the new emails during folder refreshes, so
1468 * we can use observer->new_headers
1470 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1471 tny_folder_add_observer (inbox, info->inbox_observer);
1473 /* Refresh the INBOX */
1474 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1475 g_object_unref (inbox);
1477 /* We could not perform the inbox refresh but
1478 we'll try to send mails anyway */
1479 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1485 modest_mail_operation_update_account (ModestMailOperation *self,
1486 const gchar *account_name,
1488 RetrieveAllCallback retrieve_all_cb,
1489 UpdateAccountCallback callback,
1492 UpdateAccountInfo *info = NULL;
1493 ModestMailOperationPrivate *priv = NULL;
1494 ModestTnyAccountStore *account_store = NULL;
1495 TnyStoreAccount *store_account = NULL;
1497 ModestMailOperationState *state;
1499 /* Init mail operation */
1500 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1503 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1504 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1506 /* Get the store account */
1507 account_store = modest_runtime_get_account_store ();
1508 store_account = (TnyStoreAccount *)
1509 modest_tny_account_store_get_server_account (account_store,
1511 TNY_ACCOUNT_TYPE_STORE);
1512 priv->account = g_object_ref (store_account);
1514 /* Create the helper object */
1515 info = g_slice_new0 (UpdateAccountInfo);
1516 info->pending_calls = 1;
1517 info->folders = tny_simple_list_new ();
1518 info->mail_op = g_object_ref (self);
1519 info->poke_all = poke_all;
1520 info->account_name = g_strdup (account_name);
1521 info->callback = callback;
1522 info->user_data = user_data;
1523 info->retrieve_all_cb = retrieve_all_cb;
1525 /* Set account busy */
1526 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1527 modest_mail_operation_notify_start (self);
1529 /* notify about the start of the operation */
1530 state = modest_mail_operation_clone_state (self);
1534 /* Start notifying progress */
1535 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1536 g_slice_free (ModestMailOperationState, state);
1538 /* Get all folders and continue in the callback */
1539 folders = tny_simple_list_new ();
1540 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1542 recurse_folders_async_cb,
1547 * Used to notify the queue from the main
1548 * loop. We call it inside an idle call to achieve that
1551 idle_notify_queue (gpointer data)
1553 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1555 gdk_threads_enter ();
1556 modest_mail_operation_notify_end (mail_op);
1557 gdk_threads_leave ();
1558 g_object_unref (mail_op);
1564 compare_headers_by_date (gconstpointer a,
1567 TnyHeader **header1, **header2;
1568 time_t sent1, sent2;
1570 header1 = (TnyHeader **) a;
1571 header2 = (TnyHeader **) b;
1573 sent1 = tny_header_get_date_sent (*header1);
1574 sent2 = tny_header_get_date_sent (*header2);
1576 /* We want the most recent ones (greater time_t) at the
1585 /* ******************************************************************* */
1586 /* ************************** STORE ACTIONS ************************* */
1587 /* ******************************************************************* */
1590 ModestMailOperation *mail_op;
1591 CreateFolderUserCallback callback;
1597 create_folder_cb (TnyFolderStore *parent_folder,
1599 TnyFolder *new_folder,
1603 ModestMailOperationPrivate *priv;
1604 CreateFolderInfo *info;
1606 info = (CreateFolderInfo *) user_data;
1607 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1609 if (canceled || err) {
1610 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1612 priv->error = g_error_copy (err);
1614 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1615 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1618 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1621 /* The user will unref the new_folder */
1623 info->callback (info->mail_op, parent_folder,
1624 new_folder, info->user_data);
1626 /* Notify about operation end */
1627 modest_mail_operation_notify_end (info->mail_op);
1630 g_object_unref (info->mail_op);
1631 g_slice_free (CreateFolderInfo, info);
1635 modest_mail_operation_create_folder (ModestMailOperation *self,
1636 TnyFolderStore *parent,
1638 CreateFolderUserCallback callback,
1641 ModestMailOperationPrivate *priv;
1643 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1644 g_return_if_fail (name);
1646 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1647 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1648 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1649 g_object_ref (parent) :
1650 modest_tny_folder_get_account (TNY_FOLDER (parent));
1652 /* Check for already existing folder */
1653 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1654 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1655 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1656 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1657 _CS("ckdg_ib_folder_already_exists"));
1661 if (TNY_IS_FOLDER (parent)) {
1662 /* Check folder rules */
1663 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1664 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1665 /* Set status failed and set an error */
1666 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1667 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1668 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1669 _("mail_in_ui_folder_create_error"));
1673 if (!strcmp (name, " ") || strchr (name, '/')) {
1674 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1675 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1676 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1677 _("mail_in_ui_folder_create_error"));
1681 CreateFolderInfo *info;
1683 info = g_slice_new0 (CreateFolderInfo);
1684 info->mail_op = g_object_ref (self);
1685 info->callback = callback;
1686 info->user_data = user_data;
1688 modest_mail_operation_notify_start (self);
1690 /* Create the folder */
1691 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1694 /* Call the user callback anyway */
1696 callback (self, parent, NULL, user_data);
1697 /* Notify about operation end */
1698 modest_mail_operation_notify_end (self);
1703 modest_mail_operation_remove_folder (ModestMailOperation *self,
1705 gboolean remove_to_trash)
1707 TnyAccount *account;
1708 ModestMailOperationPrivate *priv;
1709 ModestTnyFolderRules rules;
1711 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1712 g_return_if_fail (TNY_IS_FOLDER (folder));
1714 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1716 /* Check folder rules */
1717 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1718 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1719 /* Set status failed and set an error */
1720 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1721 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1722 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1723 _("mail_in_ui_folder_delete_error"));
1727 /* Get the account */
1728 account = modest_tny_folder_get_account (folder);
1729 priv->account = g_object_ref(account);
1730 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1732 /* Delete folder or move to trash */
1733 if (remove_to_trash) {
1734 TnyFolder *trash_folder = NULL;
1735 trash_folder = modest_tny_account_get_special_folder (account,
1736 TNY_FOLDER_TYPE_TRASH);
1737 /* TODO: error_handling */
1739 modest_mail_operation_notify_start (self);
1740 modest_mail_operation_xfer_folder (self, folder,
1741 TNY_FOLDER_STORE (trash_folder),
1743 g_object_unref (trash_folder);
1745 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1748 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1750 modest_mail_operation_notify_start (self);
1751 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1752 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1755 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1757 g_object_unref (parent);
1759 g_warning ("%s: could not get parent folder", __FUNCTION__);
1761 g_object_unref (G_OBJECT (account));
1764 /* Notify about operation end */
1765 modest_mail_operation_notify_end (self);
1769 transfer_folder_status_cb (GObject *obj,
1773 ModestMailOperation *self;
1774 ModestMailOperationPrivate *priv;
1775 ModestMailOperationState *state;
1776 XFerFolderAsyncHelper *helper;
1778 g_return_if_fail (status != NULL);
1779 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1781 helper = (XFerFolderAsyncHelper *) user_data;
1782 g_return_if_fail (helper != NULL);
1784 self = helper->mail_op;
1785 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1787 priv->done = status->position;
1788 priv->total = status->of_total;
1790 state = modest_mail_operation_clone_state (self);
1792 /* This is not a GDK lock because we are a Tinymail callback
1793 * which is already GDK locked by Tinymail */
1795 /* no gdk_threads_enter (), CHECKED */
1797 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1799 /* no gdk_threads_leave (), CHECKED */
1801 g_slice_free (ModestMailOperationState, state);
1806 transfer_folder_cb (TnyFolder *folder,
1808 TnyFolderStore *into,
1809 TnyFolder *new_folder,
1813 XFerFolderAsyncHelper *helper;
1814 ModestMailOperation *self = NULL;
1815 ModestMailOperationPrivate *priv = NULL;
1817 helper = (XFerFolderAsyncHelper *) user_data;
1818 g_return_if_fail (helper != NULL);
1820 self = helper->mail_op;
1821 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1824 priv->error = g_error_copy (err);
1826 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1827 } else if (cancelled) {
1828 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1829 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1830 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1831 _("Transference of %s was cancelled."),
1832 tny_folder_get_name (folder));
1835 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1838 /* Notify about operation end */
1839 modest_mail_operation_notify_end (self);
1841 /* If user defined callback function was defined, call it */
1842 if (helper->user_callback) {
1844 /* This is not a GDK lock because we are a Tinymail callback
1845 * which is already GDK locked by Tinymail */
1847 /* no gdk_threads_enter (), CHECKED */
1848 helper->user_callback (self, new_folder, helper->user_data);
1849 /* no gdk_threads_leave () , CHECKED */
1853 g_object_unref (helper->mail_op);
1854 g_slice_free (XFerFolderAsyncHelper, helper);
1859 * This function checks if the new name is a valid name for our local
1860 * folders account. The new name could not be the same than then name
1861 * of any of the mandatory local folders
1863 * We can not rely on tinymail because tinymail does not check the
1864 * name of the virtual folders that the account could have in the case
1865 * that we're doing a rename (because it directly calls Camel which
1866 * knows nothing about our virtual folders).
1868 * In the case of an actual copy/move (i.e. move/copy a folder between
1869 * accounts) tinymail uses the tny_folder_store_create_account which
1870 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1871 * checks the new name of the folder, so this call in that case
1872 * wouldn't be needed. *But* NOTE that if tinymail changes its
1873 * implementation (if folder transfers within the same account is no
1874 * longer implemented as a rename) this call will allow Modest to work
1877 * If the new name is not valid, this function will set the status to
1878 * failed and will set also an error in the mail operation
1881 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1882 TnyFolderStore *into,
1883 const gchar *new_name)
1885 if (TNY_IS_ACCOUNT (into) &&
1886 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1887 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1889 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1890 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1891 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1892 _CS("ckdg_ib_folder_already_exists"));
1899 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1901 TnyFolderStore *parent,
1902 gboolean delete_original,
1903 XferFolderAsyncUserCallback user_callback,
1906 ModestMailOperationPrivate *priv = NULL;
1907 ModestTnyFolderRules parent_rules = 0, rules;
1908 XFerFolderAsyncHelper *helper = NULL;
1909 const gchar *folder_name = NULL;
1910 const gchar *error_msg;
1912 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1913 g_return_if_fail (TNY_IS_FOLDER (folder));
1914 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1916 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1917 folder_name = tny_folder_get_name (folder);
1919 /* Set the error msg */
1920 error_msg = _("mail_in_ui_folder_move_target_error");
1922 /* Get account and set it into mail_operation */
1923 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1924 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1925 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1927 /* Get folder rules */
1928 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1929 if (TNY_IS_FOLDER (parent))
1930 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1932 /* Apply operation constraints */
1933 if ((gpointer) parent == (gpointer) folder ||
1934 (!TNY_IS_FOLDER_STORE (parent)) ||
1935 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1938 } else if (TNY_IS_FOLDER (parent) &&
1939 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
1943 } else if (TNY_IS_FOLDER (parent) &&
1944 TNY_IS_FOLDER_STORE (folder) &&
1945 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
1946 TNY_FOLDER_STORE (folder))) {
1947 /* Do not move a parent into a child */
1949 } else if (TNY_IS_FOLDER_STORE (parent) &&
1950 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
1951 /* Check that the new folder name is not used by any
1954 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
1955 /* Check that the new folder name is not used by any
1956 special local folder */
1959 /* Create the helper */
1960 helper = g_slice_new0 (XFerFolderAsyncHelper);
1961 helper->mail_op = g_object_ref (self);
1962 helper->user_callback = user_callback;
1963 helper->user_data = user_data;
1965 /* Move/Copy folder */
1966 modest_mail_operation_notify_start (self);
1967 tny_folder_copy_async (folder,
1969 tny_folder_get_name (folder),
1972 transfer_folder_status_cb,
1978 /* Set status failed and set an error */
1979 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1980 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1981 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1984 /* Call the user callback if exists */
1986 user_callback (self, NULL, user_data);
1988 /* Notify the queue */
1989 modest_mail_operation_notify_end (self);
1993 modest_mail_operation_rename_folder (ModestMailOperation *self,
1996 XferFolderAsyncUserCallback user_callback,
1999 ModestMailOperationPrivate *priv;
2000 ModestTnyFolderRules rules;
2001 XFerFolderAsyncHelper *helper;
2003 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2004 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2005 g_return_if_fail (name);
2007 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2009 /* Get account and set it into mail_operation */
2010 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2011 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2013 /* Check folder rules */
2014 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2015 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2017 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2020 TnyFolderStore *into;
2022 into = tny_folder_get_folder_store (folder);
2024 /* Check that the new folder name is not used by any
2025 special local folder */
2026 if (new_name_valid_if_local_account (priv, into, name)) {
2027 /* Create the helper */
2028 helper = g_slice_new0 (XFerFolderAsyncHelper);
2029 helper->mail_op = g_object_ref(self);
2030 helper->user_callback = user_callback;
2031 helper->user_data = user_data;
2033 /* Rename. Camel handles folder subscription/unsubscription */
2034 modest_mail_operation_notify_start (self);
2035 tny_folder_copy_async (folder, into, name, TRUE,
2037 transfer_folder_status_cb,
2042 g_object_unref (into);
2047 /* Set status failed and set an error */
2048 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2049 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2050 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2051 _("FIXME: unable to rename"));
2054 user_callback (self, NULL, user_data);
2056 /* Notify about operation end */
2057 modest_mail_operation_notify_end (self);
2060 /* ******************************************************************* */
2061 /* ************************** MSG ACTIONS ************************* */
2062 /* ******************************************************************* */
2065 modest_mail_operation_get_msg (ModestMailOperation *self,
2067 GetMsgAsyncUserCallback user_callback,
2070 GetMsgInfo *helper = NULL;
2072 ModestMailOperationPrivate *priv;
2074 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2075 g_return_if_fail (TNY_IS_HEADER (header));
2077 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2078 folder = tny_header_get_folder (header);
2080 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2084 /* Get account and set it into mail_operation */
2085 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2087 /* Check for cached messages */
2088 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2089 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2091 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2093 /* Create the helper */
2094 helper = g_slice_new0 (GetMsgInfo);
2095 helper->header = g_object_ref (header);
2096 helper->mail_op = g_object_ref (self);
2097 helper->user_callback = user_callback;
2098 helper->user_data = user_data;
2099 helper->destroy_notify = NULL;
2100 helper->last_total_bytes = 0;
2101 helper->sum_total_bytes = 0;
2102 helper->total_bytes = tny_header_get_message_size (header);
2104 modest_mail_operation_notify_start (self);
2106 /* notify about the start of the operation */
2107 ModestMailOperationState *state;
2108 state = modest_mail_operation_clone_state (self);
2111 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2114 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2116 g_object_unref (G_OBJECT (folder));
2120 get_msg_status_cb (GObject *obj,
2124 GetMsgInfo *helper = NULL;
2126 g_return_if_fail (status != NULL);
2127 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2129 helper = (GetMsgInfo *) user_data;
2130 g_return_if_fail (helper != NULL);
2132 /* Notify progress */
2133 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2134 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2138 get_msg_async_cb (TnyFolder *folder,
2144 GetMsgInfo *info = NULL;
2145 ModestMailOperationPrivate *priv = NULL;
2148 info = (GetMsgInfo *) user_data;
2150 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2154 tny_iterator_next (info->iter);
2155 finished = (tny_iterator_is_done (info->iter));
2157 finished = (priv->done == priv->total) ? TRUE : FALSE;
2161 if (canceled || err) {
2162 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2164 priv->error = g_error_copy ((const GError *) err);
2165 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2168 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2169 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2172 } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
2173 /* Set the success status before calling the user callback */
2174 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2175 } else if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED) {
2181 /* Call the user callback */
2182 if (info->user_callback)
2183 info->user_callback (info->mail_op, info->header, canceled,
2184 msg, err, info->user_data);
2186 /* Notify about operation end if this is the last callback */
2188 /* Free user data */
2189 if (info->destroy_notify)
2190 info->destroy_notify (info->user_data);
2192 /* Notify about operation end */
2193 modest_mail_operation_notify_end (info->mail_op);
2197 g_object_unref (info->iter);
2198 g_object_unref (info->header);
2199 g_object_unref (info->mail_op);
2200 g_slice_free (GetMsgInfo, info);
2201 } else if (info->iter) {
2202 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->iter));
2203 TnyFolder *folder = tny_header_get_folder (header);
2205 g_object_unref (info->header);
2206 info->header = g_object_ref (header);
2208 /* Retrieve the next message */
2209 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, info);
2211 g_object_unref (header);
2212 g_object_unref (folder);
2214 g_warning ("%s: finished != TRUE but no messages left", __FUNCTION__);
2219 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2220 TnyList *header_list,
2221 GetMsgAsyncUserCallback user_callback,
2223 GDestroyNotify notify)
2225 ModestMailOperationPrivate *priv = NULL;
2227 TnyIterator *iter = NULL;
2229 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2231 /* Init mail operation */
2232 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2233 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2234 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2236 priv->total = tny_list_get_length(header_list);
2238 /* Get account and set it into mail_operation */
2239 if (tny_list_get_length (header_list) >= 1) {
2240 TnyIterator *iterator = tny_list_create_iterator (header_list);
2241 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iterator));
2243 TnyFolder *folder = tny_header_get_folder (header);
2245 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2246 g_object_unref (folder);
2248 g_object_unref (header);
2250 g_object_unref (iterator);
2253 msg_list_size = compute_message_list_size (header_list);
2255 modest_mail_operation_notify_start (self);
2256 iter = tny_list_create_iterator (header_list);
2257 if (!tny_iterator_is_done (iter)) {
2258 /* notify about the start of the operation */
2259 ModestMailOperationState *state;
2260 state = modest_mail_operation_clone_state (self);
2263 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2266 GetMsgInfo *msg_info = NULL;
2267 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2268 TnyFolder *folder = tny_header_get_folder (header);
2270 /* Create the message info */
2271 msg_info = g_slice_new0 (GetMsgInfo);
2272 msg_info->mail_op = g_object_ref (self);
2273 msg_info->header = g_object_ref (header);
2274 msg_info->iter = g_object_ref (iter);
2275 msg_info->user_callback = user_callback;
2276 msg_info->user_data = user_data;
2277 msg_info->destroy_notify = notify;
2278 msg_info->last_total_bytes = 0;
2279 msg_info->sum_total_bytes = 0;
2280 msg_info->total_bytes = msg_list_size;
2282 /* The callback will call it per each header */
2283 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2285 /* Free and go on */
2286 g_object_unref (header);
2287 g_object_unref (folder);
2288 g_slice_free (ModestMailOperationState, state);
2290 g_object_unref (iter);
2295 modest_mail_operation_remove_msg (ModestMailOperation *self,
2297 gboolean remove_to_trash /*ignored*/)
2300 ModestMailOperationPrivate *priv;
2302 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2303 g_return_if_fail (TNY_IS_HEADER (header));
2305 if (remove_to_trash)
2306 g_warning ("remove to trash is not implemented");
2308 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2309 folder = tny_header_get_folder (header);
2311 /* Get account and set it into mail_operation */
2312 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2313 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2314 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2316 /* remove message from folder */
2317 tny_folder_remove_msg (folder, header, &(priv->error));
2319 gboolean expunge, leave_on_server;
2320 const gchar *account_name;
2321 TnyAccount *account;
2322 ModestTransportStoreProtocol account_proto;
2324 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2325 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2327 modest_mail_operation_notify_start (self);
2329 /* Get leave on server setting */
2330 account = tny_folder_get_account (folder);
2331 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2333 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2336 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2338 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2339 modest_tny_folder_is_remote_folder (folder) == FALSE)
2345 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2348 g_object_unref (account);
2354 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2356 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2359 g_object_unref (G_OBJECT (folder));
2361 /* Notify about operation end */
2362 modest_mail_operation_notify_end (self);
2366 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2368 gboolean remove_to_trash /*ignored*/)
2370 TnyFolder *folder = NULL;
2371 ModestMailOperationPrivate *priv;
2372 TnyIterator *iter = NULL;
2373 TnyHeader *header = NULL;
2374 TnyList *remove_headers = NULL;
2375 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2377 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2378 g_return_if_fail (TNY_IS_LIST (headers));
2380 if (remove_to_trash)
2381 g_warning ("remove to trash is not implemented");
2383 if (tny_list_get_length(headers) == 0) {
2384 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2385 goto cleanup; /* nothing to do */
2388 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2389 remove_headers = g_object_ref(headers);
2391 /* Get folder from first header and sync it */
2392 iter = tny_list_create_iterator (headers);
2393 header = TNY_HEADER (tny_iterator_get_current (iter));
2395 folder = tny_header_get_folder (header);
2396 if (!TNY_IS_FOLDER(folder)) {
2397 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2401 /* Don't remove messages that are being sent */
2402 if (modest_tny_folder_is_local_folder (folder)) {
2403 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2405 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2406 TnyTransportAccount *traccount = NULL;
2407 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2408 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2410 ModestTnySendQueueStatus status;
2411 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2412 TnyIterator *iter = tny_list_create_iterator(headers);
2413 g_object_unref(remove_headers);
2414 remove_headers = TNY_LIST(tny_simple_list_new());
2415 while (!tny_iterator_is_done(iter)) {
2417 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2418 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2419 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2420 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2421 tny_list_append(remove_headers, G_OBJECT(hdr));
2423 g_object_unref(hdr);
2425 tny_iterator_next(iter);
2427 g_object_unref(iter);
2428 g_object_unref(traccount);
2432 /* Get account and set it into mail_operation */
2433 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2434 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2435 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2437 /* remove message from folder */
2438 modest_mail_operation_notify_start (self);
2440 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2442 gboolean expunge, leave_on_server;
2443 const gchar *account_name;
2445 TnyAccount *account;
2446 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2448 account = tny_folder_get_account (folder);
2449 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2451 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2454 proto = tny_account_get_proto (account);
2456 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2459 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2460 modest_tny_folder_is_remote_folder (folder) == FALSE)
2466 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2468 g_object_unref (account);
2474 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2476 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2481 g_object_unref (remove_headers);
2483 g_object_unref (header);
2485 g_object_unref (iter);
2487 g_object_unref (folder);
2489 /* Notify about operation end */
2490 modest_mail_operation_notify_end (self);
2494 notify_progress_of_multiple_messages (ModestMailOperation *self,
2496 gint *last_total_bytes,
2497 gint *sum_total_bytes,
2499 gboolean increment_done)
2501 ModestMailOperationPrivate *priv;
2502 ModestMailOperationState *state;
2503 gboolean is_num_bytes = FALSE;
2505 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2507 /* We know that tinymail sends us information about
2508 * transferred bytes with this particular message
2510 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2511 * I just added the 'if' so we don't get runtime warning)
2513 if (status->message)
2514 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2516 state = modest_mail_operation_clone_state (self);
2517 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2518 /* We know that we're in a different message when the
2519 total number of bytes to transfer is different. Of
2520 course it could fail if we're transferring messages
2521 of the same size, but this is a workarround */
2522 if (status->of_total != *last_total_bytes) {
2523 /* We need to increment the done when there is
2524 no information about each individual
2525 message, we need to do this in message
2526 transfers, and we don't do it for getting
2530 *sum_total_bytes += *last_total_bytes;
2531 *last_total_bytes = status->of_total;
2533 state->bytes_done += status->position + *sum_total_bytes;
2534 state->bytes_total = total_bytes;
2536 /* Notify the status change. Only notify about changes
2537 referred to bytes */
2538 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2542 g_slice_free (ModestMailOperationState, state);
2546 transfer_msgs_status_cb (GObject *obj,
2550 XFerMsgsAsyncHelper *helper;
2552 g_return_if_fail (status != NULL);
2553 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2555 helper = (XFerMsgsAsyncHelper *) user_data;
2556 g_return_if_fail (helper != NULL);
2558 /* Notify progress */
2559 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2560 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2565 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2567 XFerMsgsAsyncHelper *helper;
2568 ModestMailOperation *self;
2569 ModestMailOperationPrivate *priv;
2570 TnyIterator *iter = NULL;
2571 TnyHeader *header = NULL;
2573 helper = (XFerMsgsAsyncHelper *) user_data;
2574 self = helper->mail_op;
2576 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2579 priv->error = g_error_copy (err);
2581 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2582 } else if (cancelled) {
2583 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2584 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2585 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2586 _("Error trying to refresh the contents of %s"),
2587 tny_folder_get_name (folder));
2590 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2592 /* Update folder counts */
2593 tny_folder_poke_status (folder);
2594 tny_folder_poke_status (helper->dest_folder);
2598 /* Mark headers as deleted and seen */
2599 if ((helper->delete) &&
2600 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2601 iter = tny_list_create_iterator (helper->headers);
2602 while (!tny_iterator_is_done (iter)) {
2603 header = TNY_HEADER (tny_iterator_get_current (iter));
2604 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2605 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2606 g_object_unref (header);
2608 tny_iterator_next (iter);
2613 /* Notify about operation end */
2614 modest_mail_operation_notify_end (self);
2616 /* If user defined callback function was defined, call it */
2617 if (helper->user_callback) {
2618 /* This is not a GDK lock because we are a Tinymail callback and
2619 * Tinymail already acquires the Gdk lock */
2621 /* no gdk_threads_enter (), CHECKED */
2622 helper->user_callback (self, helper->user_data);
2623 /* no gdk_threads_leave (), CHECKED */
2627 if (helper->headers)
2628 g_object_unref (helper->headers);
2629 if (helper->dest_folder)
2630 g_object_unref (helper->dest_folder);
2631 if (helper->mail_op)
2632 g_object_unref (helper->mail_op);
2634 g_object_unref (folder);
2636 g_object_unref (iter);
2637 g_slice_free (XFerMsgsAsyncHelper, helper);
2641 compute_message_list_size (TnyList *headers)
2646 iter = tny_list_create_iterator (headers);
2647 while (!tny_iterator_is_done (iter)) {
2648 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2649 size += tny_header_get_message_size (header);
2650 g_object_unref (header);
2651 tny_iterator_next (iter);
2653 g_object_unref (iter);
2659 compute_message_array_size (GPtrArray *headers)
2664 for (i = 0; i < headers->len; i++) {
2665 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2666 size += tny_header_get_message_size (header);
2674 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2677 gboolean delete_original,
2678 XferMsgsAsyncUserCallback user_callback,
2681 ModestMailOperationPrivate *priv = NULL;
2682 TnyIterator *iter = NULL;
2683 TnyFolder *src_folder = NULL;
2684 XFerMsgsAsyncHelper *helper = NULL;
2685 TnyHeader *header = NULL;
2686 ModestTnyFolderRules rules = 0;
2688 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2689 g_return_if_fail (headers && TNY_IS_LIST (headers));
2690 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2692 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2693 priv->total = tny_list_get_length (headers);
2695 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2696 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2698 /* Apply folder rules */
2699 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2700 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2701 /* Set status failed and set an error */
2702 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2703 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2704 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2705 _CS("ckct_ib_unable_to_paste_here"));
2706 /* Notify the queue */
2707 modest_mail_operation_notify_end (self);
2711 /* Get source folder */
2712 iter = tny_list_create_iterator (headers);
2713 header = TNY_HEADER (tny_iterator_get_current (iter));
2715 src_folder = tny_header_get_folder (header);
2716 g_object_unref (header);
2718 g_object_unref (iter);
2720 if (src_folder == NULL) {
2721 /* Notify the queue */
2722 modest_mail_operation_notify_end (self);
2724 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2729 /* Check folder source and destination */
2730 if (src_folder == folder) {
2731 /* Set status failed and set an error */
2732 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2733 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2734 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2735 _("mail_in_ui_folder_copy_target_error"));
2737 /* Notify the queue */
2738 modest_mail_operation_notify_end (self);
2741 g_object_unref (src_folder);
2745 /* Create the helper */
2746 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2747 helper->mail_op = g_object_ref(self);
2748 helper->dest_folder = g_object_ref(folder);
2749 helper->headers = g_object_ref(headers);
2750 helper->user_callback = user_callback;
2751 helper->user_data = user_data;
2752 helper->delete = delete_original;
2753 helper->last_total_bytes = 0;
2754 helper->sum_total_bytes = 0;
2755 helper->total_bytes = compute_message_list_size (headers);
2757 /* Get account and set it into mail_operation */
2758 priv->account = modest_tny_folder_get_account (src_folder);
2760 /* Transfer messages */
2761 modest_mail_operation_notify_start (self);
2762 tny_folder_transfer_msgs_async (src_folder,
2767 transfer_msgs_status_cb,
2773 on_refresh_folder (TnyFolder *folder,
2778 RefreshAsyncHelper *helper = NULL;
2779 ModestMailOperation *self = NULL;
2780 ModestMailOperationPrivate *priv = NULL;
2782 helper = (RefreshAsyncHelper *) user_data;
2783 self = helper->mail_op;
2784 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2786 g_return_if_fail(priv!=NULL);
2789 priv->error = g_error_copy (error);
2790 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2795 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2796 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2797 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2798 _("Error trying to refresh the contents of %s"),
2799 tny_folder_get_name (folder));
2803 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2806 /* Call user defined callback, if it exists */
2807 if (helper->user_callback) {
2809 /* This is not a GDK lock because we are a Tinymail callback and
2810 * Tinymail already acquires the Gdk lock */
2811 helper->user_callback (self, folder, helper->user_data);
2815 g_slice_free (RefreshAsyncHelper, helper);
2817 /* Notify about operation end */
2818 modest_mail_operation_notify_end (self);
2819 g_object_unref(self);
2823 on_refresh_folder_status_update (GObject *obj,
2827 RefreshAsyncHelper *helper = NULL;
2828 ModestMailOperation *self = NULL;
2829 ModestMailOperationPrivate *priv = NULL;
2830 ModestMailOperationState *state;
2832 g_return_if_fail (user_data != NULL);
2833 g_return_if_fail (status != NULL);
2834 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2836 helper = (RefreshAsyncHelper *) user_data;
2837 self = helper->mail_op;
2838 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2840 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2842 priv->done = status->position;
2843 priv->total = status->of_total;
2845 state = modest_mail_operation_clone_state (self);
2847 /* This is not a GDK lock because we are a Tinymail callback and
2848 * Tinymail already acquires the Gdk lock */
2849 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2851 g_slice_free (ModestMailOperationState, state);
2855 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2857 RefreshAsyncUserCallback user_callback,
2860 ModestMailOperationPrivate *priv = NULL;
2861 RefreshAsyncHelper *helper = NULL;
2863 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2865 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2867 /* Get account and set it into mail_operation */
2868 priv->account = modest_tny_folder_get_account (folder);
2869 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2871 /* Create the helper */
2872 helper = g_slice_new0 (RefreshAsyncHelper);
2873 helper->mail_op = g_object_ref(self);
2874 helper->user_callback = user_callback;
2875 helper->user_data = user_data;
2877 /* Refresh the folder. TODO: tinymail could issue a status
2878 updates before the callback call then this could happen. We
2879 must review the design */
2880 modest_mail_operation_notify_start (self);
2882 /* notify that the operation was started */
2883 ModestMailOperationState *state;
2884 state = modest_mail_operation_clone_state (self);
2887 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2890 tny_folder_refresh_async (folder,
2892 on_refresh_folder_status_update,
2897 run_queue_stop (ModestTnySendQueue *queue,
2898 ModestMailOperation *self)
2900 ModestMailOperationPrivate *priv;
2902 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2903 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2904 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2906 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2908 modest_mail_operation_notify_end (self);
2909 g_signal_handlers_disconnect_by_func (queue, run_queue_stop, self);
2910 g_object_unref (self);
2913 modest_mail_operation_run_queue (ModestMailOperation *self,
2914 ModestTnySendQueue *queue)
2916 ModestMailOperationPrivate *priv;
2918 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2919 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2920 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2922 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2923 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
2924 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
2926 modest_mail_operation_notify_start (self);
2927 g_object_ref (self);
2928 g_signal_connect ((gpointer) queue, "queue-stop", G_CALLBACK (run_queue_stop), (gpointer) self);
2932 sync_folder_finish_callback (TnyFolder *self, gboolean cancelled, GError *err, ModestMailOperation *mail_op)
2934 ModestMailOperationPrivate *priv;
2936 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
2938 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2939 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2941 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2943 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2945 modest_mail_operation_notify_end (mail_op);
2946 g_object_unref (mail_op);
2950 modest_mail_operation_sync_folder (ModestMailOperation *self,
2951 TnyFolder *folder, gboolean expunge)
2953 ModestMailOperationPrivate *priv;
2955 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2956 g_return_if_fail (TNY_IS_FOLDER (folder));
2957 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2959 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2960 priv->account = TNY_ACCOUNT (tny_folder_get_account (folder));
2961 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
2963 modest_mail_operation_notify_start (self);
2964 g_object_ref (self);
2965 tny_folder_sync_async (folder, expunge, (TnyFolderCallback) sync_folder_finish_callback, NULL, self);
2969 modest_mail_operation_notify_start (ModestMailOperation *self)
2971 ModestMailOperationPrivate *priv = NULL;
2973 g_return_if_fail (self);
2975 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2977 /* Ensure that all the fields are filled correctly */
2978 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
2980 /* Notify the observers about the mail operation. We do not
2981 wrapp this emission because we assume that this function is
2982 always called from within the main lock */
2983 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
2988 * It's used by the mail operation queue to notify the observers
2989 * attached to that signal that the operation finished. We need to use
2990 * that because tinymail does not give us the progress of a given
2991 * operation when it finishes (it directly calls the operation
2995 modest_mail_operation_notify_end (ModestMailOperation *self)
2997 ModestMailOperationPrivate *priv = NULL;
2999 g_return_if_fail (self);
3001 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3003 /* Notify the observers about the mail operation end. We do
3004 not wrapp this emission because we assume that this
3005 function is always called from within the main lock */
3006 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3008 /* Remove the error user data */
3009 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3010 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3014 modest_mail_operation_get_account (ModestMailOperation *self)
3016 ModestMailOperationPrivate *priv = NULL;
3018 g_return_val_if_fail (self, NULL);
3020 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3022 return (priv->account) ? g_object_ref (priv->account) : NULL;
3026 modest_mail_operation_noop (ModestMailOperation *self)
3028 ModestMailOperationPrivate *priv = NULL;
3030 g_return_if_fail (self);
3032 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3033 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3034 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3038 /* This mail operation does nothing actually */
3039 modest_mail_operation_notify_start (self);
3040 modest_mail_operation_notify_end (self);
3045 modest_mail_operation_to_string (ModestMailOperation *self)
3047 const gchar *type, *status, *account_id;
3048 ModestMailOperationPrivate *priv = NULL;
3050 g_return_val_if_fail (self, NULL);
3052 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3054 /* new operations don't have anything interesting */
3055 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3056 return g_strdup_printf ("%p <new operation>", self);
3058 switch (priv->op_type) {
3059 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3060 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3061 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3062 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3063 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3064 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3065 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3066 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3067 default: type = "UNEXPECTED"; break;
3070 switch (priv->status) {
3071 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3072 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3073 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3074 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3075 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3076 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3077 default: status= "UNEXPECTED"; break;
3080 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3082 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3083 priv->done, priv->total,
3084 priv->error && priv->error->message ? priv->error->message : "");