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;
138 TnyIterator *more_msgs;
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 TnyIterator *more_msgs;
158 TnyFolder *dest_folder;
159 XferMsgsAsyncUserCallback user_callback;
162 gint last_total_bytes;
163 gint sum_total_bytes;
165 } XFerMsgsAsyncHelper;
167 typedef struct _XFerFolderAsyncHelper
169 ModestMailOperation *mail_op;
170 XferFolderAsyncUserCallback user_callback;
172 } XFerFolderAsyncHelper;
174 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
178 static void modest_mail_operation_create_msg (ModestMailOperation *self,
179 const gchar *from, const gchar *to,
180 const gchar *cc, const gchar *bcc,
181 const gchar *subject, const gchar *plain_body,
182 const gchar *html_body, const GList *attachments_list,
183 const GList *images_list,
184 TnyHeaderFlags priority_flags,
185 ModestMailOperationCreateMsgCallback callback,
188 static gboolean idle_notify_queue (gpointer data);
191 ModestMailOperation *mail_op;
199 GList *attachments_list;
201 TnyHeaderFlags priority_flags;
202 ModestMailOperationCreateMsgCallback callback;
208 ModestMailOperation *mail_op;
210 ModestMailOperationCreateMsgCallback callback;
215 static GObjectClass *parent_class = NULL;
217 static guint signals[NUM_SIGNALS] = {0};
220 modest_mail_operation_get_type (void)
222 static GType my_type = 0;
224 static const GTypeInfo my_info = {
225 sizeof(ModestMailOperationClass),
226 NULL, /* base init */
227 NULL, /* base finalize */
228 (GClassInitFunc) modest_mail_operation_class_init,
229 NULL, /* class finalize */
230 NULL, /* class data */
231 sizeof(ModestMailOperation),
233 (GInstanceInitFunc) modest_mail_operation_init,
236 my_type = g_type_register_static (G_TYPE_OBJECT,
237 "ModestMailOperation",
244 modest_mail_operation_class_init (ModestMailOperationClass *klass)
246 GObjectClass *gobject_class;
247 gobject_class = (GObjectClass*) klass;
249 parent_class = g_type_class_peek_parent (klass);
250 gobject_class->finalize = modest_mail_operation_finalize;
252 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
255 * ModestMailOperation::progress-changed
256 * @self: the #MailOperation that emits the signal
257 * @user_data: user data set when the signal handler was connected
259 * Emitted when the progress of a mail operation changes
261 signals[PROGRESS_CHANGED_SIGNAL] =
262 g_signal_new ("progress-changed",
263 G_TYPE_FROM_CLASS (gobject_class),
265 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
267 g_cclosure_marshal_VOID__POINTER,
268 G_TYPE_NONE, 1, G_TYPE_POINTER);
272 * This signal is issued whenever a mail operation starts, and
273 * starts mean when the tinymail operation is issued. This
274 * means that it could happen that something wrong happens and
275 * the tinymail function is never called. In this situation a
276 * operation-finished will be issued without any
279 signals[OPERATION_STARTED_SIGNAL] =
280 g_signal_new ("operation-started",
281 G_TYPE_FROM_CLASS (gobject_class),
283 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
285 g_cclosure_marshal_VOID__VOID,
290 * This signal is issued whenever a mail operation
291 * finishes. Note that this signal could be issued without any
292 * previous "operation-started" signal, because this last one
293 * is only issued when the tinymail operation is successfully
296 signals[OPERATION_FINISHED_SIGNAL] =
297 g_signal_new ("operation-finished",
298 G_TYPE_FROM_CLASS (gobject_class),
300 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
302 g_cclosure_marshal_VOID__VOID,
307 modest_mail_operation_init (ModestMailOperation *obj)
309 ModestMailOperationPrivate *priv;
311 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
313 priv->account = NULL;
314 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
315 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
320 priv->error_checking = NULL;
321 priv->error_checking_user_data = NULL;
325 modest_mail_operation_finalize (GObject *obj)
327 ModestMailOperationPrivate *priv;
329 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
334 g_error_free (priv->error);
338 g_object_unref (priv->source);
342 g_object_unref (priv->account);
343 priv->account = NULL;
347 G_OBJECT_CLASS(parent_class)->finalize (obj);
351 modest_mail_operation_new (GObject *source)
353 ModestMailOperation *obj;
354 ModestMailOperationPrivate *priv;
356 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
357 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
360 priv->source = g_object_ref(source);
366 modest_mail_operation_new_with_error_handling (GObject *source,
367 ErrorCheckingUserCallback error_handler,
369 ErrorCheckingUserDataDestroyer error_handler_destroyer)
371 ModestMailOperation *obj;
372 ModestMailOperationPrivate *priv;
374 obj = modest_mail_operation_new (source);
375 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
377 g_return_val_if_fail (error_handler != NULL, obj);
378 priv->error_checking = error_handler;
379 priv->error_checking_user_data = user_data;
380 priv->error_checking_user_data_destroyer = error_handler_destroyer;
386 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
388 ModestMailOperationPrivate *priv;
390 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
392 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
393 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
395 /* Call the user callback */
396 if (priv->error_checking != NULL)
397 priv->error_checking (self, priv->error_checking_user_data);
401 ModestMailOperationTypeOperation
402 modest_mail_operation_get_type_operation (ModestMailOperation *self)
404 ModestMailOperationPrivate *priv;
406 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
407 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
409 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
411 return priv->op_type;
415 modest_mail_operation_is_mine (ModestMailOperation *self,
418 ModestMailOperationPrivate *priv;
420 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
423 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
424 if (priv->source == NULL) return FALSE;
426 return priv->source == me;
430 modest_mail_operation_get_source (ModestMailOperation *self)
432 ModestMailOperationPrivate *priv;
434 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
437 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
439 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
443 return (priv->source) ? g_object_ref (priv->source) : NULL;
446 ModestMailOperationStatus
447 modest_mail_operation_get_status (ModestMailOperation *self)
449 ModestMailOperationPrivate *priv;
451 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
452 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
453 MODEST_MAIL_OPERATION_STATUS_INVALID);
455 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
457 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
458 return MODEST_MAIL_OPERATION_STATUS_INVALID;
465 modest_mail_operation_get_error (ModestMailOperation *self)
467 ModestMailOperationPrivate *priv;
469 g_return_val_if_fail (self, NULL);
470 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
472 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
475 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
483 modest_mail_operation_cancel (ModestMailOperation *self)
485 ModestMailOperationPrivate *priv;
486 gboolean canceled = FALSE;
488 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
490 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
493 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
495 /* Cancel the mail operation */
496 g_return_val_if_fail (priv->account, FALSE);
497 tny_account_cancel (priv->account);
499 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
500 ModestTnySendQueue *queue;
501 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account));
503 /* Cancel the sending of the following next messages */
504 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, NULL);
511 modest_mail_operation_get_task_done (ModestMailOperation *self)
513 ModestMailOperationPrivate *priv;
515 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
518 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
523 modest_mail_operation_get_task_total (ModestMailOperation *self)
525 ModestMailOperationPrivate *priv;
527 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
530 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
535 modest_mail_operation_is_finished (ModestMailOperation *self)
537 ModestMailOperationPrivate *priv;
538 gboolean retval = FALSE;
540 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
543 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
545 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
546 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
547 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
548 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
558 * Creates an image of the current state of a mail operation, the
559 * caller must free it
561 static ModestMailOperationState *
562 modest_mail_operation_clone_state (ModestMailOperation *self)
564 ModestMailOperationState *state;
565 ModestMailOperationPrivate *priv;
567 /* FIXME: this should be fixed properly
569 * in some cases, priv was NULL, so checking here to
572 g_return_val_if_fail (self, NULL);
573 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
574 g_return_val_if_fail (priv, NULL);
579 state = g_slice_new (ModestMailOperationState);
581 state->status = priv->status;
582 state->op_type = priv->op_type;
583 state->done = priv->done;
584 state->total = priv->total;
585 state->finished = modest_mail_operation_is_finished (self);
586 state->bytes_done = 0;
587 state->bytes_total = 0;
592 /* ******************************************************************* */
593 /* ************************** SEND ACTIONS ************************* */
594 /* ******************************************************************* */
597 modest_mail_operation_send_mail (ModestMailOperation *self,
598 TnyTransportAccount *transport_account,
601 TnySendQueue *send_queue = NULL;
602 ModestMailOperationPrivate *priv;
604 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
605 g_return_if_fail (transport_account && TNY_IS_TRANSPORT_ACCOUNT (transport_account));
606 g_return_if_fail (msg && TNY_IS_MSG (msg));
608 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
610 /* Get account and set it into mail_operation */
611 priv->account = g_object_ref (transport_account);
612 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
616 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
617 if (!TNY_IS_SEND_QUEUE(send_queue)) {
618 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
619 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
620 "modest: could not find send queue for account\n");
621 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
622 modest_mail_operation_notify_end (self);
625 /* Add the msg to the queue */
626 modest_mail_operation_notify_start (self);
628 tny_send_queue_add_async (send_queue, msg, NULL, NULL, NULL);
630 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
631 modest_mail_operation_notify_end (self);
638 idle_create_msg_cb (gpointer idle_data)
640 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
642 /* This is a GDK lock because we are an idle callback and
643 * info->callback can contain Gtk+ code */
645 gdk_threads_enter (); /* CHECKED */
646 info->callback (info->mail_op, info->msg, info->userdata);
648 g_object_unref (info->mail_op);
650 g_object_unref (info->msg);
651 g_slice_free (CreateMsgIdleInfo, info);
652 gdk_threads_leave (); /* CHECKED */
658 create_msg_thread (gpointer thread_data)
660 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
661 TnyMsg *new_msg = NULL;
662 ModestMailOperationPrivate *priv;
664 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
665 if (info->html_body == NULL) {
666 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
667 info->bcc, info->subject, info->plain_body,
668 info->attachments_list);
670 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
671 info->bcc, info->subject, info->html_body,
672 info->plain_body, info->attachments_list,
679 /* Set priority flags in message */
680 header = tny_msg_get_header (new_msg);
681 tny_header_set_flag (header, info->priority_flags);
683 /* Set attachment flags in message */
684 if (info->attachments_list != NULL)
685 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
687 g_object_unref (G_OBJECT(header));
689 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
690 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
691 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
692 "modest: failed to create a new msg\n");
700 g_free (info->plain_body);
701 g_free (info->html_body);
702 g_free (info->subject);
703 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
704 g_list_free (info->attachments_list);
705 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
706 g_list_free (info->images_list);
708 if (info->callback) {
709 CreateMsgIdleInfo *idle_info;
710 idle_info = g_slice_new0 (CreateMsgIdleInfo);
711 idle_info->mail_op = g_object_ref (info->mail_op);
712 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
713 idle_info->callback = info->callback;
714 idle_info->userdata = info->userdata;
715 g_idle_add (idle_create_msg_cb, idle_info);
717 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
720 g_object_unref (info->mail_op);
721 g_slice_free (CreateMsgInfo, info);
722 if (new_msg) g_object_unref(new_msg);
728 modest_mail_operation_create_msg (ModestMailOperation *self,
729 const gchar *from, const gchar *to,
730 const gchar *cc, const gchar *bcc,
731 const gchar *subject, const gchar *plain_body,
732 const gchar *html_body,
733 const GList *attachments_list,
734 const GList *images_list,
735 TnyHeaderFlags priority_flags,
736 ModestMailOperationCreateMsgCallback callback,
739 CreateMsgInfo *info = NULL;
741 info = g_slice_new0 (CreateMsgInfo);
742 info->mail_op = g_object_ref (self);
744 info->from = g_strdup (from);
745 info->to = g_strdup (to);
746 info->cc = g_strdup (cc);
747 info->bcc = g_strdup (bcc);
748 info->subject = g_strdup (subject);
749 info->plain_body = g_strdup (plain_body);
750 info->html_body = g_strdup (html_body);
751 info->attachments_list = g_list_copy ((GList *) attachments_list);
752 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
753 info->images_list = g_list_copy ((GList *) images_list);
754 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
755 info->priority_flags = priority_flags;
757 info->callback = callback;
758 info->userdata = userdata;
760 g_thread_create (create_msg_thread, info, FALSE, NULL);
765 TnyTransportAccount *transport_account;
770 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
774 ModestMailOperationPrivate *priv = NULL;
775 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
776 TnyFolder *draft_folder = NULL;
777 TnyFolder *outbox_folder = NULL;
778 TnyHeader *header = NULL;
785 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
788 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
789 modest_mail_operation_notify_end (self);
793 /* Call mail operation */
794 modest_mail_operation_send_mail (self, info->transport_account, msg);
796 if (info->draft_msg != NULL) {
797 TnyFolder *folder = NULL;
798 TnyFolder *src_folder = NULL;
799 TnyFolderType folder_type;
800 TnyTransportAccount *transport_account = NULL;
802 /* To remove the old mail from its source folder, we need to get the
803 * transport account of the original draft message (the transport account
804 * might have been changed by the user) */
805 header = tny_msg_get_header (info->draft_msg);
806 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
807 modest_runtime_get_account_store(), header);
808 if (transport_account == NULL)
809 transport_account = g_object_ref(info->transport_account);
810 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
811 TNY_FOLDER_TYPE_DRAFTS);
812 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
813 TNY_FOLDER_TYPE_OUTBOX);
814 g_object_unref(transport_account);
817 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
821 if (!outbox_folder) {
822 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
827 folder = tny_msg_get_folder (info->draft_msg);
828 if (folder == NULL) goto end;
829 folder_type = modest_tny_folder_guess_folder_type (folder);
831 if (folder_type == TNY_FOLDER_TYPE_INVALID)
832 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
834 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
835 src_folder = outbox_folder;
837 src_folder = draft_folder;
839 /* Note: This can fail (with a warning) if the message is not really already in a folder,
840 * because this function requires it to have a UID. */
841 tny_folder_remove_msg (src_folder, header, NULL);
843 tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */
844 /* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */
846 g_object_unref (folder);
851 g_object_unref (header);
855 g_object_unref (info->draft_msg);
857 g_object_unref (draft_folder);
859 g_object_unref (outbox_folder);
860 if (info->transport_account)
861 g_object_unref (info->transport_account);
862 g_slice_free (SendNewMailInfo, info);
866 modest_mail_operation_send_new_mail (ModestMailOperation *self,
867 TnyTransportAccount *transport_account,
869 const gchar *from, const gchar *to,
870 const gchar *cc, const gchar *bcc,
871 const gchar *subject, const gchar *plain_body,
872 const gchar *html_body,
873 const GList *attachments_list,
874 const GList *images_list,
875 TnyHeaderFlags priority_flags)
877 ModestMailOperationPrivate *priv = NULL;
878 SendNewMailInfo *info;
880 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
881 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
883 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
884 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
885 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
886 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
888 /* Check parametters */
890 /* Set status failed and set an error */
891 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
892 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
893 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
894 _("Error trying to send a mail. You need to set at least one recipient"));
897 info = g_slice_new0 (SendNewMailInfo);
898 info->transport_account = transport_account;
899 if (transport_account)
900 g_object_ref (transport_account);
901 info->draft_msg = draft_msg;
903 g_object_ref (draft_msg);
906 modest_mail_operation_notify_start (self);
907 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
908 attachments_list, images_list, priority_flags,
909 modest_mail_operation_send_new_mail_cb, info);
915 TnyTransportAccount *transport_account;
917 SaveToDraftstCallback callback;
921 ModestMailOperation *mailop;
922 } SaveToDraftsAddMsgInfo;
925 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
930 ModestMailOperationPrivate *priv = NULL;
931 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
933 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
936 g_warning ("%s: priv->error != NULL", __FUNCTION__);
937 g_error_free(priv->error);
940 priv->error = (err == NULL) ? NULL : g_error_copy(err);
942 if ((!priv->error) && (info->draft_msg != NULL)) {
943 TnyHeader *header = tny_msg_get_header (info->draft_msg);
944 TnyFolder *src_folder = tny_header_get_folder (header);
946 /* Remove the old draft */
947 tny_folder_remove_msg (src_folder, header, NULL);
949 /* Synchronize to expunge and to update the msg counts */
950 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
951 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
953 g_object_unref (G_OBJECT(header));
954 g_object_unref (G_OBJECT(src_folder));
958 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
960 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
962 /* Call the user callback */
964 info->callback (info->mailop, info->msg, info->user_data);
966 if (info->transport_account)
967 g_object_unref (G_OBJECT(info->transport_account));
969 g_object_unref (G_OBJECT (info->draft_msg));
971 g_object_unref (G_OBJECT(info->drafts));
973 g_object_unref (G_OBJECT (info->msg));
975 modest_mail_operation_notify_end (info->mailop);
976 g_object_unref(info->mailop);
977 g_slice_free (SaveToDraftsAddMsgInfo, info);
982 TnyTransportAccount *transport_account;
984 SaveToDraftstCallback callback;
989 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
993 TnyFolder *drafts = NULL;
994 ModestMailOperationPrivate *priv = NULL;
995 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
997 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1000 if (!(priv->error)) {
1001 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1002 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1003 "modest: failed to create a new msg\n");
1006 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1007 TNY_FOLDER_TYPE_DRAFTS);
1008 if (!drafts && !(priv->error)) {
1009 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1010 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1011 "modest: failed to create a new msg\n");
1016 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1017 cb_info->transport_account = g_object_ref(info->transport_account);
1018 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1019 cb_info->callback = info->callback;
1020 cb_info->user_data = info->user_data;
1021 cb_info->drafts = g_object_ref(drafts);
1022 cb_info->msg = g_object_ref(msg);
1023 cb_info->mailop = g_object_ref(self);
1024 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1027 /* Call the user callback */
1028 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1030 info->callback (self, msg, info->user_data);
1031 modest_mail_operation_notify_end (self);
1035 g_object_unref (G_OBJECT(drafts));
1036 if (info->draft_msg)
1037 g_object_unref (G_OBJECT (info->draft_msg));
1038 if (info->transport_account)
1039 g_object_unref (G_OBJECT(info->transport_account));
1040 g_slice_free (SaveToDraftsInfo, info);
1044 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1045 TnyTransportAccount *transport_account,
1047 const gchar *from, const gchar *to,
1048 const gchar *cc, const gchar *bcc,
1049 const gchar *subject, const gchar *plain_body,
1050 const gchar *html_body,
1051 const GList *attachments_list,
1052 const GList *images_list,
1053 TnyHeaderFlags priority_flags,
1054 SaveToDraftstCallback callback,
1057 ModestMailOperationPrivate *priv = NULL;
1058 SaveToDraftsInfo *info = NULL;
1060 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1061 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1063 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1065 /* Get account and set it into mail_operation */
1066 priv->account = g_object_ref (transport_account);
1067 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1069 info = g_slice_new0 (SaveToDraftsInfo);
1070 info->transport_account = g_object_ref (transport_account);
1071 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1072 info->callback = callback;
1073 info->user_data = user_data;
1075 modest_mail_operation_notify_start (self);
1076 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1077 attachments_list, images_list, priority_flags,
1078 modest_mail_operation_save_to_drafts_cb, info);
1083 ModestMailOperation *mail_op;
1084 TnyMimePart *mime_part;
1086 GetMimePartSizeCallback callback;
1088 } GetMimePartSizeInfo;
1090 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1091 /* We use this folder observer to track the headers that have been
1092 * added to a folder */
1095 TnyList *new_headers;
1096 } InternalFolderObserver;
1099 GObjectClass parent;
1100 } InternalFolderObserverClass;
1102 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1104 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1105 internal_folder_observer,
1107 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1111 foreach_add_item (gpointer header, gpointer user_data)
1113 tny_list_prepend (TNY_LIST (user_data),
1114 g_object_ref (G_OBJECT (header)));
1117 /* This is the method that looks for new messages in a folder */
1119 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1121 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1123 TnyFolderChangeChanged changed;
1125 changed = tny_folder_change_get_changed (change);
1127 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1130 /* Get added headers */
1131 list = tny_simple_list_new ();
1132 tny_folder_change_get_added_headers (change, list);
1134 /* Add them to the folder observer */
1135 tny_list_foreach (list, foreach_add_item,
1136 derived->new_headers);
1138 g_object_unref (G_OBJECT (list));
1143 internal_folder_observer_init (InternalFolderObserver *self)
1145 self->new_headers = tny_simple_list_new ();
1148 internal_folder_observer_finalize (GObject *object)
1150 InternalFolderObserver *self;
1152 self = (InternalFolderObserver *) object;
1153 g_object_unref (self->new_headers);
1155 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1158 tny_folder_observer_init (TnyFolderObserverIface *iface)
1160 iface->update = internal_folder_observer_update;
1163 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1165 GObjectClass *object_class;
1167 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1168 object_class = (GObjectClass*) klass;
1169 object_class->finalize = internal_folder_observer_finalize;
1174 ModestMailOperation *mail_op;
1175 gchar *account_name;
1176 UpdateAccountCallback callback;
1181 TnyFolderObserver *inbox_observer;
1182 RetrieveAllCallback retrieve_all_cb;
1183 } UpdateAccountInfo;
1187 destroy_update_account_info (UpdateAccountInfo *info)
1189 g_free (info->account_name);
1190 g_object_unref (info->folders);
1191 g_object_unref (info->mail_op);
1192 g_slice_free (UpdateAccountInfo, info);
1196 update_account_get_msg_async_cb (TnyFolder *folder,
1202 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1204 /* Just delete the helper. Don't do anything with the new
1205 msg. There is also no need to check for errors */
1206 g_object_unref (msg_info->mail_op);
1207 g_object_unref (msg_info->header);
1208 g_slice_free (GetMsgInfo, msg_info);
1212 inbox_refreshed_cb (TnyFolder *inbox,
1217 UpdateAccountInfo *info;
1218 ModestMailOperationPrivate *priv;
1219 TnyIterator *new_headers_iter;
1220 GPtrArray *new_headers_array = NULL;
1221 gint max_size, retrieve_limit, i;
1222 ModestAccountMgr *mgr;
1223 ModestAccountRetrieveType retrieve_type;
1224 TnyList *new_headers = NULL;
1225 gboolean headers_only, ignore_limit;
1226 TnyTransportAccount *transport_account = NULL;
1228 info = (UpdateAccountInfo *) user_data;
1229 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1230 mgr = modest_runtime_get_account_mgr ();
1232 if (canceled || err || !inbox) {
1233 /* Try to send anyway */
1237 /* Get the message max size */
1238 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1239 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1241 max_size = G_MAXINT;
1243 max_size = max_size * KB;
1245 /* Create the new headers array. We need it to sort the
1246 new headers by date */
1247 new_headers_array = g_ptr_array_new ();
1248 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1249 while (!tny_iterator_is_done (new_headers_iter)) {
1250 TnyHeader *header = NULL;
1252 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1253 /* Apply per-message size limits */
1254 if (tny_header_get_message_size (header) < max_size)
1255 g_ptr_array_add (new_headers_array, g_object_ref (header));
1257 g_object_unref (header);
1258 tny_iterator_next (new_headers_iter);
1260 g_object_unref (new_headers_iter);
1261 tny_folder_remove_observer (inbox, info->inbox_observer);
1262 g_object_unref (info->inbox_observer);
1263 info->inbox_observer = NULL;
1265 /* Update the last updated key, even if we don't have to get new headers */
1266 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time (NULL));
1268 if (new_headers_array->len == 0)
1271 /* Get per-account message amount retrieval limit */
1272 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1273 if (retrieve_limit == 0)
1274 retrieve_limit = G_MAXINT;
1276 /* Get per-account retrieval type */
1277 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1278 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1281 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1283 /* Ask the users if they want to retrieve all the messages
1284 even though the limit was exceeded */
1285 ignore_limit = FALSE;
1286 if (new_headers_array->len > retrieve_limit) {
1287 /* Ask the user if a callback has been specified and
1288 if the mail operation has a source (this means that
1289 was invoked by the user and not automatically by a
1291 if (info->retrieve_all_cb && priv->source)
1292 ignore_limit = info->retrieve_all_cb (priv->source,
1293 new_headers_array->len,
1297 if (!headers_only) {
1299 const gint msg_list_size = compute_message_array_size (new_headers_array);
1303 priv->total = new_headers_array->len;
1305 priv->total = MIN (new_headers_array->len, retrieve_limit);
1306 while (msg_num < priv->total) {
1307 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1308 TnyFolder *folder = tny_header_get_folder (header);
1309 GetMsgInfo *msg_info;
1311 /* Create the message info */
1312 msg_info = g_slice_new0 (GetMsgInfo);
1313 msg_info->mail_op = g_object_ref (info->mail_op);
1314 msg_info->header = g_object_ref (header);
1315 msg_info->total_bytes = msg_list_size;
1317 /* Get message in an async way */
1318 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1319 get_msg_status_cb, msg_info);
1321 g_object_unref (folder);
1327 /* Copy the headers to a list and free the array */
1328 new_headers = tny_simple_list_new ();
1329 for (i=0; i < new_headers_array->len; i++) {
1330 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1331 tny_list_append (new_headers, G_OBJECT (header));
1333 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1334 g_ptr_array_free (new_headers_array, FALSE);
1337 /* Get the transport account */
1338 transport_account = (TnyTransportAccount *)
1339 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1340 info->account_name);
1342 if (transport_account) {
1343 ModestTnySendQueue *send_queue;
1347 send_queue = modest_runtime_get_send_queue (transport_account);
1348 g_object_unref (transport_account);
1350 /* Get outbox folder */
1351 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1352 if (outbox) { /* this could fail in some cases */
1353 num_messages = tny_folder_get_all_count (outbox);
1354 g_object_unref (outbox);
1356 g_warning ("%s: could not get outbox", __FUNCTION__);
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;
1495 ModestMailOperationState *state;
1497 /* Init mail operation */
1498 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1501 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1502 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1504 /* Get the store account */
1505 account_store = modest_runtime_get_account_store ();
1507 modest_tny_account_store_get_server_account (account_store,
1509 TNY_ACCOUNT_TYPE_STORE);
1511 /* Create the helper object */
1512 info = g_slice_new0 (UpdateAccountInfo);
1513 info->pending_calls = 1;
1514 info->folders = tny_simple_list_new ();
1515 info->mail_op = g_object_ref (self);
1516 info->poke_all = poke_all;
1517 info->account_name = g_strdup (account_name);
1518 info->callback = callback;
1519 info->user_data = user_data;
1520 info->retrieve_all_cb = retrieve_all_cb;
1522 /* Set account busy */
1523 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1524 modest_mail_operation_notify_start (self);
1526 /* notify about the start of the operation */
1527 state = modest_mail_operation_clone_state (self);
1531 /* Start notifying progress */
1532 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1533 g_slice_free (ModestMailOperationState, state);
1535 /* Get all folders and continue in the callback */
1536 folders = tny_simple_list_new ();
1537 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (priv->account),
1539 recurse_folders_async_cb,
1544 * Used to notify the queue from the main
1545 * loop. We call it inside an idle call to achieve that
1548 idle_notify_queue (gpointer data)
1550 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1552 gdk_threads_enter ();
1553 modest_mail_operation_notify_end (mail_op);
1554 gdk_threads_leave ();
1555 g_object_unref (mail_op);
1561 compare_headers_by_date (gconstpointer a,
1564 TnyHeader **header1, **header2;
1565 time_t sent1, sent2;
1567 header1 = (TnyHeader **) a;
1568 header2 = (TnyHeader **) b;
1570 sent1 = tny_header_get_date_sent (*header1);
1571 sent2 = tny_header_get_date_sent (*header2);
1573 /* We want the most recent ones (greater time_t) at the
1582 /* ******************************************************************* */
1583 /* ************************** STORE ACTIONS ************************* */
1584 /* ******************************************************************* */
1587 ModestMailOperation *mail_op;
1588 CreateFolderUserCallback callback;
1594 create_folder_cb (TnyFolderStore *parent_folder,
1596 TnyFolder *new_folder,
1600 ModestMailOperationPrivate *priv;
1601 CreateFolderInfo *info;
1603 info = (CreateFolderInfo *) user_data;
1604 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1606 if (canceled || err) {
1607 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1609 priv->error = g_error_copy (err);
1611 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1612 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1615 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1618 /* The user will unref the new_folder */
1620 info->callback (info->mail_op, parent_folder,
1621 new_folder, info->user_data);
1623 /* Notify about operation end */
1624 modest_mail_operation_notify_end (info->mail_op);
1627 g_object_unref (info->mail_op);
1628 g_slice_free (CreateFolderInfo, info);
1632 modest_mail_operation_create_folder (ModestMailOperation *self,
1633 TnyFolderStore *parent,
1635 CreateFolderUserCallback callback,
1638 ModestMailOperationPrivate *priv;
1640 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1641 g_return_if_fail (name);
1643 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1644 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1645 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1646 g_object_ref (parent) :
1647 modest_tny_folder_get_account (TNY_FOLDER (parent));
1649 /* Check for already existing folder */
1650 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1651 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1652 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1653 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1654 _CS("ckdg_ib_folder_already_exists"));
1658 if (TNY_IS_FOLDER (parent)) {
1659 /* Check folder rules */
1660 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1661 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1662 /* Set status failed and set an error */
1663 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1664 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1665 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1666 _("mail_in_ui_folder_create_error"));
1670 if (!strcmp (name, " ") || strchr (name, '/')) {
1671 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1672 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1673 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1674 _("mail_in_ui_folder_create_error"));
1678 CreateFolderInfo *info;
1680 info = g_slice_new0 (CreateFolderInfo);
1681 info->mail_op = g_object_ref (self);
1682 info->callback = callback;
1683 info->user_data = user_data;
1685 modest_mail_operation_notify_start (self);
1687 /* Create the folder */
1688 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1691 /* Call the user callback anyway */
1693 callback (self, parent, NULL, user_data);
1694 /* Notify about operation end */
1695 modest_mail_operation_notify_end (self);
1700 modest_mail_operation_remove_folder (ModestMailOperation *self,
1702 gboolean remove_to_trash)
1704 ModestMailOperationPrivate *priv;
1705 ModestTnyFolderRules rules;
1707 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1708 g_return_if_fail (TNY_IS_FOLDER (folder));
1710 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1712 /* Check folder rules */
1713 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1714 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1715 /* Set status failed and set an error */
1716 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1717 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1718 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1719 _("mail_in_ui_folder_delete_error"));
1723 /* Get the account */
1724 priv->account = modest_tny_folder_get_account (folder);
1725 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1727 /* Delete folder or move to trash */
1728 if (remove_to_trash) {
1729 TnyFolder *trash_folder = NULL;
1730 trash_folder = modest_tny_account_get_special_folder (priv->account,
1731 TNY_FOLDER_TYPE_TRASH);
1732 /* TODO: error_handling */
1734 modest_mail_operation_notify_start (self);
1735 modest_mail_operation_xfer_folder (self, folder,
1736 TNY_FOLDER_STORE (trash_folder),
1738 g_object_unref (trash_folder);
1740 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1743 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1745 modest_mail_operation_notify_start (self);
1746 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1747 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1750 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1752 g_object_unref (parent);
1754 g_warning ("%s: could not get parent folder", __FUNCTION__);
1758 /* Notify about operation end */
1759 modest_mail_operation_notify_end (self);
1763 transfer_folder_status_cb (GObject *obj,
1767 ModestMailOperation *self;
1768 ModestMailOperationPrivate *priv;
1769 ModestMailOperationState *state;
1770 XFerFolderAsyncHelper *helper;
1772 g_return_if_fail (status != NULL);
1773 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1775 helper = (XFerFolderAsyncHelper *) user_data;
1776 g_return_if_fail (helper != NULL);
1778 self = helper->mail_op;
1779 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1781 priv->done = status->position;
1782 priv->total = status->of_total;
1784 state = modest_mail_operation_clone_state (self);
1786 /* This is not a GDK lock because we are a Tinymail callback
1787 * which is already GDK locked by Tinymail */
1789 /* no gdk_threads_enter (), CHECKED */
1791 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1793 /* no gdk_threads_leave (), CHECKED */
1795 g_slice_free (ModestMailOperationState, state);
1800 transfer_folder_cb (TnyFolder *folder,
1802 TnyFolderStore *into,
1803 TnyFolder *new_folder,
1807 XFerFolderAsyncHelper *helper;
1808 ModestMailOperation *self = NULL;
1809 ModestMailOperationPrivate *priv = NULL;
1811 helper = (XFerFolderAsyncHelper *) user_data;
1812 g_return_if_fail (helper != NULL);
1814 self = helper->mail_op;
1815 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1818 priv->error = g_error_copy (err);
1820 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1821 } else if (cancelled) {
1822 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1823 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1824 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1825 _("Transference of %s was cancelled."),
1826 tny_folder_get_name (folder));
1829 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1832 /* Notify about operation end */
1833 modest_mail_operation_notify_end (self);
1835 /* If user defined callback function was defined, call it */
1836 if (helper->user_callback) {
1838 /* This is not a GDK lock because we are a Tinymail callback
1839 * which is already GDK locked by Tinymail */
1841 /* no gdk_threads_enter (), CHECKED */
1842 helper->user_callback (self, new_folder, helper->user_data);
1843 /* no gdk_threads_leave () , CHECKED */
1847 g_object_unref (helper->mail_op);
1848 g_slice_free (XFerFolderAsyncHelper, helper);
1853 * This function checks if the new name is a valid name for our local
1854 * folders account. The new name could not be the same than then name
1855 * of any of the mandatory local folders
1857 * We can not rely on tinymail because tinymail does not check the
1858 * name of the virtual folders that the account could have in the case
1859 * that we're doing a rename (because it directly calls Camel which
1860 * knows nothing about our virtual folders).
1862 * In the case of an actual copy/move (i.e. move/copy a folder between
1863 * accounts) tinymail uses the tny_folder_store_create_account which
1864 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1865 * checks the new name of the folder, so this call in that case
1866 * wouldn't be needed. *But* NOTE that if tinymail changes its
1867 * implementation (if folder transfers within the same account is no
1868 * longer implemented as a rename) this call will allow Modest to work
1871 * If the new name is not valid, this function will set the status to
1872 * failed and will set also an error in the mail operation
1875 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1876 TnyFolderStore *into,
1877 const gchar *new_name)
1879 if (TNY_IS_ACCOUNT (into) &&
1880 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1881 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1883 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1884 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1885 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1886 _CS("ckdg_ib_folder_already_exists"));
1893 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1895 TnyFolderStore *parent,
1896 gboolean delete_original,
1897 XferFolderAsyncUserCallback user_callback,
1900 ModestMailOperationPrivate *priv = NULL;
1901 ModestTnyFolderRules parent_rules = 0, rules;
1902 XFerFolderAsyncHelper *helper = NULL;
1903 const gchar *folder_name = NULL;
1904 const gchar *error_msg;
1906 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1907 g_return_if_fail (TNY_IS_FOLDER (folder));
1908 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1910 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1911 folder_name = tny_folder_get_name (folder);
1913 /* Set the error msg */
1914 error_msg = _("mail_in_ui_folder_move_target_error");
1916 /* Get account and set it into mail_operation */
1917 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1918 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1919 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1921 /* Get folder rules */
1922 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1923 if (TNY_IS_FOLDER (parent))
1924 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1926 /* Apply operation constraints */
1927 if ((gpointer) parent == (gpointer) folder ||
1928 (!TNY_IS_FOLDER_STORE (parent)) ||
1929 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1932 } else if (TNY_IS_FOLDER (parent) &&
1933 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
1937 } else if (TNY_IS_FOLDER (parent) &&
1938 TNY_IS_FOLDER_STORE (folder) &&
1939 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
1940 TNY_FOLDER_STORE (folder))) {
1941 /* Do not move a parent into a child */
1943 } else if (TNY_IS_FOLDER_STORE (parent) &&
1944 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
1945 /* Check that the new folder name is not used by any
1948 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
1949 /* Check that the new folder name is not used by any
1950 special local folder */
1953 /* Create the helper */
1954 helper = g_slice_new0 (XFerFolderAsyncHelper);
1955 helper->mail_op = g_object_ref (self);
1956 helper->user_callback = user_callback;
1957 helper->user_data = user_data;
1959 /* Move/Copy folder */
1960 modest_mail_operation_notify_start (self);
1961 tny_folder_copy_async (folder,
1963 tny_folder_get_name (folder),
1966 transfer_folder_status_cb,
1972 /* Set status failed and set an error */
1973 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1974 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1975 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1978 /* Call the user callback if exists */
1980 user_callback (self, NULL, user_data);
1982 /* Notify the queue */
1983 modest_mail_operation_notify_end (self);
1987 modest_mail_operation_rename_folder (ModestMailOperation *self,
1990 XferFolderAsyncUserCallback user_callback,
1993 ModestMailOperationPrivate *priv;
1994 ModestTnyFolderRules rules;
1995 XFerFolderAsyncHelper *helper;
1997 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1998 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
1999 g_return_if_fail (name);
2001 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2003 /* Get account and set it into mail_operation */
2004 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2005 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2007 /* Check folder rules */
2008 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2009 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2011 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2014 TnyFolderStore *into;
2016 into = tny_folder_get_folder_store (folder);
2018 /* Check that the new folder name is not used by any
2019 special local folder */
2020 if (new_name_valid_if_local_account (priv, into, name)) {
2021 /* Create the helper */
2022 helper = g_slice_new0 (XFerFolderAsyncHelper);
2023 helper->mail_op = g_object_ref(self);
2024 helper->user_callback = user_callback;
2025 helper->user_data = user_data;
2027 /* Rename. Camel handles folder subscription/unsubscription */
2028 modest_mail_operation_notify_start (self);
2029 tny_folder_copy_async (folder, into, name, TRUE,
2031 transfer_folder_status_cb,
2036 g_object_unref (into);
2041 /* Set status failed and set an error */
2042 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2043 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2044 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2045 _("FIXME: unable to rename"));
2048 user_callback (self, NULL, user_data);
2050 /* Notify about operation end */
2051 modest_mail_operation_notify_end (self);
2054 /* ******************************************************************* */
2055 /* ************************** MSG ACTIONS ************************* */
2056 /* ******************************************************************* */
2059 modest_mail_operation_get_msg (ModestMailOperation *self,
2061 GetMsgAsyncUserCallback user_callback,
2064 GetMsgInfo *helper = NULL;
2066 ModestMailOperationPrivate *priv;
2068 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2069 g_return_if_fail (TNY_IS_HEADER (header));
2071 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2072 folder = tny_header_get_folder (header);
2074 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2078 /* Get account and set it into mail_operation */
2079 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2081 /* Check for cached messages */
2082 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2083 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2085 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2087 /* Create the helper */
2088 helper = g_slice_new0 (GetMsgInfo);
2089 helper->header = g_object_ref (header);
2090 helper->mail_op = g_object_ref (self);
2091 helper->user_callback = user_callback;
2092 helper->user_data = user_data;
2093 helper->destroy_notify = NULL;
2094 helper->last_total_bytes = 0;
2095 helper->sum_total_bytes = 0;
2096 helper->total_bytes = tny_header_get_message_size (header);
2098 modest_mail_operation_notify_start (self);
2100 /* notify about the start of the operation */
2101 ModestMailOperationState *state;
2102 state = modest_mail_operation_clone_state (self);
2105 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2108 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2110 g_object_unref (G_OBJECT (folder));
2114 get_msg_status_cb (GObject *obj,
2118 GetMsgInfo *helper = NULL;
2120 g_return_if_fail (status != NULL);
2121 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2123 helper = (GetMsgInfo *) user_data;
2124 g_return_if_fail (helper != NULL);
2126 /* Notify progress */
2127 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2128 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2132 get_msg_async_cb (TnyFolder *folder,
2138 GetMsgInfo *info = NULL;
2139 ModestMailOperationPrivate *priv = NULL;
2142 info = (GetMsgInfo *) user_data;
2144 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2147 if (info->more_msgs) {
2148 tny_iterator_next (info->more_msgs);
2149 finished = (tny_iterator_is_done (info->more_msgs));
2151 finished = (priv->done == priv->total) ? TRUE : FALSE;
2155 if (canceled || err) {
2156 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2158 priv->error = g_error_copy ((const GError *) err);
2159 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2162 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2163 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2166 } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
2167 /* Set the success status before calling the user callback */
2168 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2169 } else if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED) {
2175 /* Call the user callback */
2176 if (info->user_callback)
2177 info->user_callback (info->mail_op, info->header, canceled,
2178 msg, err, info->user_data);
2180 /* Notify about operation end if this is the last callback */
2182 /* Free user data */
2183 if (info->destroy_notify)
2184 info->destroy_notify (info->user_data);
2186 /* Notify about operation end */
2187 modest_mail_operation_notify_end (info->mail_op);
2190 if (info->more_msgs)
2191 g_object_unref (info->more_msgs);
2192 g_object_unref (info->header);
2193 g_object_unref (info->mail_op);
2194 g_slice_free (GetMsgInfo, info);
2195 } else if (info->more_msgs) {
2196 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->more_msgs));
2197 TnyFolder *folder = tny_header_get_folder (header);
2199 g_object_unref (info->header);
2200 info->header = g_object_ref (header);
2202 /* Retrieve the next message */
2203 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, info);
2205 g_object_unref (header);
2206 g_object_unref (folder);
2208 g_warning ("%s: finished != TRUE but no messages left", __FUNCTION__);
2213 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2214 TnyList *header_list,
2215 GetMsgAsyncUserCallback user_callback,
2217 GDestroyNotify notify)
2219 ModestMailOperationPrivate *priv = NULL;
2221 TnyIterator *iter = NULL;
2223 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2225 /* Init mail operation */
2226 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2227 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2228 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2230 priv->total = tny_list_get_length(header_list);
2232 /* Get account and set it into mail_operation */
2233 if (tny_list_get_length (header_list) >= 1) {
2234 TnyIterator *iterator = tny_list_create_iterator (header_list);
2235 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iterator));
2237 TnyFolder *folder = tny_header_get_folder (header);
2239 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2240 g_object_unref (folder);
2242 g_object_unref (header);
2244 g_object_unref (iterator);
2247 msg_list_size = compute_message_list_size (header_list);
2249 modest_mail_operation_notify_start (self);
2250 iter = tny_list_create_iterator (header_list);
2251 if (!tny_iterator_is_done (iter)) {
2252 /* notify about the start of the operation */
2253 ModestMailOperationState *state;
2254 state = modest_mail_operation_clone_state (self);
2257 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2260 GetMsgInfo *msg_info = NULL;
2261 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2262 TnyFolder *folder = tny_header_get_folder (header);
2264 /* Create the message info */
2265 msg_info = g_slice_new0 (GetMsgInfo);
2266 msg_info->mail_op = g_object_ref (self);
2267 msg_info->header = g_object_ref (header);
2268 msg_info->more_msgs = g_object_ref (iter);
2269 msg_info->user_callback = user_callback;
2270 msg_info->user_data = user_data;
2271 msg_info->destroy_notify = notify;
2272 msg_info->last_total_bytes = 0;
2273 msg_info->sum_total_bytes = 0;
2274 msg_info->total_bytes = msg_list_size;
2276 /* The callback will call it per each header */
2277 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2279 /* Free and go on */
2280 g_object_unref (header);
2281 g_object_unref (folder);
2282 g_slice_free (ModestMailOperationState, state);
2284 g_object_unref (iter);
2289 modest_mail_operation_remove_msg (ModestMailOperation *self,
2291 gboolean remove_to_trash /*ignored*/)
2294 ModestMailOperationPrivate *priv;
2296 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2297 g_return_if_fail (TNY_IS_HEADER (header));
2299 if (remove_to_trash)
2300 g_warning ("remove to trash is not implemented");
2302 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2303 folder = tny_header_get_folder (header);
2305 /* Get account and set it into mail_operation */
2306 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2307 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2308 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2310 /* remove message from folder */
2311 tny_folder_remove_msg (folder, header, &(priv->error));
2313 gboolean expunge, leave_on_server;
2314 const gchar *account_name;
2315 TnyAccount *account;
2316 ModestTransportStoreProtocol account_proto;
2318 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2319 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2321 modest_mail_operation_notify_start (self);
2323 /* Get leave on server setting */
2324 account = tny_folder_get_account (folder);
2325 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2327 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2330 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2332 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2333 modest_tny_folder_is_remote_folder (folder) == FALSE)
2339 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2342 g_object_unref (account);
2348 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2350 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2353 g_object_unref (G_OBJECT (folder));
2355 /* Notify about operation end */
2356 modest_mail_operation_notify_end (self);
2360 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2362 gboolean remove_to_trash /*ignored*/)
2364 TnyFolder *folder = NULL;
2365 ModestMailOperationPrivate *priv;
2366 TnyIterator *iter = NULL;
2367 TnyHeader *header = NULL;
2368 TnyList *remove_headers = NULL;
2369 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2371 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2372 g_return_if_fail (TNY_IS_LIST (headers));
2374 if (remove_to_trash)
2375 g_warning ("remove to trash is not implemented");
2377 if (tny_list_get_length(headers) == 0) {
2378 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2379 goto cleanup; /* nothing to do */
2382 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2383 remove_headers = g_object_ref(headers);
2385 /* Get folder from first header and sync it */
2386 iter = tny_list_create_iterator (headers);
2387 header = TNY_HEADER (tny_iterator_get_current (iter));
2389 folder = tny_header_get_folder (header);
2390 if (!TNY_IS_FOLDER(folder)) {
2391 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2395 /* Don't remove messages that are being sent */
2396 if (modest_tny_folder_is_local_folder (folder)) {
2397 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2399 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2400 TnyTransportAccount *traccount = NULL;
2401 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2402 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2404 ModestTnySendQueueStatus status;
2405 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2406 TnyIterator *iter = tny_list_create_iterator(headers);
2407 g_object_unref(remove_headers);
2408 remove_headers = TNY_LIST(tny_simple_list_new());
2409 while (!tny_iterator_is_done(iter)) {
2411 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2412 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2413 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2414 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2415 tny_list_append(remove_headers, G_OBJECT(hdr));
2417 g_object_unref(hdr);
2419 tny_iterator_next(iter);
2421 g_object_unref(iter);
2422 g_object_unref(traccount);
2426 /* Get account and set it into mail_operation */
2427 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2428 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2429 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2431 /* remove message from folder */
2432 modest_mail_operation_notify_start (self);
2434 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2436 gboolean expunge, leave_on_server;
2437 const gchar *account_name;
2439 TnyAccount *account;
2440 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2442 account = tny_folder_get_account (folder);
2443 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2445 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2448 proto = tny_account_get_proto (account);
2450 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2453 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2454 modest_tny_folder_is_remote_folder (folder) == FALSE)
2460 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2462 g_object_unref (account);
2468 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2470 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2475 g_object_unref (remove_headers);
2477 g_object_unref (header);
2479 g_object_unref (iter);
2481 g_object_unref (folder);
2483 /* Notify about operation end */
2484 modest_mail_operation_notify_end (self);
2488 notify_progress_of_multiple_messages (ModestMailOperation *self,
2490 gint *last_total_bytes,
2491 gint *sum_total_bytes,
2493 gboolean increment_done)
2495 ModestMailOperationPrivate *priv;
2496 ModestMailOperationState *state;
2497 gboolean is_num_bytes = FALSE;
2499 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2501 /* We know that tinymail sends us information about
2502 * transferred bytes with this particular message
2504 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2505 * I just added the 'if' so we don't get runtime warning)
2507 if (status->message)
2508 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2510 state = modest_mail_operation_clone_state (self);
2511 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2512 /* We know that we're in a different message when the
2513 total number of bytes to transfer is different. Of
2514 course it could fail if we're transferring messages
2515 of the same size, but this is a workarround */
2516 if (status->of_total != *last_total_bytes) {
2517 /* We need to increment the done when there is
2518 no information about each individual
2519 message, we need to do this in message
2520 transfers, and we don't do it for getting
2524 *sum_total_bytes += *last_total_bytes;
2525 *last_total_bytes = status->of_total;
2527 state->bytes_done += status->position + *sum_total_bytes;
2528 state->bytes_total = total_bytes;
2530 /* Notify the status change. Only notify about changes
2531 referred to bytes */
2532 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2536 g_slice_free (ModestMailOperationState, state);
2540 transfer_msgs_status_cb (GObject *obj,
2544 XFerMsgsAsyncHelper *helper;
2546 g_return_if_fail (status != NULL);
2547 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2549 helper = (XFerMsgsAsyncHelper *) user_data;
2550 g_return_if_fail (helper != NULL);
2552 /* Notify progress */
2553 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2554 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2559 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2561 XFerMsgsAsyncHelper *helper;
2562 ModestMailOperation *self;
2563 ModestMailOperationPrivate *priv;
2564 gboolean finished = TRUE;
2566 helper = (XFerMsgsAsyncHelper *) user_data;
2567 self = helper->mail_op;
2569 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2572 priv->error = g_error_copy (err);
2574 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2575 } else if (cancelled) {
2576 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2577 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2578 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2579 _("Error trying to refresh the contents of %s"),
2580 tny_folder_get_name (folder));
2581 } else if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
2582 if (helper->more_msgs) {
2583 /* We'll transfer the next message in the list */
2584 tny_iterator_next (helper->more_msgs);
2585 if (!tny_iterator_is_done (helper->more_msgs)) {
2586 GObject *next_header;
2587 g_object_unref (helper->headers);
2588 helper->headers = tny_simple_list_new ();
2589 next_header = tny_iterator_get_current (helper->more_msgs);
2590 tny_list_append (helper->headers, next_header);
2591 g_object_unref (next_header);
2598 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2604 /* Update folder counts */
2605 tny_folder_poke_status (folder);
2606 tny_folder_poke_status (helper->dest_folder);
2608 /* Notify about operation end */
2609 modest_mail_operation_notify_end (self);
2611 /* If user defined callback function was defined, call it */
2612 if (helper->user_callback) {
2613 /* This is not a GDK lock because we are a Tinymail callback and
2614 * Tinymail already acquires the Gdk lock */
2616 /* no gdk_threads_enter (), CHECKED */
2617 helper->user_callback (self, helper->user_data);
2618 /* no gdk_threads_leave (), CHECKED */
2622 if (helper->more_msgs)
2623 g_object_unref (helper->more_msgs);
2624 if (helper->headers)
2625 g_object_unref (helper->headers);
2626 if (helper->dest_folder)
2627 g_object_unref (helper->dest_folder);
2628 if (helper->mail_op)
2629 g_object_unref (helper->mail_op);
2630 g_slice_free (XFerMsgsAsyncHelper, helper);
2632 /* Transfer more messages */
2633 tny_folder_transfer_msgs_async (folder,
2635 helper->dest_folder,
2638 transfer_msgs_status_cb,
2644 compute_message_list_size (TnyList *headers)
2649 iter = tny_list_create_iterator (headers);
2650 while (!tny_iterator_is_done (iter)) {
2651 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2652 size += tny_header_get_message_size (header);
2653 g_object_unref (header);
2654 tny_iterator_next (iter);
2656 g_object_unref (iter);
2662 compute_message_array_size (GPtrArray *headers)
2667 for (i = 0; i < headers->len; i++) {
2668 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2669 size += tny_header_get_message_size (header);
2677 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2680 gboolean delete_original,
2681 XferMsgsAsyncUserCallback user_callback,
2684 ModestMailOperationPrivate *priv = NULL;
2685 TnyIterator *iter = NULL;
2686 TnyFolder *src_folder = NULL;
2687 XFerMsgsAsyncHelper *helper = NULL;
2688 TnyHeader *header = NULL;
2689 ModestTnyFolderRules rules = 0;
2690 TnyAccount *dst_account = NULL;
2691 gboolean leave_on_server;
2693 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2694 g_return_if_fail (headers && TNY_IS_LIST (headers));
2695 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2697 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2698 priv->total = tny_list_get_length (headers);
2700 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2701 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2703 /* Apply folder rules */
2704 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2705 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2706 /* Set status failed and set an error */
2707 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2708 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2709 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2710 _CS("ckct_ib_unable_to_paste_here"));
2711 /* Notify the queue */
2712 modest_mail_operation_notify_end (self);
2716 /* Get source folder */
2717 iter = tny_list_create_iterator (headers);
2718 header = TNY_HEADER (tny_iterator_get_current (iter));
2720 src_folder = tny_header_get_folder (header);
2721 g_object_unref (header);
2723 g_object_unref (iter);
2725 if (src_folder == NULL) {
2726 /* Notify the queue */
2727 modest_mail_operation_notify_end (self);
2729 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2734 /* Check folder source and destination */
2735 if (src_folder == folder) {
2736 /* Set status failed and set an error */
2737 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2738 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2739 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2740 _("mail_in_ui_folder_copy_target_error"));
2742 /* Notify the queue */
2743 modest_mail_operation_notify_end (self);
2746 g_object_unref (src_folder);
2750 /* Create the helper */
2751 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2752 helper->mail_op = g_object_ref(self);
2753 helper->dest_folder = g_object_ref(folder);
2754 helper->user_callback = user_callback;
2755 helper->user_data = user_data;
2756 helper->delete = delete_original;
2757 helper->last_total_bytes = 0;
2758 helper->sum_total_bytes = 0;
2759 helper->total_bytes = compute_message_list_size (headers);
2761 /* Get account and set it into mail_operation */
2762 priv->account = modest_tny_folder_get_account (src_folder);
2763 dst_account = modest_tny_folder_get_account (folder);
2765 if (priv->account == dst_account) {
2766 /* Transfer all messages at once using the fast
2767 * method. Note that depending on the server this
2768 * might not be that fast, and might not be
2769 * user-cancellable either */
2770 helper->headers = g_object_ref (headers);
2771 helper->more_msgs = NULL;
2773 /* Transfer messages one by one so the user can cancel
2776 helper->headers = tny_simple_list_new ();
2777 helper->more_msgs = tny_list_create_iterator (headers);
2778 hdr = tny_iterator_get_current (helper->more_msgs);
2779 tny_list_append (helper->headers, hdr);
2780 g_object_unref (hdr);
2783 /* If leave_on_server is set to TRUE then don't use
2784 delete_original, we always pass FALSE. This is because
2785 otherwise tinymail will try to sync the source folder and
2786 this could cause an error if we're offline while
2787 transferring an already downloaded message from a POP
2789 if (modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (priv->account)) ==
2790 MODEST_PROTOCOL_STORE_POP) {
2791 const gchar *account_name;
2793 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (priv->account);
2794 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2797 leave_on_server = FALSE;
2800 modest_mail_operation_notify_start (self);
2801 tny_folder_transfer_msgs_async (src_folder,
2804 (leave_on_server) ? FALSE : delete_original,
2806 transfer_msgs_status_cb,
2808 g_object_unref (src_folder);
2809 g_object_unref (dst_account);
2814 on_refresh_folder (TnyFolder *folder,
2819 RefreshAsyncHelper *helper = NULL;
2820 ModestMailOperation *self = NULL;
2821 ModestMailOperationPrivate *priv = NULL;
2823 helper = (RefreshAsyncHelper *) user_data;
2824 self = helper->mail_op;
2825 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2827 g_return_if_fail(priv!=NULL);
2830 priv->error = g_error_copy (error);
2831 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2836 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2837 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2838 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2839 _("Error trying to refresh the contents of %s"),
2840 tny_folder_get_name (folder));
2844 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2847 /* Call user defined callback, if it exists */
2848 if (helper->user_callback) {
2850 /* This is not a GDK lock because we are a Tinymail callback and
2851 * Tinymail already acquires the Gdk lock */
2852 helper->user_callback (self, folder, helper->user_data);
2856 g_slice_free (RefreshAsyncHelper, helper);
2858 /* Notify about operation end */
2859 modest_mail_operation_notify_end (self);
2860 g_object_unref(self);
2864 on_refresh_folder_status_update (GObject *obj,
2868 RefreshAsyncHelper *helper = NULL;
2869 ModestMailOperation *self = NULL;
2870 ModestMailOperationPrivate *priv = NULL;
2871 ModestMailOperationState *state;
2873 g_return_if_fail (user_data != NULL);
2874 g_return_if_fail (status != NULL);
2875 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2877 helper = (RefreshAsyncHelper *) user_data;
2878 self = helper->mail_op;
2879 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2881 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2883 priv->done = status->position;
2884 priv->total = status->of_total;
2886 state = modest_mail_operation_clone_state (self);
2888 /* This is not a GDK lock because we are a Tinymail callback and
2889 * Tinymail already acquires the Gdk lock */
2890 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2892 g_slice_free (ModestMailOperationState, state);
2896 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2898 RefreshAsyncUserCallback user_callback,
2901 ModestMailOperationPrivate *priv = NULL;
2902 RefreshAsyncHelper *helper = NULL;
2904 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2906 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2908 /* Get account and set it into mail_operation */
2909 priv->account = modest_tny_folder_get_account (folder);
2910 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2912 /* Create the helper */
2913 helper = g_slice_new0 (RefreshAsyncHelper);
2914 helper->mail_op = g_object_ref(self);
2915 helper->user_callback = user_callback;
2916 helper->user_data = user_data;
2918 /* Refresh the folder. TODO: tinymail could issue a status
2919 updates before the callback call then this could happen. We
2920 must review the design */
2921 modest_mail_operation_notify_start (self);
2923 /* notify that the operation was started */
2924 ModestMailOperationState *state;
2925 state = modest_mail_operation_clone_state (self);
2928 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2931 /* FIXME: we're leaking the state here, or? valgrind thinks so */
2933 tny_folder_refresh_async (folder,
2935 on_refresh_folder_status_update,
2940 run_queue_stop (ModestTnySendQueue *queue,
2941 ModestMailOperation *self)
2943 ModestMailOperationPrivate *priv;
2945 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2946 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2947 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2949 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2951 modest_mail_operation_notify_end (self);
2952 g_signal_handlers_disconnect_by_func (queue, run_queue_stop, self);
2953 g_object_unref (self);
2956 modest_mail_operation_run_queue (ModestMailOperation *self,
2957 ModestTnySendQueue *queue)
2959 ModestMailOperationPrivate *priv;
2961 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2962 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2963 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2965 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2966 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
2967 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
2969 modest_mail_operation_notify_start (self);
2970 g_object_ref (self);
2971 g_signal_connect ((gpointer) queue, "queue-stop", G_CALLBACK (run_queue_stop), (gpointer) self);
2975 sync_folder_finish_callback (TnyFolder *self, gboolean cancelled, GError *err, ModestMailOperation *mail_op)
2977 ModestMailOperationPrivate *priv;
2979 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
2981 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2982 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2984 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2986 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2988 modest_mail_operation_notify_end (mail_op);
2989 g_object_unref (mail_op);
2993 modest_mail_operation_sync_folder (ModestMailOperation *self,
2994 TnyFolder *folder, gboolean expunge)
2996 ModestMailOperationPrivate *priv;
2998 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2999 g_return_if_fail (TNY_IS_FOLDER (folder));
3000 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3002 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3003 priv->account = TNY_ACCOUNT (tny_folder_get_account (folder));
3004 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
3006 modest_mail_operation_notify_start (self);
3007 g_object_ref (self);
3008 tny_folder_sync_async (folder, expunge, (TnyFolderCallback) sync_folder_finish_callback, NULL, self);
3012 modest_mail_operation_notify_start (ModestMailOperation *self)
3014 ModestMailOperationPrivate *priv = NULL;
3016 g_return_if_fail (self);
3018 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3020 /* Ensure that all the fields are filled correctly */
3021 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
3023 /* Notify the observers about the mail operation. We do not
3024 wrapp this emission because we assume that this function is
3025 always called from within the main lock */
3026 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
3031 * It's used by the mail operation queue to notify the observers
3032 * attached to that signal that the operation finished. We need to use
3033 * that because tinymail does not give us the progress of a given
3034 * operation when it finishes (it directly calls the operation
3038 modest_mail_operation_notify_end (ModestMailOperation *self)
3040 ModestMailOperationPrivate *priv = NULL;
3042 g_return_if_fail (self);
3044 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3046 /* Notify the observers about the mail operation end. We do
3047 not wrapp this emission because we assume that this
3048 function is always called from within the main lock */
3049 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3051 /* Remove the error user data */
3052 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3053 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3057 modest_mail_operation_get_account (ModestMailOperation *self)
3059 ModestMailOperationPrivate *priv = NULL;
3061 g_return_val_if_fail (self, NULL);
3063 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3065 return (priv->account) ? g_object_ref (priv->account) : NULL;
3069 modest_mail_operation_noop (ModestMailOperation *self)
3071 ModestMailOperationPrivate *priv = NULL;
3073 g_return_if_fail (self);
3075 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3076 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3077 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3081 /* This mail operation does nothing actually */
3082 modest_mail_operation_notify_start (self);
3083 modest_mail_operation_notify_end (self);
3088 modest_mail_operation_to_string (ModestMailOperation *self)
3090 const gchar *type, *status, *account_id;
3091 ModestMailOperationPrivate *priv = NULL;
3093 g_return_val_if_fail (self, NULL);
3095 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3097 /* new operations don't have anything interesting */
3098 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3099 return g_strdup_printf ("%p <new operation>", self);
3101 switch (priv->op_type) {
3102 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3103 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3104 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3105 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3106 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3107 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3108 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3109 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3110 default: type = "UNEXPECTED"; break;
3113 switch (priv->status) {
3114 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3115 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3116 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3117 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3118 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3119 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3120 default: status= "UNEXPECTED"; break;
3123 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3125 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3126 priv->done, priv->total,
3127 priv->error && priv->error->message ? priv->error->message : "");