1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <tny-mime-part.h>
33 #include <tny-store-account.h>
34 #include <tny-folder-store.h>
35 #include <tny-folder-store-query.h>
36 #include <tny-camel-stream.h>
37 #include <tny-camel-pop-store-account.h>
38 #include <tny-camel-pop-folder.h>
39 #include <tny-camel-imap-folder.h>
40 #include <tny-camel-mem-stream.h>
41 #include <tny-simple-list.h>
42 #include <tny-send-queue.h>
43 #include <tny-status.h>
44 #include <tny-folder-observer.h>
45 #include <camel/camel-stream-mem.h>
46 #include <glib/gi18n.h>
47 #include "modest-platform.h"
48 #include "modest-account-mgr-helpers.h"
49 #include <modest-tny-account.h>
50 #include <modest-tny-send-queue.h>
51 #include <modest-runtime.h>
52 #include "modest-text-utils.h"
53 #include "modest-tny-msg.h"
54 #include "modest-tny-folder.h"
55 #include "modest-tny-account-store.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-marshal.h"
58 #include "modest-error.h"
59 #include "modest-mail-operation.h"
60 #include <modest-count-stream.h>
61 #include <libgnomevfs/gnome-vfs.h>
62 #include "modest-utils.h"
67 * Remove all these #ifdef stuff when the tinymail's idle calls become
70 #define TINYMAIL_IDLES_NOT_LOCKED_YET 1
72 /* 'private'/'protected' functions */
73 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
74 static void modest_mail_operation_init (ModestMailOperation *obj);
75 static void modest_mail_operation_finalize (GObject *obj);
77 static void get_msg_async_cb (TnyFolder *folder,
83 static void get_msg_status_cb (GObject *obj,
87 static void modest_mail_operation_notify_start (ModestMailOperation *self);
88 static void modest_mail_operation_notify_end (ModestMailOperation *self);
90 static void notify_progress_of_multiple_messages (ModestMailOperation *self,
92 gint *last_total_bytes,
93 gint *sum_total_bytes,
95 gboolean increment_done);
97 static guint compute_message_list_size (TnyList *headers);
99 static guint compute_message_array_size (GPtrArray *headers);
101 static int compare_headers_by_date (gconstpointer a,
104 enum _ModestMailOperationSignals
106 PROGRESS_CHANGED_SIGNAL,
107 OPERATION_STARTED_SIGNAL,
108 OPERATION_FINISHED_SIGNAL,
112 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
113 struct _ModestMailOperationPrivate {
119 ErrorCheckingUserCallback error_checking;
120 gpointer error_checking_user_data;
121 ErrorCheckingUserDataDestroyer error_checking_user_data_destroyer;
122 ModestMailOperationStatus status;
123 ModestMailOperationTypeOperation op_type;
126 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
127 MODEST_TYPE_MAIL_OPERATION, \
128 ModestMailOperationPrivate))
130 #define CHECK_EXCEPTION(priv, new_status) if (priv->error) {\
131 priv->status = new_status;\
136 GetMsgAsyncUserCallback user_callback;
139 ModestMailOperation *mail_op;
140 GDestroyNotify destroy_notify;
141 gint last_total_bytes;
142 gint sum_total_bytes;
146 typedef struct _RefreshAsyncHelper {
147 ModestMailOperation *mail_op;
148 RefreshAsyncUserCallback user_callback;
150 } RefreshAsyncHelper;
152 typedef struct _XFerMsgsAsyncHelper
154 ModestMailOperation *mail_op;
156 TnyFolder *dest_folder;
157 XferMsgsAsyncUserCallback user_callback;
160 gint last_total_bytes;
161 gint sum_total_bytes;
163 } XFerMsgsAsyncHelper;
165 typedef struct _XFerFolderAsyncHelper
167 ModestMailOperation *mail_op;
168 XferFolderAsyncUserCallback user_callback;
170 } XFerFolderAsyncHelper;
172 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
176 static void modest_mail_operation_create_msg (ModestMailOperation *self,
177 const gchar *from, const gchar *to,
178 const gchar *cc, const gchar *bcc,
179 const gchar *subject, const gchar *plain_body,
180 const gchar *html_body, const GList *attachments_list,
181 const GList *images_list,
182 TnyHeaderFlags priority_flags,
183 ModestMailOperationCreateMsgCallback callback,
186 static gboolean idle_notify_queue (gpointer data);
189 ModestMailOperation *mail_op;
197 GList *attachments_list;
199 TnyHeaderFlags priority_flags;
200 ModestMailOperationCreateMsgCallback callback;
206 ModestMailOperation *mail_op;
208 ModestMailOperationCreateMsgCallback callback;
213 static GObjectClass *parent_class = NULL;
215 static guint signals[NUM_SIGNALS] = {0};
218 modest_mail_operation_get_type (void)
220 static GType my_type = 0;
222 static const GTypeInfo my_info = {
223 sizeof(ModestMailOperationClass),
224 NULL, /* base init */
225 NULL, /* base finalize */
226 (GClassInitFunc) modest_mail_operation_class_init,
227 NULL, /* class finalize */
228 NULL, /* class data */
229 sizeof(ModestMailOperation),
231 (GInstanceInitFunc) modest_mail_operation_init,
234 my_type = g_type_register_static (G_TYPE_OBJECT,
235 "ModestMailOperation",
242 modest_mail_operation_class_init (ModestMailOperationClass *klass)
244 GObjectClass *gobject_class;
245 gobject_class = (GObjectClass*) klass;
247 parent_class = g_type_class_peek_parent (klass);
248 gobject_class->finalize = modest_mail_operation_finalize;
250 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
253 * ModestMailOperation::progress-changed
254 * @self: the #MailOperation that emits the signal
255 * @user_data: user data set when the signal handler was connected
257 * Emitted when the progress of a mail operation changes
259 signals[PROGRESS_CHANGED_SIGNAL] =
260 g_signal_new ("progress-changed",
261 G_TYPE_FROM_CLASS (gobject_class),
263 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
265 g_cclosure_marshal_VOID__POINTER,
266 G_TYPE_NONE, 1, G_TYPE_POINTER);
270 * This signal is issued whenever a mail operation starts, and
271 * starts mean when the tinymail operation is issued. This
272 * means that it could happen that something wrong happens and
273 * the tinymail function is never called. In this situation a
274 * operation-finished will be issued without any
277 signals[OPERATION_STARTED_SIGNAL] =
278 g_signal_new ("operation-started",
279 G_TYPE_FROM_CLASS (gobject_class),
281 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
283 g_cclosure_marshal_VOID__VOID,
288 * This signal is issued whenever a mail operation
289 * finishes. Note that this signal could be issued without any
290 * previous "operation-started" signal, because this last one
291 * is only issued when the tinymail operation is successfully
294 signals[OPERATION_FINISHED_SIGNAL] =
295 g_signal_new ("operation-finished",
296 G_TYPE_FROM_CLASS (gobject_class),
298 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
300 g_cclosure_marshal_VOID__VOID,
305 modest_mail_operation_init (ModestMailOperation *obj)
307 ModestMailOperationPrivate *priv;
309 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
311 priv->account = NULL;
312 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
313 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
318 priv->error_checking = NULL;
319 priv->error_checking_user_data = NULL;
323 modest_mail_operation_finalize (GObject *obj)
325 ModestMailOperationPrivate *priv;
327 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
332 g_error_free (priv->error);
336 g_object_unref (priv->source);
340 g_object_unref (priv->account);
341 priv->account = NULL;
345 G_OBJECT_CLASS(parent_class)->finalize (obj);
349 modest_mail_operation_new (GObject *source)
351 ModestMailOperation *obj;
352 ModestMailOperationPrivate *priv;
354 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
355 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
358 priv->source = g_object_ref(source);
364 modest_mail_operation_new_with_error_handling (GObject *source,
365 ErrorCheckingUserCallback error_handler,
367 ErrorCheckingUserDataDestroyer error_handler_destroyer)
369 ModestMailOperation *obj;
370 ModestMailOperationPrivate *priv;
372 obj = modest_mail_operation_new (source);
373 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
375 g_return_val_if_fail (error_handler != NULL, obj);
376 priv->error_checking = error_handler;
377 priv->error_checking_user_data = user_data;
378 priv->error_checking_user_data_destroyer = error_handler_destroyer;
384 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
386 ModestMailOperationPrivate *priv;
388 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
390 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
391 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
393 /* Call the user callback */
394 if (priv->error_checking != NULL)
395 priv->error_checking (self, priv->error_checking_user_data);
399 ModestMailOperationTypeOperation
400 modest_mail_operation_get_type_operation (ModestMailOperation *self)
402 ModestMailOperationPrivate *priv;
404 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
405 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
407 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
409 return priv->op_type;
413 modest_mail_operation_is_mine (ModestMailOperation *self,
416 ModestMailOperationPrivate *priv;
418 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
421 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
422 if (priv->source == NULL) return FALSE;
424 return priv->source == me;
428 modest_mail_operation_get_source (ModestMailOperation *self)
430 ModestMailOperationPrivate *priv;
432 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
435 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
437 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
441 return (priv->source) ? g_object_ref (priv->source) : NULL;
444 ModestMailOperationStatus
445 modest_mail_operation_get_status (ModestMailOperation *self)
447 ModestMailOperationPrivate *priv;
449 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
450 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
451 MODEST_MAIL_OPERATION_STATUS_INVALID);
453 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
455 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
456 return MODEST_MAIL_OPERATION_STATUS_INVALID;
463 modest_mail_operation_get_error (ModestMailOperation *self)
465 ModestMailOperationPrivate *priv;
467 g_return_val_if_fail (self, NULL);
468 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
470 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
473 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
481 modest_mail_operation_cancel (ModestMailOperation *self)
483 ModestMailOperationPrivate *priv;
484 gboolean canceled = FALSE;
486 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
488 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
490 /* Note that if we call cancel with an already canceled mail
491 operation the progress changed signal won't be emitted */
492 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
496 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
498 /* Cancel the mail operation */
499 g_return_val_if_fail (priv->account, FALSE);
500 tny_account_cancel (priv->account);
502 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
503 ModestTnySendQueue *queue;
504 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
506 /* Cancel the sending of the following next messages */
507 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, NULL);
514 modest_mail_operation_get_task_done (ModestMailOperation *self)
516 ModestMailOperationPrivate *priv;
518 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
521 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
526 modest_mail_operation_get_task_total (ModestMailOperation *self)
528 ModestMailOperationPrivate *priv;
530 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
533 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
538 modest_mail_operation_is_finished (ModestMailOperation *self)
540 ModestMailOperationPrivate *priv;
541 gboolean retval = FALSE;
543 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
546 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
548 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
549 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
550 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
551 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
561 * Creates an image of the current state of a mail operation, the
562 * caller must free it
564 static ModestMailOperationState *
565 modest_mail_operation_clone_state (ModestMailOperation *self)
567 ModestMailOperationState *state;
568 ModestMailOperationPrivate *priv;
570 /* FIXME: this should be fixed properly
572 * in some cases, priv was NULL, so checking here to
575 g_return_val_if_fail (self, NULL);
576 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
577 g_return_val_if_fail (priv, NULL);
582 state = g_slice_new (ModestMailOperationState);
584 state->status = priv->status;
585 state->op_type = priv->op_type;
586 state->done = priv->done;
587 state->total = priv->total;
588 state->finished = modest_mail_operation_is_finished (self);
589 state->bytes_done = 0;
590 state->bytes_total = 0;
595 /* ******************************************************************* */
596 /* ************************** SEND ACTIONS ************************* */
597 /* ******************************************************************* */
600 modest_mail_operation_send_mail (ModestMailOperation *self,
601 TnyTransportAccount *transport_account,
604 TnySendQueue *send_queue = NULL;
605 ModestMailOperationPrivate *priv;
607 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
608 g_return_if_fail (transport_account && TNY_IS_TRANSPORT_ACCOUNT (transport_account));
609 g_return_if_fail (msg && TNY_IS_MSG (msg));
611 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
613 /* Get account and set it into mail_operation */
614 priv->account = g_object_ref (transport_account);
615 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
619 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
620 if (!TNY_IS_SEND_QUEUE(send_queue)) {
621 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
622 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
623 "modest: could not find send queue for account\n");
624 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
625 modest_mail_operation_notify_end (self);
628 /* Add the msg to the queue */
629 modest_mail_operation_notify_start (self);
631 tny_send_queue_add_async (send_queue, msg, NULL, NULL, NULL);
633 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
634 modest_mail_operation_notify_end (self);
641 idle_create_msg_cb (gpointer idle_data)
643 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
645 /* This is a GDK lock because we are an idle callback and
646 * info->callback can contain Gtk+ code */
648 gdk_threads_enter (); /* CHECKED */
649 info->callback (info->mail_op, info->msg, info->userdata);
651 g_object_unref (info->mail_op);
653 g_object_unref (info->msg);
654 g_slice_free (CreateMsgIdleInfo, info);
655 gdk_threads_leave (); /* CHECKED */
661 create_msg_thread (gpointer thread_data)
663 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
664 TnyMsg *new_msg = NULL;
665 ModestMailOperationPrivate *priv;
667 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
668 if (info->html_body == NULL) {
669 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
670 info->bcc, info->subject, info->plain_body,
671 info->attachments_list);
673 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
674 info->bcc, info->subject, info->html_body,
675 info->plain_body, info->attachments_list,
682 /* Set priority flags in message */
683 header = tny_msg_get_header (new_msg);
684 tny_header_set_flag (header, info->priority_flags);
686 /* Set attachment flags in message */
687 if (info->attachments_list != NULL)
688 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
690 g_object_unref (G_OBJECT(header));
692 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
693 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
694 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
695 "modest: failed to create a new msg\n");
703 g_free (info->plain_body);
704 g_free (info->html_body);
705 g_free (info->subject);
706 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
707 g_list_free (info->attachments_list);
708 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
709 g_list_free (info->images_list);
711 if (info->callback) {
712 CreateMsgIdleInfo *idle_info;
713 idle_info = g_slice_new0 (CreateMsgIdleInfo);
714 idle_info->mail_op = g_object_ref (info->mail_op);
715 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
716 idle_info->callback = info->callback;
717 idle_info->userdata = info->userdata;
718 g_idle_add (idle_create_msg_cb, idle_info);
720 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
723 g_object_unref (info->mail_op);
724 g_slice_free (CreateMsgInfo, info);
725 if (new_msg) g_object_unref(new_msg);
731 modest_mail_operation_create_msg (ModestMailOperation *self,
732 const gchar *from, const gchar *to,
733 const gchar *cc, const gchar *bcc,
734 const gchar *subject, const gchar *plain_body,
735 const gchar *html_body,
736 const GList *attachments_list,
737 const GList *images_list,
738 TnyHeaderFlags priority_flags,
739 ModestMailOperationCreateMsgCallback callback,
742 ModestMailOperationPrivate *priv;
743 CreateMsgInfo *info = NULL;
745 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
747 info = g_slice_new0 (CreateMsgInfo);
748 info->mail_op = g_object_ref (self);
750 info->from = g_strdup (from);
751 info->to = g_strdup (to);
752 info->cc = g_strdup (cc);
753 info->bcc = g_strdup (bcc);
754 info->subject = g_strdup (subject);
755 info->plain_body = g_strdup (plain_body);
756 info->html_body = g_strdup (html_body);
757 info->attachments_list = g_list_copy ((GList *) attachments_list);
758 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
759 info->images_list = g_list_copy ((GList *) images_list);
760 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
761 info->priority_flags = priority_flags;
763 info->callback = callback;
764 info->userdata = userdata;
766 g_thread_create (create_msg_thread, info, FALSE, NULL);
771 TnyTransportAccount *transport_account;
776 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
780 ModestMailOperationPrivate *priv = NULL;
781 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
782 TnyFolder *draft_folder = NULL;
783 TnyFolder *outbox_folder = NULL;
784 TnyHeader *header = NULL;
791 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
794 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
795 modest_mail_operation_notify_end (self);
799 /* Call mail operation */
800 modest_mail_operation_send_mail (self, info->transport_account, msg);
802 if (info->draft_msg != NULL) {
803 TnyFolder *folder = NULL;
804 TnyFolder *src_folder = NULL;
805 TnyFolderType folder_type;
806 TnyTransportAccount *transport_account = NULL;
808 /* To remove the old mail from its source folder, we need to get the
809 * transport account of the original draft message (the transport account
810 * might have been changed by the user) */
811 header = tny_msg_get_header (info->draft_msg);
812 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
813 modest_runtime_get_account_store(), header);
814 if (transport_account == NULL)
815 transport_account = g_object_ref(info->transport_account);
816 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
817 TNY_FOLDER_TYPE_DRAFTS);
818 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
819 TNY_FOLDER_TYPE_OUTBOX);
820 g_object_unref(transport_account);
823 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
827 if (!outbox_folder) {
828 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
833 folder = tny_msg_get_folder (info->draft_msg);
834 if (folder == NULL) goto end;
835 folder_type = modest_tny_folder_guess_folder_type (folder);
837 if (folder_type == TNY_FOLDER_TYPE_INVALID)
838 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
840 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
841 src_folder = outbox_folder;
843 src_folder = draft_folder;
845 /* Note: This can fail (with a warning) if the message is not really already in a folder,
846 * because this function requires it to have a UID. */
847 tny_folder_remove_msg (src_folder, header, NULL);
849 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
850 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
852 g_object_unref (folder);
857 g_object_unref (header);
861 g_object_unref (info->draft_msg);
863 g_object_unref (draft_folder);
865 g_object_unref (outbox_folder);
866 if (info->transport_account)
867 g_object_unref (info->transport_account);
868 g_slice_free (SendNewMailInfo, info);
872 modest_mail_operation_send_new_mail (ModestMailOperation *self,
873 TnyTransportAccount *transport_account,
875 const gchar *from, const gchar *to,
876 const gchar *cc, const gchar *bcc,
877 const gchar *subject, const gchar *plain_body,
878 const gchar *html_body,
879 const GList *attachments_list,
880 const GList *images_list,
881 TnyHeaderFlags priority_flags)
883 ModestMailOperationPrivate *priv = NULL;
884 SendNewMailInfo *info;
886 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
887 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
889 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
890 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
891 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
892 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
894 /* Check parametters */
896 /* Set status failed and set an error */
897 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
898 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
899 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
900 _("Error trying to send a mail. You need to set at least one recipient"));
903 info = g_slice_new0 (SendNewMailInfo);
904 info->transport_account = transport_account;
905 if (transport_account)
906 g_object_ref (transport_account);
907 info->draft_msg = draft_msg;
909 g_object_ref (draft_msg);
912 modest_mail_operation_notify_start (self);
913 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
914 attachments_list, images_list, priority_flags,
915 modest_mail_operation_send_new_mail_cb, info);
921 TnyTransportAccount *transport_account;
923 SaveToDraftstCallback callback;
927 ModestMailOperation *mailop;
928 } SaveToDraftsAddMsgInfo;
931 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
936 ModestMailOperationPrivate *priv = NULL;
937 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
939 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
942 g_warning ("%s: priv->error != NULL", __FUNCTION__);
943 g_error_free(priv->error);
946 priv->error = (err == NULL) ? NULL : g_error_copy(err);
948 if ((!priv->error) && (info->draft_msg != NULL)) {
949 TnyHeader *header = tny_msg_get_header (info->draft_msg);
950 TnyFolder *src_folder = tny_header_get_folder (header);
952 /* Remove the old draft */
953 tny_folder_remove_msg (src_folder, header, NULL);
955 /* Synchronize to expunge and to update the msg counts */
956 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
957 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
959 g_object_unref (G_OBJECT(header));
960 g_object_unref (G_OBJECT(src_folder));
964 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
966 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
968 /* Call the user callback */
970 info->callback (info->mailop, info->msg, info->user_data);
972 if (info->transport_account)
973 g_object_unref (G_OBJECT(info->transport_account));
975 g_object_unref (G_OBJECT (info->draft_msg));
977 g_object_unref (G_OBJECT(info->drafts));
979 g_object_unref (G_OBJECT (info->msg));
981 modest_mail_operation_notify_end (info->mailop);
982 g_object_unref(info->mailop);
983 g_slice_free (SaveToDraftsAddMsgInfo, info);
988 TnyTransportAccount *transport_account;
990 SaveToDraftstCallback callback;
995 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
999 TnyFolder *drafts = NULL;
1000 ModestMailOperationPrivate *priv = NULL;
1001 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1003 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1006 if (!(priv->error)) {
1007 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1008 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1009 "modest: failed to create a new msg\n");
1012 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1013 TNY_FOLDER_TYPE_DRAFTS);
1014 if (!drafts && !(priv->error)) {
1015 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1016 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1017 "modest: failed to create a new msg\n");
1022 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1023 cb_info->transport_account = g_object_ref(info->transport_account);
1024 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1025 cb_info->callback = info->callback;
1026 cb_info->user_data = info->user_data;
1027 cb_info->drafts = g_object_ref(drafts);
1028 cb_info->msg = g_object_ref(msg);
1029 cb_info->mailop = g_object_ref(self);
1030 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1033 /* Call the user callback */
1034 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1036 info->callback (self, msg, info->user_data);
1037 modest_mail_operation_notify_end (self);
1041 g_object_unref (G_OBJECT(drafts));
1042 if (info->draft_msg)
1043 g_object_unref (G_OBJECT (info->draft_msg));
1044 if (info->transport_account)
1045 g_object_unref (G_OBJECT(info->transport_account));
1046 g_slice_free (SaveToDraftsInfo, info);
1050 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1051 TnyTransportAccount *transport_account,
1053 const gchar *from, const gchar *to,
1054 const gchar *cc, const gchar *bcc,
1055 const gchar *subject, const gchar *plain_body,
1056 const gchar *html_body,
1057 const GList *attachments_list,
1058 const GList *images_list,
1059 TnyHeaderFlags priority_flags,
1060 SaveToDraftstCallback callback,
1063 ModestMailOperationPrivate *priv = NULL;
1064 SaveToDraftsInfo *info = NULL;
1066 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1067 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1069 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1071 /* Get account and set it into mail_operation */
1072 priv->account = g_object_ref (transport_account);
1073 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1075 info = g_slice_new0 (SaveToDraftsInfo);
1076 info->transport_account = g_object_ref (transport_account);
1077 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1078 info->callback = callback;
1079 info->user_data = user_data;
1081 modest_mail_operation_notify_start (self);
1082 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1083 attachments_list, images_list, priority_flags,
1084 modest_mail_operation_save_to_drafts_cb, info);
1089 ModestMailOperation *mail_op;
1090 TnyMimePart *mime_part;
1092 GetMimePartSizeCallback callback;
1094 } GetMimePartSizeInfo;
1096 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1097 /* We use this folder observer to track the headers that have been
1098 * added to a folder */
1101 TnyList *new_headers;
1102 } InternalFolderObserver;
1105 GObjectClass parent;
1106 } InternalFolderObserverClass;
1108 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1110 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1111 internal_folder_observer,
1113 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1117 foreach_add_item (gpointer header, gpointer user_data)
1119 tny_list_prepend (TNY_LIST (user_data),
1120 g_object_ref (G_OBJECT (header)));
1123 /* This is the method that looks for new messages in a folder */
1125 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1127 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1129 TnyFolderChangeChanged changed;
1131 changed = tny_folder_change_get_changed (change);
1133 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1136 /* Get added headers */
1137 list = tny_simple_list_new ();
1138 tny_folder_change_get_added_headers (change, list);
1140 /* Add them to the folder observer */
1141 tny_list_foreach (list, foreach_add_item,
1142 derived->new_headers);
1144 g_object_unref (G_OBJECT (list));
1149 internal_folder_observer_init (InternalFolderObserver *self)
1151 self->new_headers = tny_simple_list_new ();
1154 internal_folder_observer_finalize (GObject *object)
1156 InternalFolderObserver *self;
1158 self = (InternalFolderObserver *) object;
1159 g_object_unref (self->new_headers);
1161 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1164 tny_folder_observer_init (TnyFolderObserverIface *iface)
1166 iface->update = internal_folder_observer_update;
1169 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1171 GObjectClass *object_class;
1173 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1174 object_class = (GObjectClass*) klass;
1175 object_class->finalize = internal_folder_observer_finalize;
1180 ModestMailOperation *mail_op;
1181 gchar *account_name;
1182 UpdateAccountCallback callback;
1187 TnyFolderObserver *inbox_observer;
1188 RetrieveAllCallback retrieve_all_cb;
1189 } UpdateAccountInfo;
1193 destroy_update_account_info (UpdateAccountInfo *info)
1195 g_free (info->account_name);
1196 g_object_unref (info->folders);
1197 g_object_unref (info->mail_op);
1198 g_slice_free (UpdateAccountInfo, info);
1202 update_account_get_msg_async_cb (TnyFolder *folder,
1208 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1210 /* Just delete the helper. Don't do anything with the new
1211 msg. There is also no need to check for errors */
1212 g_object_unref (msg_info->mail_op);
1213 g_object_unref (msg_info->header);
1214 g_slice_free (GetMsgInfo, msg_info);
1218 inbox_refreshed_cb (TnyFolder *inbox,
1223 UpdateAccountInfo *info;
1224 ModestMailOperationPrivate *priv;
1225 TnyIterator *new_headers_iter;
1226 GPtrArray *new_headers_array = NULL;
1227 gint max_size, retrieve_limit, i;
1228 ModestAccountMgr *mgr;
1229 ModestAccountRetrieveType retrieve_type;
1230 TnyList *new_headers = NULL;
1231 gboolean headers_only, ignore_limit;
1232 TnyTransportAccount *transport_account;
1234 info = (UpdateAccountInfo *) user_data;
1235 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1236 mgr = modest_runtime_get_account_mgr ();
1238 if (canceled || err || !inbox) {
1239 /* Try to send anyway */
1243 /* Get the message max size */
1244 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1245 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1247 max_size = G_MAXINT;
1249 max_size = max_size * KB;
1251 /* Create the new headers array. We need it to sort the
1252 new headers by date */
1253 new_headers_array = g_ptr_array_new ();
1254 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1255 while (!tny_iterator_is_done (new_headers_iter)) {
1256 TnyHeader *header = NULL;
1258 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1259 /* Apply per-message size limits */
1260 if (tny_header_get_message_size (header) < max_size)
1261 g_ptr_array_add (new_headers_array, g_object_ref (header));
1263 g_object_unref (header);
1264 tny_iterator_next (new_headers_iter);
1266 g_object_unref (new_headers_iter);
1267 tny_folder_remove_observer (inbox, info->inbox_observer);
1268 g_object_unref (info->inbox_observer);
1269 info->inbox_observer = NULL;
1271 /* Update the last updated key, even if we don't have to get new headers */
1272 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1274 if (new_headers_array->len == 0)
1277 /* Get per-account message amount retrieval limit */
1278 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1279 if (retrieve_limit == 0)
1280 retrieve_limit = G_MAXINT;
1282 /* Get per-account retrieval type */
1283 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1284 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1287 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1289 /* Ask the users if they want to retrieve all the messages
1290 even though the limit was exceeded */
1291 ignore_limit = FALSE;
1292 if (new_headers_array->len > retrieve_limit) {
1293 /* Ask the user if a callback has been specified and
1294 if the mail operation has a source (this means that
1295 was invoked by the user and not automatically by a
1297 if (info->retrieve_all_cb && priv->source)
1298 ignore_limit = info->retrieve_all_cb (priv->source,
1299 new_headers_array->len,
1303 if (!headers_only) {
1305 const gint msg_list_size = compute_message_array_size (new_headers_array);
1309 priv->total = new_headers_array->len;
1311 priv->total = MIN (new_headers_array->len, retrieve_limit);
1312 while (msg_num < priv->total) {
1313 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1314 TnyFolder *folder = tny_header_get_folder (header);
1315 GetMsgInfo *msg_info;
1317 /* Create the message info */
1318 msg_info = g_slice_new0 (GetMsgInfo);
1319 msg_info->mail_op = g_object_ref (info->mail_op);
1320 msg_info->header = g_object_ref (header);
1321 msg_info->total_bytes = msg_list_size;
1323 /* Get message in an async way */
1324 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1325 get_msg_status_cb, msg_info);
1327 g_object_unref (folder);
1333 /* Copy the headers to a list and free the array */
1334 new_headers = tny_simple_list_new ();
1335 for (i=0; i < new_headers_array->len; i++) {
1336 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1337 tny_list_append (new_headers, G_OBJECT (header));
1339 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1340 g_ptr_array_free (new_headers_array, FALSE);
1343 /* Get the transport account */
1344 transport_account = (TnyTransportAccount *)
1345 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1346 info->account_name);
1348 if (transport_account) {
1349 ModestTnySendQueue *send_queue;
1353 send_queue = modest_runtime_get_send_queue (transport_account);
1355 /* Get outbox folder */
1356 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1357 num_messages = tny_folder_get_all_count (outbox);
1358 g_object_unref (outbox);
1360 if (num_messages != 0) {
1362 g_object_unref (priv->account);
1364 /* Reenable suspended items */
1365 modest_tny_send_queue_wakeup (MODEST_TNY_SEND_QUEUE (send_queue));
1368 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (send_queue));
1372 /* Check if the operation was a success */
1374 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1376 /* Set the account back to not busy */
1377 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1379 /* Call the user callback */
1381 info->callback (info->mail_op, new_headers, info->user_data);
1383 /* Notify about operation end */
1384 modest_mail_operation_notify_end (info->mail_op);
1388 g_object_unref (new_headers);
1389 destroy_update_account_info (info);
1393 recurse_folders_async_cb (TnyFolderStore *folder_store,
1399 UpdateAccountInfo *info;
1400 ModestMailOperationPrivate *priv;
1402 info = (UpdateAccountInfo *) user_data;
1403 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1405 if (err || canceled) {
1406 /* Try to continue anyway */
1408 TnyIterator *iter = tny_list_create_iterator (list);
1409 while (!tny_iterator_is_done (iter)) {
1410 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1411 TnyList *folders = tny_simple_list_new ();
1413 /* Add to the list of all folders */
1414 tny_list_append (info->folders, (GObject *) folder);
1416 /* Add pending call */
1417 info->pending_calls++;
1419 tny_folder_store_get_folders_async (folder, folders, NULL,
1420 recurse_folders_async_cb,
1423 g_object_unref (G_OBJECT (folder));
1425 tny_iterator_next (iter);
1427 g_object_unref (G_OBJECT (iter));
1428 g_object_unref (G_OBJECT (list));
1431 /* Remove my own pending call */
1432 info->pending_calls--;
1434 /* This means that we have all the folders */
1435 if (info->pending_calls == 0) {
1436 TnyIterator *iter_all_folders;
1437 TnyFolder *inbox = NULL;
1439 iter_all_folders = tny_list_create_iterator (info->folders);
1441 /* Do a poke status over all folders */
1442 while (!tny_iterator_is_done (iter_all_folders) &&
1443 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1444 TnyFolder *folder = NULL;
1446 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1448 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1449 /* Get a reference to the INBOX */
1450 inbox = g_object_ref (folder);
1452 /* Issue a poke status over the folder */
1454 tny_folder_poke_status (folder);
1457 /* Free and go to next */
1458 g_object_unref (folder);
1459 tny_iterator_next (iter_all_folders);
1461 g_object_unref (iter_all_folders);
1463 /* Refresh the INBOX */
1465 /* Refresh the folder. Our observer receives
1466 * the new emails during folder refreshes, so
1467 * we can use observer->new_headers
1469 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1470 tny_folder_add_observer (inbox, info->inbox_observer);
1472 /* Refresh the INBOX */
1473 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1474 g_object_unref (inbox);
1476 /* We could not perform the inbox refresh but
1477 we'll try to send mails anyway */
1478 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1484 modest_mail_operation_update_account (ModestMailOperation *self,
1485 const gchar *account_name,
1487 RetrieveAllCallback retrieve_all_cb,
1488 UpdateAccountCallback callback,
1491 UpdateAccountInfo *info = NULL;
1492 ModestMailOperationPrivate *priv = NULL;
1493 ModestTnyAccountStore *account_store = NULL;
1494 TnyStoreAccount *store_account = NULL;
1496 ModestMailOperationState *state;
1498 /* Init mail operation */
1499 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1502 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1503 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1505 /* Get the store account */
1506 account_store = modest_runtime_get_account_store ();
1507 store_account = (TnyStoreAccount *)
1508 modest_tny_account_store_get_server_account (account_store,
1510 TNY_ACCOUNT_TYPE_STORE);
1511 priv->account = g_object_ref (store_account);
1513 /* Create the helper object */
1514 info = g_slice_new0 (UpdateAccountInfo);
1515 info->pending_calls = 1;
1516 info->folders = tny_simple_list_new ();
1517 info->mail_op = g_object_ref (self);
1518 info->poke_all = poke_all;
1519 info->account_name = g_strdup (account_name);
1520 info->callback = callback;
1521 info->user_data = user_data;
1522 info->retrieve_all_cb = retrieve_all_cb;
1524 /* Set account busy */
1525 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1526 modest_mail_operation_notify_start (self);
1528 /* notify about the start of the operation */
1529 state = modest_mail_operation_clone_state (self);
1533 /* Start notifying progress */
1534 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1535 g_slice_free (ModestMailOperationState, state);
1537 /* Get all folders and continue in the callback */
1538 folders = tny_simple_list_new ();
1539 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
1541 recurse_folders_async_cb,
1546 * Used to notify the queue from the main
1547 * loop. We call it inside an idle call to achieve that
1550 idle_notify_queue (gpointer data)
1552 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1554 gdk_threads_enter ();
1555 modest_mail_operation_notify_end (mail_op);
1556 gdk_threads_leave ();
1557 g_object_unref (mail_op);
1563 compare_headers_by_date (gconstpointer a,
1566 TnyHeader **header1, **header2;
1567 time_t sent1, sent2;
1569 header1 = (TnyHeader **) a;
1570 header2 = (TnyHeader **) b;
1572 sent1 = tny_header_get_date_sent (*header1);
1573 sent2 = tny_header_get_date_sent (*header2);
1575 /* We want the most recent ones (greater time_t) at the
1584 /* ******************************************************************* */
1585 /* ************************** STORE ACTIONS ************************* */
1586 /* ******************************************************************* */
1589 ModestMailOperation *mail_op;
1590 CreateFolderUserCallback callback;
1596 create_folder_cb (TnyFolderStore *parent_folder,
1598 TnyFolder *new_folder,
1602 ModestMailOperationPrivate *priv;
1603 CreateFolderInfo *info;
1605 info = (CreateFolderInfo *) user_data;
1606 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1608 if (canceled || err) {
1609 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1611 priv->error = g_error_copy (err);
1613 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1614 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1617 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1620 /* The user will unref the new_folder */
1622 info->callback (info->mail_op, parent_folder,
1623 new_folder, info->user_data);
1625 /* Notify about operation end */
1626 modest_mail_operation_notify_end (info->mail_op);
1629 g_object_unref (info->mail_op);
1630 g_slice_free (CreateFolderInfo, info);
1634 modest_mail_operation_create_folder (ModestMailOperation *self,
1635 TnyFolderStore *parent,
1637 CreateFolderUserCallback callback,
1640 ModestMailOperationPrivate *priv;
1642 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1643 g_return_if_fail (name);
1645 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1646 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1647 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1648 g_object_ref (parent) :
1649 modest_tny_folder_get_account (TNY_FOLDER (parent));
1651 /* Check for already existing folder */
1652 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1653 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1654 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1655 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1656 _CS("ckdg_ib_folder_already_exists"));
1660 if (TNY_IS_FOLDER (parent)) {
1661 /* Check folder rules */
1662 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1663 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1664 /* Set status failed and set an error */
1665 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1666 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1667 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1668 _("mail_in_ui_folder_create_error"));
1672 if (!strcmp (name, " ") || strchr (name, '/')) {
1673 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1674 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1675 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1676 _("mail_in_ui_folder_create_error"));
1680 CreateFolderInfo *info;
1682 info = g_slice_new0 (CreateFolderInfo);
1683 info->mail_op = g_object_ref (self);
1684 info->callback = callback;
1685 info->user_data = user_data;
1687 modest_mail_operation_notify_start (self);
1689 /* Create the folder */
1690 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1693 /* Call the user callback anyway */
1695 callback (self, parent, NULL, user_data);
1696 /* Notify about operation end */
1697 modest_mail_operation_notify_end (self);
1702 modest_mail_operation_remove_folder (ModestMailOperation *self,
1704 gboolean remove_to_trash)
1706 TnyAccount *account;
1707 ModestMailOperationPrivate *priv;
1708 ModestTnyFolderRules rules;
1710 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1711 g_return_if_fail (TNY_IS_FOLDER (folder));
1713 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1715 /* Check folder rules */
1716 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1717 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1718 /* Set status failed and set an error */
1719 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1720 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1721 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1722 _("mail_in_ui_folder_delete_error"));
1726 /* Get the account */
1727 account = modest_tny_folder_get_account (folder);
1728 priv->account = g_object_ref(account);
1729 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1731 /* Delete folder or move to trash */
1732 if (remove_to_trash) {
1733 TnyFolder *trash_folder = NULL;
1734 trash_folder = modest_tny_account_get_special_folder (account,
1735 TNY_FOLDER_TYPE_TRASH);
1736 /* TODO: error_handling */
1738 modest_mail_operation_notify_start (self);
1739 modest_mail_operation_xfer_folder (self, folder,
1740 TNY_FOLDER_STORE (trash_folder),
1742 g_object_unref (trash_folder);
1744 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1747 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1749 modest_mail_operation_notify_start (self);
1750 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1751 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1754 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1756 g_object_unref (parent);
1758 g_warning ("%s: could not get parent folder", __FUNCTION__);
1760 g_object_unref (G_OBJECT (account));
1763 /* Notify about operation end */
1764 modest_mail_operation_notify_end (self);
1768 transfer_folder_status_cb (GObject *obj,
1772 ModestMailOperation *self;
1773 ModestMailOperationPrivate *priv;
1774 ModestMailOperationState *state;
1775 XFerFolderAsyncHelper *helper;
1777 g_return_if_fail (status != NULL);
1778 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1780 helper = (XFerFolderAsyncHelper *) user_data;
1781 g_return_if_fail (helper != NULL);
1783 self = helper->mail_op;
1784 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1786 priv->done = status->position;
1787 priv->total = status->of_total;
1789 state = modest_mail_operation_clone_state (self);
1791 /* This is not a GDK lock because we are a Tinymail callback
1792 * which is already GDK locked by Tinymail */
1794 /* no gdk_threads_enter (), CHECKED */
1796 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1798 /* no gdk_threads_leave (), CHECKED */
1800 g_slice_free (ModestMailOperationState, state);
1805 transfer_folder_cb (TnyFolder *folder,
1807 TnyFolderStore *into,
1808 TnyFolder *new_folder,
1812 XFerFolderAsyncHelper *helper;
1813 ModestMailOperation *self = NULL;
1814 ModestMailOperationPrivate *priv = NULL;
1816 helper = (XFerFolderAsyncHelper *) user_data;
1817 g_return_if_fail (helper != NULL);
1819 self = helper->mail_op;
1820 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1823 priv->error = g_error_copy (err);
1825 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1826 } else if (cancelled) {
1827 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1828 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1829 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1830 _("Transference of %s was cancelled."),
1831 tny_folder_get_name (folder));
1834 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1837 /* Notify about operation end */
1838 modest_mail_operation_notify_end (self);
1840 /* If user defined callback function was defined, call it */
1841 if (helper->user_callback) {
1843 /* This is not a GDK lock because we are a Tinymail callback
1844 * which is already GDK locked by Tinymail */
1846 /* no gdk_threads_enter (), CHECKED */
1847 helper->user_callback (self, new_folder, helper->user_data);
1848 /* no gdk_threads_leave () , CHECKED */
1852 g_object_unref (helper->mail_op);
1853 g_slice_free (XFerFolderAsyncHelper, helper);
1858 * This function checks if the new name is a valid name for our local
1859 * folders account. The new name could not be the same than then name
1860 * of any of the mandatory local folders
1862 * We can not rely on tinymail because tinymail does not check the
1863 * name of the virtual folders that the account could have in the case
1864 * that we're doing a rename (because it directly calls Camel which
1865 * knows nothing about our virtual folders).
1867 * In the case of an actual copy/move (i.e. move/copy a folder between
1868 * accounts) tinymail uses the tny_folder_store_create_account which
1869 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1870 * checks the new name of the folder, so this call in that case
1871 * wouldn't be needed. *But* NOTE that if tinymail changes its
1872 * implementation (if folder transfers within the same account is no
1873 * longer implemented as a rename) this call will allow Modest to work
1876 * If the new name is not valid, this function will set the status to
1877 * failed and will set also an error in the mail operation
1880 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1881 TnyFolderStore *into,
1882 const gchar *new_name)
1884 if (TNY_IS_ACCOUNT (into) &&
1885 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1886 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1888 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1889 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1890 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1891 _CS("ckdg_ib_folder_already_exists"));
1898 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1900 TnyFolderStore *parent,
1901 gboolean delete_original,
1902 XferFolderAsyncUserCallback user_callback,
1905 ModestMailOperationPrivate *priv = NULL;
1906 ModestTnyFolderRules parent_rules = 0, rules;
1907 XFerFolderAsyncHelper *helper = NULL;
1908 const gchar *folder_name = NULL;
1909 const gchar *error_msg;
1911 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1912 g_return_if_fail (TNY_IS_FOLDER (folder));
1913 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1915 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1916 folder_name = tny_folder_get_name (folder);
1918 /* Set the error msg */
1919 error_msg = _("mail_in_ui_folder_move_target_error");
1921 /* Get account and set it into mail_operation */
1922 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1923 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1924 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1926 /* Get folder rules */
1927 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1928 if (TNY_IS_FOLDER (parent))
1929 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1931 /* Apply operation constraints */
1932 if ((gpointer) parent == (gpointer) folder ||
1933 (!TNY_IS_FOLDER_STORE (parent)) ||
1934 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1937 } else if (TNY_IS_FOLDER (parent) &&
1938 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
1942 } else if (TNY_IS_FOLDER (parent) &&
1943 TNY_IS_FOLDER_STORE (folder) &&
1944 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
1945 TNY_FOLDER_STORE (folder))) {
1946 /* Do not move a parent into a child */
1948 } else if (TNY_IS_FOLDER_STORE (parent) &&
1949 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
1950 /* Check that the new folder name is not used by any
1953 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
1954 /* Check that the new folder name is not used by any
1955 special local folder */
1958 /* Create the helper */
1959 helper = g_slice_new0 (XFerFolderAsyncHelper);
1960 helper->mail_op = g_object_ref (self);
1961 helper->user_callback = user_callback;
1962 helper->user_data = user_data;
1964 /* Move/Copy folder */
1965 modest_mail_operation_notify_start (self);
1966 tny_folder_copy_async (folder,
1968 tny_folder_get_name (folder),
1971 transfer_folder_status_cb,
1977 /* Set status failed and set an error */
1978 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1979 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1980 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1983 /* Call the user callback if exists */
1985 user_callback (self, NULL, user_data);
1987 /* Notify the queue */
1988 modest_mail_operation_notify_end (self);
1992 modest_mail_operation_rename_folder (ModestMailOperation *self,
1995 XferFolderAsyncUserCallback user_callback,
1998 ModestMailOperationPrivate *priv;
1999 ModestTnyFolderRules rules;
2000 XFerFolderAsyncHelper *helper;
2002 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2003 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2004 g_return_if_fail (name);
2006 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2008 /* Get account and set it into mail_operation */
2009 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2010 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2012 /* Check folder rules */
2013 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2014 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2016 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2019 TnyFolderStore *into;
2021 into = tny_folder_get_folder_store (folder);
2023 /* Check that the new folder name is not used by any
2024 special local folder */
2025 if (new_name_valid_if_local_account (priv, into, name)) {
2026 /* Create the helper */
2027 helper = g_slice_new0 (XFerFolderAsyncHelper);
2028 helper->mail_op = g_object_ref(self);
2029 helper->user_callback = user_callback;
2030 helper->user_data = user_data;
2032 /* Rename. Camel handles folder subscription/unsubscription */
2033 modest_mail_operation_notify_start (self);
2034 tny_folder_copy_async (folder, into, name, TRUE,
2036 transfer_folder_status_cb,
2041 g_object_unref (into);
2046 /* Set status failed and set an error */
2047 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2048 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2049 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2050 _("FIXME: unable to rename"));
2053 user_callback (self, NULL, user_data);
2055 /* Notify about operation end */
2056 modest_mail_operation_notify_end (self);
2059 /* ******************************************************************* */
2060 /* ************************** MSG ACTIONS ************************* */
2061 /* ******************************************************************* */
2064 modest_mail_operation_get_msg (ModestMailOperation *self,
2066 GetMsgAsyncUserCallback user_callback,
2069 GetMsgInfo *helper = NULL;
2071 ModestMailOperationPrivate *priv;
2073 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2074 g_return_if_fail (TNY_IS_HEADER (header));
2076 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2077 folder = tny_header_get_folder (header);
2079 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2083 /* Get account and set it into mail_operation */
2084 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2086 /* Check for cached messages */
2087 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2088 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2090 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2092 /* Create the helper */
2093 helper = g_slice_new0 (GetMsgInfo);
2094 helper->header = g_object_ref (header);
2095 helper->mail_op = g_object_ref (self);
2096 helper->user_callback = user_callback;
2097 helper->user_data = user_data;
2098 helper->destroy_notify = NULL;
2099 helper->last_total_bytes = 0;
2100 helper->sum_total_bytes = 0;
2101 helper->total_bytes = tny_header_get_message_size (header);
2103 modest_mail_operation_notify_start (self);
2105 /* notify about the start of the operation */
2106 ModestMailOperationState *state;
2107 state = modest_mail_operation_clone_state (self);
2110 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2113 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2115 g_object_unref (G_OBJECT (folder));
2119 get_msg_status_cb (GObject *obj,
2123 GetMsgInfo *helper = NULL;
2125 g_return_if_fail (status != NULL);
2126 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2128 helper = (GetMsgInfo *) user_data;
2129 g_return_if_fail (helper != NULL);
2131 /* Notify progress */
2132 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2133 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2137 get_msg_async_cb (TnyFolder *folder,
2143 GetMsgInfo *info = NULL;
2144 ModestMailOperationPrivate *priv = NULL;
2147 info = (GetMsgInfo *) user_data;
2149 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2151 finished = (priv->done == priv->total) ? TRUE : FALSE;
2154 if (canceled || err) {
2155 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2157 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2158 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2161 /* Set the success status before calling the user callback */
2162 if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2163 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2167 /* Call the user callback */
2168 if (info->user_callback)
2169 info->user_callback (info->mail_op, info->header, canceled,
2170 msg, err, info->user_data);
2172 /* Notify about operation end if this is the last callback */
2174 /* Free user data */
2175 if (info->destroy_notify)
2176 info->destroy_notify (info->user_data);
2178 /* Notify about operation end */
2179 modest_mail_operation_notify_end (info->mail_op);
2183 g_object_unref (info->header);
2184 g_object_unref (info->mail_op);
2185 g_slice_free (GetMsgInfo, info);
2189 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2190 TnyList *header_list,
2191 GetMsgAsyncUserCallback user_callback,
2193 GDestroyNotify notify)
2195 ModestMailOperationPrivate *priv = NULL;
2197 TnyIterator *iter = NULL;
2199 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2201 /* Init mail operation */
2202 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2203 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2204 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2206 priv->total = tny_list_get_length(header_list);
2208 /* Get account and set it into mail_operation */
2209 if (tny_list_get_length (header_list) >= 1) {
2210 iter = tny_list_create_iterator (header_list);
2211 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2213 TnyFolder *folder = tny_header_get_folder (header);
2215 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2216 g_object_unref (folder);
2218 g_object_unref (header);
2221 if (tny_list_get_length (header_list) == 1) {
2222 g_object_unref (iter);
2227 msg_list_size = compute_message_list_size (header_list);
2229 modest_mail_operation_notify_start (self);
2230 iter = tny_list_create_iterator (header_list);
2231 while (!tny_iterator_is_done (iter)) {
2232 /* notify about the start of the operation */
2233 ModestMailOperationState *state;
2234 state = modest_mail_operation_clone_state (self);
2237 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2240 GetMsgInfo *msg_info = NULL;
2241 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2242 TnyFolder *folder = tny_header_get_folder (header);
2244 /* Create the message info */
2245 msg_info = g_slice_new0 (GetMsgInfo);
2246 msg_info->mail_op = g_object_ref (self);
2247 msg_info->header = g_object_ref (header);
2248 msg_info->user_callback = user_callback;
2249 msg_info->user_data = user_data;
2250 msg_info->destroy_notify = notify;
2251 msg_info->last_total_bytes = 0;
2252 msg_info->sum_total_bytes = 0;
2253 msg_info->total_bytes = msg_list_size;
2255 /* The callback will call it per each header */
2256 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2258 /* Free and go on */
2259 g_object_unref (header);
2260 g_object_unref (folder);
2261 tny_iterator_next (iter);
2263 g_object_unref (iter);
2268 modest_mail_operation_remove_msg (ModestMailOperation *self,
2270 gboolean remove_to_trash /*ignored*/)
2273 ModestMailOperationPrivate *priv;
2275 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2276 g_return_if_fail (TNY_IS_HEADER (header));
2278 if (remove_to_trash)
2279 g_warning ("remove to trash is not implemented");
2281 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2282 folder = tny_header_get_folder (header);
2284 /* Get account and set it into mail_operation */
2285 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2286 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2287 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2289 /* remove message from folder */
2290 tny_folder_remove_msg (folder, header, &(priv->error));
2292 gboolean expunge, leave_on_server;
2293 const gchar *account_name;
2294 TnyAccount *account;
2295 ModestTransportStoreProtocol account_proto;
2297 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2298 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2300 modest_mail_operation_notify_start (self);
2302 /* Get leave on server setting */
2303 account = tny_folder_get_account (folder);
2304 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2306 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2309 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2311 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2312 modest_tny_folder_is_remote_folder (folder) == FALSE)
2318 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2321 g_object_unref (account);
2327 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2329 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2332 g_object_unref (G_OBJECT (folder));
2334 /* Notify about operation end */
2335 modest_mail_operation_notify_end (self);
2339 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2341 gboolean remove_to_trash /*ignored*/)
2343 TnyFolder *folder = NULL;
2344 ModestMailOperationPrivate *priv;
2345 TnyIterator *iter = NULL;
2346 TnyHeader *header = NULL;
2347 TnyList *remove_headers = NULL;
2348 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2350 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2351 g_return_if_fail (TNY_IS_LIST (headers));
2353 if (remove_to_trash)
2354 g_warning ("remove to trash is not implemented");
2356 if (tny_list_get_length(headers) == 0) {
2357 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2358 goto cleanup; /* nothing to do */
2361 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2362 remove_headers = g_object_ref(headers);
2364 /* Get folder from first header and sync it */
2365 iter = tny_list_create_iterator (headers);
2366 header = TNY_HEADER (tny_iterator_get_current (iter));
2368 folder = tny_header_get_folder (header);
2369 if (!TNY_IS_FOLDER(folder)) {
2370 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2374 /* Don't remove messages that are being sent */
2375 if (modest_tny_folder_is_local_folder (folder)) {
2376 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2378 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2379 TnyTransportAccount *traccount = NULL;
2380 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2381 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2383 ModestTnySendQueueStatus status;
2384 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2385 TnyIterator *iter = tny_list_create_iterator(headers);
2386 g_object_unref(remove_headers);
2387 remove_headers = TNY_LIST(tny_simple_list_new());
2388 while (!tny_iterator_is_done(iter)) {
2390 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2391 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2392 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2393 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2394 tny_list_append(remove_headers, G_OBJECT(hdr));
2396 g_object_unref(hdr);
2398 tny_iterator_next(iter);
2400 g_object_unref(iter);
2401 g_object_unref(traccount);
2405 /* Get account and set it into mail_operation */
2406 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2407 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2408 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2410 /* remove message from folder */
2411 modest_mail_operation_notify_start (self);
2413 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2415 gboolean expunge, leave_on_server;
2416 const gchar *account_name;
2418 TnyAccount *account;
2419 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2421 account = tny_folder_get_account (folder);
2422 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2424 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2427 proto = tny_account_get_proto (account);
2429 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2432 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2433 modest_tny_folder_is_remote_folder (folder) == FALSE)
2439 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2441 g_object_unref (account);
2447 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2449 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2454 g_object_unref (remove_headers);
2456 g_object_unref (header);
2458 g_object_unref (iter);
2460 g_object_unref (folder);
2462 /* Notify about operation end */
2463 modest_mail_operation_notify_end (self);
2467 notify_progress_of_multiple_messages (ModestMailOperation *self,
2469 gint *last_total_bytes,
2470 gint *sum_total_bytes,
2472 gboolean increment_done)
2474 ModestMailOperationPrivate *priv;
2475 ModestMailOperationState *state;
2476 gboolean is_num_bytes = FALSE;
2478 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2480 /* We know that tinymail sends us information about
2481 * transferred bytes with this particular message
2483 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2484 * I just added the 'if' so we don't get runtime warning)
2486 if (status->message)
2487 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2489 state = modest_mail_operation_clone_state (self);
2490 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2491 /* We know that we're in a different message when the
2492 total number of bytes to transfer is different. Of
2493 course it could fail if we're transferring messages
2494 of the same size, but this is a workarround */
2495 if (status->of_total != *last_total_bytes) {
2496 /* We need to increment the done when there is
2497 no information about each individual
2498 message, we need to do this in message
2499 transfers, and we don't do it for getting
2503 *sum_total_bytes += *last_total_bytes;
2504 *last_total_bytes = status->of_total;
2506 state->bytes_done += status->position + *sum_total_bytes;
2507 state->bytes_total = total_bytes;
2509 /* Notify the status change. Only notify about changes
2510 referred to bytes */
2511 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2515 g_slice_free (ModestMailOperationState, state);
2519 transfer_msgs_status_cb (GObject *obj,
2523 XFerMsgsAsyncHelper *helper;
2525 g_return_if_fail (status != NULL);
2526 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2528 helper = (XFerMsgsAsyncHelper *) user_data;
2529 g_return_if_fail (helper != NULL);
2531 /* Notify progress */
2532 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2533 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2538 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2540 XFerMsgsAsyncHelper *helper;
2541 ModestMailOperation *self;
2542 ModestMailOperationPrivate *priv;
2543 TnyIterator *iter = NULL;
2544 TnyHeader *header = NULL;
2546 helper = (XFerMsgsAsyncHelper *) user_data;
2547 self = helper->mail_op;
2549 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2552 priv->error = g_error_copy (err);
2554 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2555 } else if (cancelled) {
2556 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2557 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2558 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2559 _("Error trying to refresh the contents of %s"),
2560 tny_folder_get_name (folder));
2563 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2565 /* Update folder counts */
2566 tny_folder_poke_status (folder);
2567 tny_folder_poke_status (helper->dest_folder);
2571 /* Mark headers as deleted and seen */
2572 if ((helper->delete) &&
2573 (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) {
2574 iter = tny_list_create_iterator (helper->headers);
2575 while (!tny_iterator_is_done (iter)) {
2576 header = TNY_HEADER (tny_iterator_get_current (iter));
2577 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2578 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2579 g_object_unref (header);
2581 tny_iterator_next (iter);
2586 /* Notify about operation end */
2587 modest_mail_operation_notify_end (self);
2589 /* If user defined callback function was defined, call it */
2590 if (helper->user_callback) {
2591 /* This is not a GDK lock because we are a Tinymail callback and
2592 * Tinymail already acquires the Gdk lock */
2594 /* no gdk_threads_enter (), CHECKED */
2595 helper->user_callback (self, helper->user_data);
2596 /* no gdk_threads_leave (), CHECKED */
2600 if (helper->headers)
2601 g_object_unref (helper->headers);
2602 if (helper->dest_folder)
2603 g_object_unref (helper->dest_folder);
2604 if (helper->mail_op)
2605 g_object_unref (helper->mail_op);
2607 g_object_unref (folder);
2609 g_object_unref (iter);
2610 g_slice_free (XFerMsgsAsyncHelper, helper);
2614 compute_message_list_size (TnyList *headers)
2619 iter = tny_list_create_iterator (headers);
2620 while (!tny_iterator_is_done (iter)) {
2621 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2622 size += tny_header_get_message_size (header);
2623 g_object_unref (header);
2624 tny_iterator_next (iter);
2626 g_object_unref (iter);
2632 compute_message_array_size (GPtrArray *headers)
2637 for (i = 0; i < headers->len; i++) {
2638 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2639 size += tny_header_get_message_size (header);
2647 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2650 gboolean delete_original,
2651 XferMsgsAsyncUserCallback user_callback,
2654 ModestMailOperationPrivate *priv = NULL;
2655 TnyIterator *iter = NULL;
2656 TnyFolder *src_folder = NULL;
2657 XFerMsgsAsyncHelper *helper = NULL;
2658 TnyHeader *header = NULL;
2659 ModestTnyFolderRules rules = 0;
2661 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2662 g_return_if_fail (headers && TNY_IS_LIST (headers));
2663 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2665 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2666 priv->total = tny_list_get_length (headers);
2668 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2669 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2671 /* Apply folder rules */
2672 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2673 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2674 /* Set status failed and set an error */
2675 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2676 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2677 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2678 _CS("ckct_ib_unable_to_paste_here"));
2679 /* Notify the queue */
2680 modest_mail_operation_notify_end (self);
2684 /* Get source folder */
2685 iter = tny_list_create_iterator (headers);
2686 header = TNY_HEADER (tny_iterator_get_current (iter));
2688 src_folder = tny_header_get_folder (header);
2689 g_object_unref (header);
2691 g_object_unref (iter);
2693 if (src_folder == NULL) {
2694 /* Notify the queue */
2695 modest_mail_operation_notify_end (self);
2697 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2702 /* Check folder source and destination */
2703 if (src_folder == folder) {
2704 /* Set status failed and set an error */
2705 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2706 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2707 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2708 _("mail_in_ui_folder_copy_target_error"));
2710 /* Notify the queue */
2711 modest_mail_operation_notify_end (self);
2714 g_object_unref (src_folder);
2718 /* Create the helper */
2719 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2720 helper->mail_op = g_object_ref(self);
2721 helper->dest_folder = g_object_ref(folder);
2722 helper->headers = g_object_ref(headers);
2723 helper->user_callback = user_callback;
2724 helper->user_data = user_data;
2725 helper->delete = delete_original;
2726 helper->last_total_bytes = 0;
2727 helper->sum_total_bytes = 0;
2728 helper->total_bytes = compute_message_list_size (headers);
2730 /* Get account and set it into mail_operation */
2731 priv->account = modest_tny_folder_get_account (src_folder);
2733 /* Transfer messages */
2734 modest_mail_operation_notify_start (self);
2735 tny_folder_transfer_msgs_async (src_folder,
2740 transfer_msgs_status_cb,
2746 on_refresh_folder (TnyFolder *folder,
2751 RefreshAsyncHelper *helper = NULL;
2752 ModestMailOperation *self = NULL;
2753 ModestMailOperationPrivate *priv = NULL;
2755 helper = (RefreshAsyncHelper *) user_data;
2756 self = helper->mail_op;
2757 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2759 g_return_if_fail(priv!=NULL);
2762 priv->error = g_error_copy (error);
2763 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2768 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2769 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2770 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2771 _("Error trying to refresh the contents of %s"),
2772 tny_folder_get_name (folder));
2776 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2779 /* Call user defined callback, if it exists */
2780 if (helper->user_callback) {
2782 /* This is not a GDK lock because we are a Tinymail callback and
2783 * Tinymail already acquires the Gdk lock */
2784 helper->user_callback (self, folder, helper->user_data);
2788 g_slice_free (RefreshAsyncHelper, helper);
2790 /* Notify about operation end */
2791 modest_mail_operation_notify_end (self);
2792 g_object_unref(self);
2796 on_refresh_folder_status_update (GObject *obj,
2800 RefreshAsyncHelper *helper = NULL;
2801 ModestMailOperation *self = NULL;
2802 ModestMailOperationPrivate *priv = NULL;
2803 ModestMailOperationState *state;
2805 g_return_if_fail (user_data != NULL);
2806 g_return_if_fail (status != NULL);
2807 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2809 helper = (RefreshAsyncHelper *) user_data;
2810 self = helper->mail_op;
2811 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2813 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2815 priv->done = status->position;
2816 priv->total = status->of_total;
2818 state = modest_mail_operation_clone_state (self);
2820 /* This is not a GDK lock because we are a Tinymail callback and
2821 * Tinymail already acquires the Gdk lock */
2822 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2824 g_slice_free (ModestMailOperationState, state);
2828 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2830 RefreshAsyncUserCallback user_callback,
2833 ModestMailOperationPrivate *priv = NULL;
2834 RefreshAsyncHelper *helper = NULL;
2836 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2838 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2840 /* Get account and set it into mail_operation */
2841 priv->account = modest_tny_folder_get_account (folder);
2842 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2844 /* Create the helper */
2845 helper = g_slice_new0 (RefreshAsyncHelper);
2846 helper->mail_op = g_object_ref(self);
2847 helper->user_callback = user_callback;
2848 helper->user_data = user_data;
2850 /* Refresh the folder. TODO: tinymail could issue a status
2851 updates before the callback call then this could happen. We
2852 must review the design */
2853 modest_mail_operation_notify_start (self);
2855 /* notify that the operation was started */
2856 ModestMailOperationState *state;
2857 state = modest_mail_operation_clone_state (self);
2860 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2863 tny_folder_refresh_async (folder,
2865 on_refresh_folder_status_update,
2870 run_queue_stop (ModestTnySendQueue *queue,
2871 ModestMailOperation *self)
2873 ModestMailOperationPrivate *priv;
2875 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2876 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2877 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2879 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2881 modest_mail_operation_notify_end (self);
2882 g_signal_handlers_disconnect_by_func (queue, run_queue_stop, self);
2883 g_object_unref (self);
2886 modest_mail_operation_run_queue (ModestMailOperation *self,
2887 ModestTnySendQueue *queue)
2889 ModestMailOperationPrivate *priv;
2891 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2892 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2893 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2895 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2896 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
2897 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
2899 modest_mail_operation_notify_start (self);
2900 g_object_ref (self);
2901 g_signal_connect ((gpointer) queue, "queue-stop", G_CALLBACK (run_queue_stop), (gpointer) self);
2905 sync_folder_finish_callback (TnyFolder *self, gboolean cancelled, GError *err, ModestMailOperation *mail_op)
2907 ModestMailOperationPrivate *priv;
2909 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
2911 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2912 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2914 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2916 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2918 modest_mail_operation_notify_end (mail_op);
2919 g_object_unref (mail_op);
2923 modest_mail_operation_sync_folder (ModestMailOperation *self,
2924 TnyFolder *folder, gboolean expunge)
2926 ModestMailOperationPrivate *priv;
2928 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2929 g_return_if_fail (TNY_IS_FOLDER (folder));
2930 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2932 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2933 priv->account = TNY_ACCOUNT (tny_folder_get_account (folder));
2934 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
2936 modest_mail_operation_notify_start (self);
2937 g_object_ref (self);
2938 tny_folder_sync_async (folder, expunge, (TnyFolderCallback) sync_folder_finish_callback, NULL, self);
2942 modest_mail_operation_notify_start (ModestMailOperation *self)
2944 ModestMailOperationPrivate *priv = NULL;
2946 g_return_if_fail (self);
2948 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2950 /* Ensure that all the fields are filled correctly */
2951 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
2953 /* Notify the observers about the mail operation. We do not
2954 wrapp this emission because we assume that this function is
2955 always called from within the main lock */
2956 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
2961 * It's used by the mail operation queue to notify the observers
2962 * attached to that signal that the operation finished. We need to use
2963 * that because tinymail does not give us the progress of a given
2964 * operation when it finishes (it directly calls the operation
2968 modest_mail_operation_notify_end (ModestMailOperation *self)
2970 ModestMailOperationPrivate *priv = NULL;
2972 g_return_if_fail (self);
2974 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2976 /* Notify the observers about the mail operation end. We do
2977 not wrapp this emission because we assume that this
2978 function is always called from within the main lock */
2979 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
2981 /* Remove the error user data */
2982 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
2983 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
2987 modest_mail_operation_get_account (ModestMailOperation *self)
2989 ModestMailOperationPrivate *priv = NULL;
2991 g_return_val_if_fail (self, NULL);
2993 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2995 return (priv->account) ? g_object_ref (priv->account) : NULL;
2999 modest_mail_operation_noop (ModestMailOperation *self)
3001 ModestMailOperationPrivate *priv = NULL;
3003 g_return_if_fail (self);
3005 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3006 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3007 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3011 /* This mail operation does nothing actually */
3012 modest_mail_operation_notify_start (self);
3013 modest_mail_operation_notify_end (self);
3018 modest_mail_operation_to_string (ModestMailOperation *self)
3020 const gchar *type, *status, *account_id;
3021 ModestMailOperationPrivate *priv = NULL;
3023 g_return_val_if_fail (self, NULL);
3025 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3027 /* new operations don't have anything interesting */
3028 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3029 return g_strdup_printf ("%p <new operation>", self);
3031 switch (priv->op_type) {
3032 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3033 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3034 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3035 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3036 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3037 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3038 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3039 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3040 default: type = "UNEXPECTED"; break;
3043 switch (priv->status) {
3044 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3045 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3046 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3047 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3048 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3049 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3050 default: status= "UNEXPECTED"; break;
3053 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3055 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3056 priv->done, priv->total,
3057 priv->error && priv->error->message ? priv->error->message : "");