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, succeeded;
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));
1267 if (!canceled && !err)
1268 modest_account_mgr_set_server_account_username_has_succeeded (mgr, tny_account_get_id (priv->account), TRUE);
1270 if (new_headers_array->len == 0)
1273 /* Get per-account message amount retrieval limit */
1274 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1275 if (retrieve_limit == 0)
1276 retrieve_limit = G_MAXINT;
1278 /* Get per-account retrieval type */
1279 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1280 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1283 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1285 /* Ask the users if they want to retrieve all the messages
1286 even though the limit was exceeded */
1287 ignore_limit = FALSE;
1288 if (new_headers_array->len > retrieve_limit) {
1289 /* Ask the user if a callback has been specified and
1290 if the mail operation has a source (this means that
1291 was invoked by the user and not automatically by a
1293 if (info->retrieve_all_cb && priv->source)
1294 ignore_limit = info->retrieve_all_cb (priv->source,
1295 new_headers_array->len,
1299 if (!headers_only) {
1301 const gint msg_list_size = compute_message_array_size (new_headers_array);
1305 priv->total = new_headers_array->len;
1307 priv->total = MIN (new_headers_array->len, retrieve_limit);
1308 while (msg_num < priv->total) {
1309 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num));
1310 TnyFolder *folder = tny_header_get_folder (header);
1311 GetMsgInfo *msg_info;
1313 /* Create the message info */
1314 msg_info = g_slice_new0 (GetMsgInfo);
1315 msg_info->mail_op = g_object_ref (info->mail_op);
1316 msg_info->header = g_object_ref (header);
1317 msg_info->total_bytes = msg_list_size;
1319 /* Get message in an async way */
1320 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1321 get_msg_status_cb, msg_info);
1323 g_object_unref (folder);
1329 /* Copy the headers to a list and free the array */
1330 new_headers = tny_simple_list_new ();
1331 for (i=0; i < new_headers_array->len; i++) {
1332 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1333 tny_list_append (new_headers, G_OBJECT (header));
1335 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1336 g_ptr_array_free (new_headers_array, FALSE);
1342 modest_account_mgr_set_server_account_username_has_succeeded (modest_runtime_get_account_mgr (),
1343 tny_account_get_name (priv->account),
1346 /* Get the transport account */
1347 transport_account = (TnyTransportAccount *)
1348 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
1349 info->account_name);
1351 if (transport_account) {
1352 ModestTnySendQueue *send_queue;
1356 send_queue = modest_runtime_get_send_queue (transport_account);
1357 g_object_unref (transport_account);
1359 /* Get outbox folder */
1360 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1361 if (outbox) { /* this could fail in some cases */
1362 num_messages = tny_folder_get_all_count (outbox);
1363 g_object_unref (outbox);
1365 g_warning ("%s: could not get outbox", __FUNCTION__);
1369 if (num_messages != 0) {
1371 g_object_unref (priv->account);
1373 /* Reenable suspended items */
1374 modest_tny_send_queue_wakeup (MODEST_TNY_SEND_QUEUE (send_queue));
1377 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (send_queue));
1381 /* Check if the operation was a success */
1383 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1385 /* Set the account back to not busy */
1386 modest_account_mgr_set_account_busy (mgr, info->account_name, FALSE);
1388 /* Call the user callback */
1390 info->callback (info->mail_op, new_headers, info->user_data);
1392 /* Notify about operation end */
1393 modest_mail_operation_notify_end (info->mail_op);
1397 g_object_unref (new_headers);
1398 destroy_update_account_info (info);
1402 recurse_folders_async_cb (TnyFolderStore *folder_store,
1408 UpdateAccountInfo *info;
1409 ModestMailOperationPrivate *priv;
1411 info = (UpdateAccountInfo *) user_data;
1412 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1414 if (err || canceled) {
1415 /* Try to continue anyway */
1416 } else if (info->poke_all) {
1417 /* We're not getting INBOX children if we don't want to poke all */
1418 TnyIterator *iter = tny_list_create_iterator (list);
1419 while (!tny_iterator_is_done (iter)) {
1420 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1421 TnyList *folders = tny_simple_list_new ();
1423 /* Add to the list of all folders */
1424 tny_list_append (info->folders, (GObject *) folder);
1426 /* Add pending call */
1427 info->pending_calls++;
1429 tny_folder_store_get_folders_async (folder, folders, NULL,
1430 recurse_folders_async_cb,
1433 g_object_unref (G_OBJECT (folder));
1435 tny_iterator_next (iter);
1437 g_object_unref (G_OBJECT (iter));
1438 g_object_unref (G_OBJECT (list));
1441 /* Remove my own pending call */
1442 info->pending_calls--;
1444 /* This means that we have all the folders */
1445 if (info->pending_calls == 0) {
1446 TnyIterator *iter_all_folders;
1447 TnyFolder *inbox = NULL;
1449 iter_all_folders = tny_list_create_iterator (info->folders);
1451 /* Do a poke status over all folders */
1452 while (!tny_iterator_is_done (iter_all_folders) &&
1453 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1454 TnyFolder *folder = NULL;
1456 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1458 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1459 /* Get a reference to the INBOX */
1460 inbox = g_object_ref (folder);
1462 /* Issue a poke status over the folder */
1464 tny_folder_poke_status (folder);
1467 /* Free and go to next */
1468 g_object_unref (folder);
1469 tny_iterator_next (iter_all_folders);
1471 g_object_unref (iter_all_folders);
1473 /* Refresh the INBOX */
1475 /* Refresh the folder. Our observer receives
1476 * the new emails during folder refreshes, so
1477 * we can use observer->new_headers
1479 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1480 tny_folder_add_observer (inbox, info->inbox_observer);
1482 /* Refresh the INBOX */
1483 tny_folder_refresh_async (inbox, inbox_refreshed_cb, NULL, info);
1484 g_object_unref (inbox);
1486 /* We could not perform the inbox refresh but
1487 we'll try to send mails anyway */
1488 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1494 modest_mail_operation_update_account (ModestMailOperation *self,
1495 const gchar *account_name,
1497 RetrieveAllCallback retrieve_all_cb,
1498 UpdateAccountCallback callback,
1501 UpdateAccountInfo *info = NULL;
1502 ModestMailOperationPrivate *priv = NULL;
1503 ModestTnyAccountStore *account_store = NULL;
1505 ModestMailOperationState *state;
1507 /* Init mail operation */
1508 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1511 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1512 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1514 /* Get the store account */
1515 account_store = modest_runtime_get_account_store ();
1517 modest_tny_account_store_get_server_account (account_store,
1519 TNY_ACCOUNT_TYPE_STORE);
1521 /* The above function could return NULL */
1522 if (!priv->account) {
1523 /* Check if the operation was a success */
1524 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1525 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1527 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1529 /* Call the user callback */
1531 callback (self, NULL, user_data);
1533 /* Notify about operation end */
1534 modest_mail_operation_notify_end (self);
1539 /* Create the helper object */
1540 info = g_slice_new0 (UpdateAccountInfo);
1541 info->pending_calls = 1;
1542 info->folders = tny_simple_list_new ();
1543 info->mail_op = g_object_ref (self);
1544 info->poke_all = poke_all;
1545 info->account_name = g_strdup (account_name);
1546 info->callback = callback;
1547 info->user_data = user_data;
1548 info->retrieve_all_cb = retrieve_all_cb;
1550 /* Set account busy */
1551 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
1552 modest_mail_operation_notify_start (self);
1554 /* notify about the start of the operation */
1555 state = modest_mail_operation_clone_state (self);
1559 /* Start notifying progress */
1560 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1561 g_slice_free (ModestMailOperationState, state);
1563 /* Get all folders and continue in the callback */
1564 folders = tny_simple_list_new ();
1565 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (priv->account),
1567 recurse_folders_async_cb,
1572 * Used to notify the queue from the main
1573 * loop. We call it inside an idle call to achieve that
1576 idle_notify_queue (gpointer data)
1578 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1580 gdk_threads_enter ();
1581 modest_mail_operation_notify_end (mail_op);
1582 gdk_threads_leave ();
1583 g_object_unref (mail_op);
1589 compare_headers_by_date (gconstpointer a,
1592 TnyHeader **header1, **header2;
1593 time_t sent1, sent2;
1595 header1 = (TnyHeader **) a;
1596 header2 = (TnyHeader **) b;
1598 sent1 = tny_header_get_date_sent (*header1);
1599 sent2 = tny_header_get_date_sent (*header2);
1601 /* We want the most recent ones (greater time_t) at the
1610 /* ******************************************************************* */
1611 /* ************************** STORE ACTIONS ************************* */
1612 /* ******************************************************************* */
1615 ModestMailOperation *mail_op;
1616 CreateFolderUserCallback callback;
1622 create_folder_cb (TnyFolderStore *parent_folder,
1624 TnyFolder *new_folder,
1628 ModestMailOperationPrivate *priv;
1629 CreateFolderInfo *info;
1631 info = (CreateFolderInfo *) user_data;
1632 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1634 if (canceled || err) {
1635 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1637 priv->error = g_error_copy (err);
1639 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1640 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1643 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1646 /* The user will unref the new_folder */
1648 info->callback (info->mail_op, parent_folder,
1649 new_folder, info->user_data);
1651 /* Notify about operation end */
1652 modest_mail_operation_notify_end (info->mail_op);
1655 g_object_unref (info->mail_op);
1656 g_slice_free (CreateFolderInfo, info);
1660 modest_mail_operation_create_folder (ModestMailOperation *self,
1661 TnyFolderStore *parent,
1663 CreateFolderUserCallback callback,
1666 ModestMailOperationPrivate *priv;
1668 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1669 g_return_if_fail (name);
1671 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1672 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1673 priv->account = (TNY_IS_ACCOUNT (parent)) ?
1674 g_object_ref (parent) :
1675 modest_tny_folder_get_account (TNY_FOLDER (parent));
1677 /* Check for already existing folder */
1678 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
1679 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1680 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1681 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1682 _CS("ckdg_ib_folder_already_exists"));
1686 if (TNY_IS_FOLDER (parent)) {
1687 /* Check folder rules */
1688 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1689 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
1690 /* Set status failed and set an error */
1691 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1692 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1693 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1694 _("mail_in_ui_folder_create_error"));
1698 if (!strcmp (name, " ") || strchr (name, '/')) {
1699 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1700 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1701 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1702 _("mail_in_ui_folder_create_error"));
1706 CreateFolderInfo *info;
1708 info = g_slice_new0 (CreateFolderInfo);
1709 info->mail_op = g_object_ref (self);
1710 info->callback = callback;
1711 info->user_data = user_data;
1713 modest_mail_operation_notify_start (self);
1715 /* Create the folder */
1716 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
1719 /* Call the user callback anyway */
1721 callback (self, parent, NULL, user_data);
1722 /* Notify about operation end */
1723 modest_mail_operation_notify_end (self);
1728 modest_mail_operation_remove_folder (ModestMailOperation *self,
1730 gboolean remove_to_trash)
1732 ModestMailOperationPrivate *priv;
1733 ModestTnyFolderRules rules;
1735 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1736 g_return_if_fail (TNY_IS_FOLDER (folder));
1738 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1740 /* Check folder rules */
1741 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1742 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
1743 /* Set status failed and set an error */
1744 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1745 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1746 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
1747 _("mail_in_ui_folder_delete_error"));
1751 /* Get the account */
1752 priv->account = modest_tny_folder_get_account (folder);
1753 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
1755 /* Delete folder or move to trash */
1756 if (remove_to_trash) {
1757 TnyFolder *trash_folder = NULL;
1758 trash_folder = modest_tny_account_get_special_folder (priv->account,
1759 TNY_FOLDER_TYPE_TRASH);
1760 /* TODO: error_handling */
1762 modest_mail_operation_notify_start (self);
1763 modest_mail_operation_xfer_folder (self, folder,
1764 TNY_FOLDER_STORE (trash_folder),
1766 g_object_unref (trash_folder);
1768 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
1771 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
1773 modest_mail_operation_notify_start (self);
1774 tny_folder_store_remove_folder (parent, folder, &(priv->error));
1775 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
1778 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1780 g_object_unref (parent);
1782 g_warning ("%s: could not get parent folder", __FUNCTION__);
1786 /* Notify about operation end */
1787 modest_mail_operation_notify_end (self);
1791 transfer_folder_status_cb (GObject *obj,
1795 ModestMailOperation *self;
1796 ModestMailOperationPrivate *priv;
1797 ModestMailOperationState *state;
1798 XFerFolderAsyncHelper *helper;
1800 g_return_if_fail (status != NULL);
1801 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
1803 helper = (XFerFolderAsyncHelper *) user_data;
1804 g_return_if_fail (helper != NULL);
1806 self = helper->mail_op;
1807 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1809 priv->done = status->position;
1810 priv->total = status->of_total;
1812 state = modest_mail_operation_clone_state (self);
1814 /* This is not a GDK lock because we are a Tinymail callback
1815 * which is already GDK locked by Tinymail */
1817 /* no gdk_threads_enter (), CHECKED */
1819 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1821 /* no gdk_threads_leave (), CHECKED */
1823 g_slice_free (ModestMailOperationState, state);
1828 transfer_folder_cb (TnyFolder *folder,
1830 TnyFolderStore *into,
1831 TnyFolder *new_folder,
1835 XFerFolderAsyncHelper *helper;
1836 ModestMailOperation *self = NULL;
1837 ModestMailOperationPrivate *priv = NULL;
1839 helper = (XFerFolderAsyncHelper *) user_data;
1840 g_return_if_fail (helper != NULL);
1842 self = helper->mail_op;
1843 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1846 priv->error = g_error_copy (err);
1848 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1849 } else if (cancelled) {
1850 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1851 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1852 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1853 _("Transference of %s was cancelled."),
1854 tny_folder_get_name (folder));
1857 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1860 /* Notify about operation end */
1861 modest_mail_operation_notify_end (self);
1863 /* If user defined callback function was defined, call it */
1864 if (helper->user_callback) {
1866 /* This is not a GDK lock because we are a Tinymail callback
1867 * which is already GDK locked by Tinymail */
1869 /* no gdk_threads_enter (), CHECKED */
1870 helper->user_callback (self, new_folder, helper->user_data);
1871 /* no gdk_threads_leave () , CHECKED */
1875 g_object_unref (helper->mail_op);
1876 g_slice_free (XFerFolderAsyncHelper, helper);
1881 * This function checks if the new name is a valid name for our local
1882 * folders account. The new name could not be the same than then name
1883 * of any of the mandatory local folders
1885 * We can not rely on tinymail because tinymail does not check the
1886 * name of the virtual folders that the account could have in the case
1887 * that we're doing a rename (because it directly calls Camel which
1888 * knows nothing about our virtual folders).
1890 * In the case of an actual copy/move (i.e. move/copy a folder between
1891 * accounts) tinymail uses the tny_folder_store_create_account which
1892 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
1893 * checks the new name of the folder, so this call in that case
1894 * wouldn't be needed. *But* NOTE that if tinymail changes its
1895 * implementation (if folder transfers within the same account is no
1896 * longer implemented as a rename) this call will allow Modest to work
1899 * If the new name is not valid, this function will set the status to
1900 * failed and will set also an error in the mail operation
1903 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
1904 TnyFolderStore *into,
1905 const gchar *new_name)
1907 if (TNY_IS_ACCOUNT (into) &&
1908 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
1909 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
1911 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1912 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1913 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
1914 _CS("ckdg_ib_folder_already_exists"));
1921 modest_mail_operation_xfer_folder (ModestMailOperation *self,
1923 TnyFolderStore *parent,
1924 gboolean delete_original,
1925 XferFolderAsyncUserCallback user_callback,
1928 ModestMailOperationPrivate *priv = NULL;
1929 ModestTnyFolderRules parent_rules = 0, rules;
1930 XFerFolderAsyncHelper *helper = NULL;
1931 const gchar *folder_name = NULL;
1932 const gchar *error_msg;
1934 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1935 g_return_if_fail (TNY_IS_FOLDER (folder));
1936 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
1938 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1939 folder_name = tny_folder_get_name (folder);
1941 /* Set the error msg */
1942 error_msg = _("mail_in_ui_folder_move_target_error");
1944 /* Get account and set it into mail_operation */
1945 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1946 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
1947 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1949 /* Get folder rules */
1950 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
1951 if (TNY_IS_FOLDER (parent))
1952 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
1954 /* Apply operation constraints */
1955 if ((gpointer) parent == (gpointer) folder ||
1956 (!TNY_IS_FOLDER_STORE (parent)) ||
1957 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
1960 } else if (TNY_IS_FOLDER (parent) &&
1961 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
1965 } else if (TNY_IS_FOLDER (parent) &&
1966 TNY_IS_FOLDER_STORE (folder) &&
1967 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
1968 TNY_FOLDER_STORE (folder))) {
1969 /* Do not move a parent into a child */
1971 } else if (TNY_IS_FOLDER_STORE (parent) &&
1972 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
1973 /* Check that the new folder name is not used by any
1976 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
1977 /* Check that the new folder name is not used by any
1978 special local folder */
1981 /* Create the helper */
1982 helper = g_slice_new0 (XFerFolderAsyncHelper);
1983 helper->mail_op = g_object_ref (self);
1984 helper->user_callback = user_callback;
1985 helper->user_data = user_data;
1987 /* Move/Copy folder */
1988 modest_mail_operation_notify_start (self);
1989 tny_folder_copy_async (folder,
1991 tny_folder_get_name (folder),
1994 transfer_folder_status_cb,
2000 /* Set status failed and set an error */
2001 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2002 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2003 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2006 /* Call the user callback if exists */
2008 user_callback (self, NULL, user_data);
2010 /* Notify the queue */
2011 modest_mail_operation_notify_end (self);
2015 modest_mail_operation_rename_folder (ModestMailOperation *self,
2018 XferFolderAsyncUserCallback user_callback,
2021 ModestMailOperationPrivate *priv;
2022 ModestTnyFolderRules rules;
2023 XFerFolderAsyncHelper *helper;
2025 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2026 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2027 g_return_if_fail (name);
2029 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2031 /* Get account and set it into mail_operation */
2032 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2033 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2035 /* Check folder rules */
2036 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2037 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2039 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2042 TnyFolderStore *into;
2044 into = tny_folder_get_folder_store (folder);
2046 /* Check that the new folder name is not used by any
2047 special local folder */
2048 if (new_name_valid_if_local_account (priv, into, name)) {
2049 /* Create the helper */
2050 helper = g_slice_new0 (XFerFolderAsyncHelper);
2051 helper->mail_op = g_object_ref(self);
2052 helper->user_callback = user_callback;
2053 helper->user_data = user_data;
2055 /* Rename. Camel handles folder subscription/unsubscription */
2056 modest_mail_operation_notify_start (self);
2057 tny_folder_copy_async (folder, into, name, TRUE,
2059 transfer_folder_status_cb,
2064 g_object_unref (into);
2069 /* Set status failed and set an error */
2070 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2071 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2072 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2073 _("FIXME: unable to rename"));
2076 user_callback (self, NULL, user_data);
2078 /* Notify about operation end */
2079 modest_mail_operation_notify_end (self);
2082 /* ******************************************************************* */
2083 /* ************************** MSG ACTIONS ************************* */
2084 /* ******************************************************************* */
2087 modest_mail_operation_get_msg (ModestMailOperation *self,
2089 GetMsgAsyncUserCallback user_callback,
2092 GetMsgInfo *helper = NULL;
2094 ModestMailOperationPrivate *priv;
2096 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2097 g_return_if_fail (TNY_IS_HEADER (header));
2099 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2100 folder = tny_header_get_folder (header);
2102 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2106 /* Get account and set it into mail_operation */
2107 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2109 /* Check for cached messages */
2110 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2111 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2113 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2115 /* Create the helper */
2116 helper = g_slice_new0 (GetMsgInfo);
2117 helper->header = g_object_ref (header);
2118 helper->mail_op = g_object_ref (self);
2119 helper->user_callback = user_callback;
2120 helper->user_data = user_data;
2121 helper->destroy_notify = NULL;
2122 helper->last_total_bytes = 0;
2123 helper->sum_total_bytes = 0;
2124 helper->total_bytes = tny_header_get_message_size (header);
2126 modest_mail_operation_notify_start (self);
2128 /* notify about the start of the operation */
2129 ModestMailOperationState *state;
2130 state = modest_mail_operation_clone_state (self);
2133 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2136 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2138 g_object_unref (G_OBJECT (folder));
2142 get_msg_status_cb (GObject *obj,
2146 GetMsgInfo *helper = NULL;
2148 g_return_if_fail (status != NULL);
2149 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
2151 helper = (GetMsgInfo *) user_data;
2152 g_return_if_fail (helper != NULL);
2154 /* Notify progress */
2155 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2156 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2160 get_msg_async_cb (TnyFolder *folder,
2166 GetMsgInfo *info = NULL;
2167 ModestMailOperationPrivate *priv = NULL;
2170 info = (GetMsgInfo *) user_data;
2172 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2175 if (info->more_msgs) {
2176 tny_iterator_next (info->more_msgs);
2177 finished = (tny_iterator_is_done (info->more_msgs));
2179 finished = (priv->done == priv->total) ? TRUE : FALSE;
2182 /* If canceled by the user, ignore the error given by Tinymail */
2183 if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED) {
2186 } else if (canceled || err) {
2187 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2189 priv->error = g_error_copy ((const GError *) err);
2190 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2193 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2194 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2197 } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
2198 /* Set the success status before calling the user callback */
2199 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2203 /* Call the user callback */
2204 if (info->user_callback)
2205 info->user_callback (info->mail_op, info->header, canceled,
2206 msg, err, info->user_data);
2208 /* Notify about operation end if this is the last callback */
2210 /* Free user data */
2211 if (info->destroy_notify)
2212 info->destroy_notify (info->user_data);
2214 /* Notify about operation end */
2215 modest_mail_operation_notify_end (info->mail_op);
2218 if (info->more_msgs)
2219 g_object_unref (info->more_msgs);
2220 g_object_unref (info->header);
2221 g_object_unref (info->mail_op);
2222 g_slice_free (GetMsgInfo, info);
2223 } else if (info->more_msgs) {
2224 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->more_msgs));
2225 TnyFolder *folder = tny_header_get_folder (header);
2227 g_object_unref (info->header);
2228 info->header = g_object_ref (header);
2230 /* Retrieve the next message */
2231 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, info);
2233 g_object_unref (header);
2234 g_object_unref (folder);
2236 g_warning ("%s: finished != TRUE but no messages left", __FUNCTION__);
2241 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2242 TnyList *header_list,
2243 GetMsgAsyncUserCallback user_callback,
2245 GDestroyNotify notify)
2247 ModestMailOperationPrivate *priv = NULL;
2249 TnyIterator *iter = NULL;
2251 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2253 /* Init mail operation */
2254 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2255 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2256 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2258 priv->total = tny_list_get_length(header_list);
2260 /* Get account and set it into mail_operation */
2261 if (tny_list_get_length (header_list) >= 1) {
2262 TnyIterator *iterator = tny_list_create_iterator (header_list);
2263 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iterator));
2265 TnyFolder *folder = tny_header_get_folder (header);
2267 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2268 g_object_unref (folder);
2270 g_object_unref (header);
2272 g_object_unref (iterator);
2275 msg_list_size = compute_message_list_size (header_list);
2277 modest_mail_operation_notify_start (self);
2278 iter = tny_list_create_iterator (header_list);
2279 if (!tny_iterator_is_done (iter)) {
2280 /* notify about the start of the operation */
2281 ModestMailOperationState *state;
2282 state = modest_mail_operation_clone_state (self);
2285 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2288 GetMsgInfo *msg_info = NULL;
2289 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2290 TnyFolder *folder = tny_header_get_folder (header);
2292 /* Create the message info */
2293 msg_info = g_slice_new0 (GetMsgInfo);
2294 msg_info->mail_op = g_object_ref (self);
2295 msg_info->header = g_object_ref (header);
2296 msg_info->more_msgs = g_object_ref (iter);
2297 msg_info->user_callback = user_callback;
2298 msg_info->user_data = user_data;
2299 msg_info->destroy_notify = notify;
2300 msg_info->last_total_bytes = 0;
2301 msg_info->sum_total_bytes = 0;
2302 msg_info->total_bytes = msg_list_size;
2304 /* The callback will call it per each header */
2305 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2307 /* Free and go on */
2308 g_object_unref (header);
2309 g_object_unref (folder);
2310 g_slice_free (ModestMailOperationState, state);
2312 g_object_unref (iter);
2317 modest_mail_operation_remove_msg (ModestMailOperation *self,
2319 gboolean remove_to_trash /*ignored*/)
2322 ModestMailOperationPrivate *priv;
2324 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2325 g_return_if_fail (TNY_IS_HEADER (header));
2327 if (remove_to_trash)
2328 g_warning ("remove to trash is not implemented");
2330 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2331 folder = tny_header_get_folder (header);
2333 /* Get account and set it into mail_operation */
2334 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2335 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2336 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2338 /* remove message from folder */
2339 tny_folder_remove_msg (folder, header, &(priv->error));
2341 gboolean expunge, leave_on_server;
2342 const gchar *account_name;
2343 TnyAccount *account;
2344 ModestTransportStoreProtocol account_proto;
2346 tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
2347 tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
2349 modest_mail_operation_notify_start (self);
2351 /* Get leave on server setting */
2352 account = tny_folder_get_account (folder);
2353 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2355 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2358 account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
2360 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2361 modest_tny_folder_is_remote_folder (folder) == FALSE)
2367 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2370 g_object_unref (account);
2376 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2378 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2381 g_object_unref (G_OBJECT (folder));
2383 /* Notify about operation end */
2384 modest_mail_operation_notify_end (self);
2388 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2390 gboolean remove_to_trash /*ignored*/)
2392 TnyFolder *folder = NULL;
2393 ModestMailOperationPrivate *priv;
2394 TnyIterator *iter = NULL;
2395 TnyHeader *header = NULL;
2396 TnyList *remove_headers = NULL;
2397 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2399 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2400 g_return_if_fail (TNY_IS_LIST (headers));
2402 if (remove_to_trash)
2403 g_warning ("remove to trash is not implemented");
2405 if (tny_list_get_length(headers) == 0) {
2406 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2407 goto cleanup; /* nothing to do */
2410 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2411 remove_headers = g_object_ref(headers);
2413 /* Get folder from first header and sync it */
2414 iter = tny_list_create_iterator (headers);
2415 header = TNY_HEADER (tny_iterator_get_current (iter));
2417 folder = tny_header_get_folder (header);
2418 if (!TNY_IS_FOLDER(folder)) {
2419 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
2423 /* Don't remove messages that are being sent */
2424 if (modest_tny_folder_is_local_folder (folder)) {
2425 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
2427 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2428 TnyTransportAccount *traccount = NULL;
2429 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2430 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
2432 ModestTnySendQueueStatus status;
2433 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue(traccount);
2434 TnyIterator *iter = tny_list_create_iterator(headers);
2435 g_object_unref(remove_headers);
2436 remove_headers = TNY_LIST(tny_simple_list_new());
2437 while (!tny_iterator_is_done(iter)) {
2439 TnyHeader *hdr = TNY_HEADER(tny_iterator_get_current(iter));
2440 msg_id = modest_tny_send_queue_get_msg_id (hdr);
2441 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
2442 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
2443 tny_list_append(remove_headers, G_OBJECT(hdr));
2445 g_object_unref(hdr);
2447 tny_iterator_next(iter);
2449 g_object_unref(iter);
2450 g_object_unref(traccount);
2454 /* Get account and set it into mail_operation */
2455 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2456 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2457 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2459 /* remove message from folder */
2460 modest_mail_operation_notify_start (self);
2462 tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
2464 gboolean expunge, leave_on_server;
2465 const gchar *account_name;
2467 TnyAccount *account;
2468 ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
2470 account = tny_folder_get_account (folder);
2471 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2473 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2476 proto = tny_account_get_proto (account);
2478 account_proto = modest_protocol_info_get_transport_store_protocol (proto);
2481 if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
2482 modest_tny_folder_is_remote_folder (folder) == FALSE)
2488 tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
2490 g_object_unref (account);
2496 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2498 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2503 g_object_unref (remove_headers);
2505 g_object_unref (header);
2507 g_object_unref (iter);
2509 g_object_unref (folder);
2511 /* Notify about operation end */
2512 modest_mail_operation_notify_end (self);
2516 notify_progress_of_multiple_messages (ModestMailOperation *self,
2518 gint *last_total_bytes,
2519 gint *sum_total_bytes,
2521 gboolean increment_done)
2523 ModestMailOperationPrivate *priv;
2524 ModestMailOperationState *state;
2525 gboolean is_num_bytes = FALSE;
2527 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2529 /* We know that tinymail sends us information about
2530 * transferred bytes with this particular message
2532 * (FIXME: this is very ugly, and no I (djcb) didn't write this code,
2533 * I just added the 'if' so we don't get runtime warning)
2535 if (status->message)
2536 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
2538 state = modest_mail_operation_clone_state (self);
2539 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
2540 /* We know that we're in a different message when the
2541 total number of bytes to transfer is different. Of
2542 course it could fail if we're transferring messages
2543 of the same size, but this is a workarround */
2544 if (status->of_total != *last_total_bytes) {
2545 /* We need to increment the done when there is
2546 no information about each individual
2547 message, we need to do this in message
2548 transfers, and we don't do it for getting
2552 *sum_total_bytes += *last_total_bytes;
2553 *last_total_bytes = status->of_total;
2555 state->bytes_done += status->position + *sum_total_bytes;
2556 state->bytes_total = total_bytes;
2558 /* Notify the status change. Only notify about changes
2559 referred to bytes */
2560 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2564 g_slice_free (ModestMailOperationState, state);
2568 transfer_msgs_status_cb (GObject *obj,
2572 XFerMsgsAsyncHelper *helper;
2574 g_return_if_fail (status != NULL);
2575 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
2577 helper = (XFerMsgsAsyncHelper *) user_data;
2578 g_return_if_fail (helper != NULL);
2580 /* Notify progress */
2581 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2582 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
2587 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
2589 XFerMsgsAsyncHelper *helper;
2590 ModestMailOperation *self;
2591 ModestMailOperationPrivate *priv;
2592 gboolean finished = TRUE;
2594 helper = (XFerMsgsAsyncHelper *) user_data;
2595 self = helper->mail_op;
2597 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2600 priv->error = g_error_copy (err);
2602 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2603 } else if (cancelled) {
2604 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2605 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2606 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2607 _("Error trying to refresh the contents of %s"),
2608 tny_folder_get_name (folder));
2609 } else if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
2610 if (helper->more_msgs) {
2611 /* We'll transfer the next message in the list */
2612 tny_iterator_next (helper->more_msgs);
2613 if (!tny_iterator_is_done (helper->more_msgs)) {
2614 GObject *next_header;
2615 g_object_unref (helper->headers);
2616 helper->headers = tny_simple_list_new ();
2617 next_header = tny_iterator_get_current (helper->more_msgs);
2618 tny_list_append (helper->headers, next_header);
2619 g_object_unref (next_header);
2626 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2632 /* Update folder counts */
2633 tny_folder_poke_status (folder);
2634 tny_folder_poke_status (helper->dest_folder);
2636 /* Notify about operation end */
2637 modest_mail_operation_notify_end (self);
2639 /* If user defined callback function was defined, call it */
2640 if (helper->user_callback) {
2641 /* This is not a GDK lock because we are a Tinymail callback and
2642 * Tinymail already acquires the Gdk lock */
2644 /* no gdk_threads_enter (), CHECKED */
2645 helper->user_callback (self, helper->user_data);
2646 /* no gdk_threads_leave (), CHECKED */
2650 if (helper->more_msgs)
2651 g_object_unref (helper->more_msgs);
2652 if (helper->headers)
2653 g_object_unref (helper->headers);
2654 if (helper->dest_folder)
2655 g_object_unref (helper->dest_folder);
2656 if (helper->mail_op)
2657 g_object_unref (helper->mail_op);
2658 g_slice_free (XFerMsgsAsyncHelper, helper);
2660 /* Transfer more messages */
2661 tny_folder_transfer_msgs_async (folder,
2663 helper->dest_folder,
2666 transfer_msgs_status_cb,
2672 compute_message_list_size (TnyList *headers)
2677 iter = tny_list_create_iterator (headers);
2678 while (!tny_iterator_is_done (iter)) {
2679 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2680 size += tny_header_get_message_size (header);
2681 g_object_unref (header);
2682 tny_iterator_next (iter);
2684 g_object_unref (iter);
2690 compute_message_array_size (GPtrArray *headers)
2695 for (i = 0; i < headers->len; i++) {
2696 TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i));
2697 size += tny_header_get_message_size (header);
2705 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
2708 gboolean delete_original,
2709 XferMsgsAsyncUserCallback user_callback,
2712 ModestMailOperationPrivate *priv = NULL;
2713 TnyIterator *iter = NULL;
2714 TnyFolder *src_folder = NULL;
2715 XFerMsgsAsyncHelper *helper = NULL;
2716 TnyHeader *header = NULL;
2717 ModestTnyFolderRules rules = 0;
2718 TnyAccount *dst_account = NULL;
2719 gboolean leave_on_server;
2721 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
2722 g_return_if_fail (headers && TNY_IS_LIST (headers));
2723 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
2725 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2726 priv->total = tny_list_get_length (headers);
2728 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2729 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2731 /* Apply folder rules */
2732 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2733 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2734 /* Set status failed and set an error */
2735 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2736 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2737 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2738 _CS("ckct_ib_unable_to_paste_here"));
2739 /* Notify the queue */
2740 modest_mail_operation_notify_end (self);
2744 /* Get source folder */
2745 iter = tny_list_create_iterator (headers);
2746 header = TNY_HEADER (tny_iterator_get_current (iter));
2748 src_folder = tny_header_get_folder (header);
2749 g_object_unref (header);
2751 g_object_unref (iter);
2753 if (src_folder == NULL) {
2754 /* Notify the queue */
2755 modest_mail_operation_notify_end (self);
2757 g_warning ("%s: cannot find folder from header", __FUNCTION__);
2762 /* Check folder source and destination */
2763 if (src_folder == folder) {
2764 /* Set status failed and set an error */
2765 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2766 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2767 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
2768 _("mail_in_ui_folder_copy_target_error"));
2770 /* Notify the queue */
2771 modest_mail_operation_notify_end (self);
2774 g_object_unref (src_folder);
2778 /* Create the helper */
2779 helper = g_slice_new0 (XFerMsgsAsyncHelper);
2780 helper->mail_op = g_object_ref(self);
2781 helper->dest_folder = g_object_ref(folder);
2782 helper->user_callback = user_callback;
2783 helper->user_data = user_data;
2784 helper->delete = delete_original;
2785 helper->last_total_bytes = 0;
2786 helper->sum_total_bytes = 0;
2787 helper->total_bytes = compute_message_list_size (headers);
2789 /* Get account and set it into mail_operation */
2790 priv->account = modest_tny_folder_get_account (src_folder);
2791 dst_account = modest_tny_folder_get_account (folder);
2793 if (priv->account == dst_account) {
2794 /* Transfer all messages at once using the fast
2795 * method. Note that depending on the server this
2796 * might not be that fast, and might not be
2797 * user-cancellable either */
2798 helper->headers = g_object_ref (headers);
2799 helper->more_msgs = NULL;
2801 /* Transfer messages one by one so the user can cancel
2804 helper->headers = tny_simple_list_new ();
2805 helper->more_msgs = tny_list_create_iterator (headers);
2806 hdr = tny_iterator_get_current (helper->more_msgs);
2807 tny_list_append (helper->headers, hdr);
2808 g_object_unref (hdr);
2811 /* If leave_on_server is set to TRUE then don't use
2812 delete_original, we always pass FALSE. This is because
2813 otherwise tinymail will try to sync the source folder and
2814 this could cause an error if we're offline while
2815 transferring an already downloaded message from a POP
2817 if (modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (priv->account)) ==
2818 MODEST_PROTOCOL_STORE_POP) {
2819 const gchar *account_name;
2821 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (priv->account);
2822 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2825 leave_on_server = FALSE;
2828 modest_mail_operation_notify_start (self);
2829 tny_folder_transfer_msgs_async (src_folder,
2832 (leave_on_server) ? FALSE : delete_original,
2834 transfer_msgs_status_cb,
2836 g_object_unref (src_folder);
2837 g_object_unref (dst_account);
2842 on_refresh_folder (TnyFolder *folder,
2847 RefreshAsyncHelper *helper = NULL;
2848 ModestMailOperation *self = NULL;
2849 ModestMailOperationPrivate *priv = NULL;
2851 helper = (RefreshAsyncHelper *) user_data;
2852 self = helper->mail_op;
2853 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2855 g_return_if_fail(priv!=NULL);
2858 priv->error = g_error_copy (error);
2859 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2864 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2865 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2866 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2867 _("Error trying to refresh the contents of %s"),
2868 tny_folder_get_name (folder));
2872 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2875 /* Call user defined callback, if it exists */
2876 if (helper->user_callback) {
2878 /* This is not a GDK lock because we are a Tinymail callback and
2879 * Tinymail already acquires the Gdk lock */
2880 helper->user_callback (self, folder, helper->user_data);
2884 g_slice_free (RefreshAsyncHelper, helper);
2886 /* Notify about operation end */
2887 modest_mail_operation_notify_end (self);
2888 g_object_unref(self);
2892 on_refresh_folder_status_update (GObject *obj,
2896 RefreshAsyncHelper *helper = NULL;
2897 ModestMailOperation *self = NULL;
2898 ModestMailOperationPrivate *priv = NULL;
2899 ModestMailOperationState *state;
2901 g_return_if_fail (user_data != NULL);
2902 g_return_if_fail (status != NULL);
2903 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
2905 helper = (RefreshAsyncHelper *) user_data;
2906 self = helper->mail_op;
2907 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
2909 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2911 priv->done = status->position;
2912 priv->total = status->of_total;
2914 state = modest_mail_operation_clone_state (self);
2916 /* This is not a GDK lock because we are a Tinymail callback and
2917 * Tinymail already acquires the Gdk lock */
2918 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2920 g_slice_free (ModestMailOperationState, state);
2924 modest_mail_operation_refresh_folder (ModestMailOperation *self,
2926 RefreshAsyncUserCallback user_callback,
2929 ModestMailOperationPrivate *priv = NULL;
2930 RefreshAsyncHelper *helper = NULL;
2932 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2934 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2936 /* Get account and set it into mail_operation */
2937 priv->account = modest_tny_folder_get_account (folder);
2938 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2940 /* Create the helper */
2941 helper = g_slice_new0 (RefreshAsyncHelper);
2942 helper->mail_op = g_object_ref(self);
2943 helper->user_callback = user_callback;
2944 helper->user_data = user_data;
2946 modest_mail_operation_notify_start (self);
2948 /* notify that the operation was started */
2949 ModestMailOperationState *state;
2950 state = modest_mail_operation_clone_state (self);
2953 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2956 /* FIXME: we're leaking the state here, or? valgrind thinks so */
2958 tny_folder_refresh_async (folder,
2960 on_refresh_folder_status_update,
2965 run_queue_stop (ModestTnySendQueue *queue,
2966 ModestMailOperation *self)
2968 ModestMailOperationPrivate *priv;
2970 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2971 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2972 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2974 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2976 modest_mail_operation_notify_end (self);
2977 g_signal_handlers_disconnect_by_func (queue, run_queue_stop, self);
2978 g_object_unref (self);
2981 modest_mail_operation_run_queue (ModestMailOperation *self,
2982 ModestTnySendQueue *queue)
2984 ModestMailOperationPrivate *priv;
2986 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2987 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
2988 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2990 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2991 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
2992 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
2994 modest_mail_operation_notify_start (self);
2995 g_object_ref (self);
2996 g_signal_connect ((gpointer) queue, "queue-stop", G_CALLBACK (run_queue_stop), (gpointer) self);
3000 sync_folder_finish_callback (TnyFolder *self, gboolean cancelled, GError *err, ModestMailOperation *mail_op)
3002 ModestMailOperationPrivate *priv;
3004 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3006 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3007 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
3009 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3011 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3013 modest_mail_operation_notify_end (mail_op);
3014 g_object_unref (mail_op);
3018 modest_mail_operation_sync_folder (ModestMailOperation *self,
3019 TnyFolder *folder, gboolean expunge)
3021 ModestMailOperationPrivate *priv;
3023 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3024 g_return_if_fail (TNY_IS_FOLDER (folder));
3025 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3027 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3028 priv->account = TNY_ACCOUNT (tny_folder_get_account (folder));
3029 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
3031 modest_mail_operation_notify_start (self);
3032 g_object_ref (self);
3033 tny_folder_sync_async (folder, expunge, (TnyFolderCallback) sync_folder_finish_callback, NULL, self);
3037 modest_mail_operation_notify_start (ModestMailOperation *self)
3039 ModestMailOperationPrivate *priv = NULL;
3041 g_return_if_fail (self);
3043 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3045 /* Ensure that all the fields are filled correctly */
3046 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
3048 /* Notify the observers about the mail operation. We do not
3049 wrapp this emission because we assume that this function is
3050 always called from within the main lock */
3051 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
3056 * It's used by the mail operation queue to notify the observers
3057 * attached to that signal that the operation finished. We need to use
3058 * that because tinymail does not give us the progress of a given
3059 * operation when it finishes (it directly calls the operation
3063 modest_mail_operation_notify_end (ModestMailOperation *self)
3065 ModestMailOperationPrivate *priv = NULL;
3067 g_return_if_fail (self);
3069 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3071 /* Notify the observers about the mail operation end. We do
3072 not wrapp this emission because we assume that this
3073 function is always called from within the main lock */
3074 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3076 /* Remove the error user data */
3077 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3078 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3082 modest_mail_operation_get_account (ModestMailOperation *self)
3084 ModestMailOperationPrivate *priv = NULL;
3086 g_return_val_if_fail (self, NULL);
3088 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3090 return (priv->account) ? g_object_ref (priv->account) : NULL;
3094 modest_mail_operation_noop (ModestMailOperation *self)
3096 ModestMailOperationPrivate *priv = NULL;
3098 g_return_if_fail (self);
3100 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3101 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3102 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3106 /* This mail operation does nothing actually */
3107 modest_mail_operation_notify_start (self);
3108 modest_mail_operation_notify_end (self);
3113 modest_mail_operation_to_string (ModestMailOperation *self)
3115 const gchar *type, *status, *account_id;
3116 ModestMailOperationPrivate *priv = NULL;
3118 g_return_val_if_fail (self, NULL);
3120 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3122 /* new operations don't have anything interesting */
3123 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3124 return g_strdup_printf ("%p <new operation>", self);
3126 switch (priv->op_type) {
3127 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3128 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3129 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3130 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3131 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3132 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3133 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3134 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3135 default: type = "UNEXPECTED"; break;
3138 switch (priv->status) {
3139 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3140 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3141 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3142 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3143 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3144 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3145 default: status= "UNEXPECTED"; break;
3148 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3150 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3151 priv->done, priv->total,
3152 priv->error && priv->error->message ? priv->error->message : "");