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-error.h>
45 #include <tny-folder-observer.h>
46 #include <camel/camel-stream-mem.h>
47 #include <glib/gi18n.h>
48 #include <modest-defs.h>
49 #include "modest-platform.h"
50 #include "modest-account-mgr-helpers.h"
51 #include <modest-tny-account.h>
52 #include <modest-tny-send-queue.h>
53 #include <modest-runtime.h>
54 #include "modest-text-utils.h"
55 #include "modest-tny-msg.h"
56 #include "modest-tny-folder.h"
57 #include "modest-tny-account-store.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-marshal.h"
60 #include "modest-error.h"
61 #include "modest-mail-operation.h"
62 #include <modest-count-stream.h>
63 #include <libgnomevfs/gnome-vfs.h>
64 #include "modest-utils.h"
65 #include "modest-debug.h"
66 #ifdef MODEST_USE_LIBTIME
67 #include <clockd/libtime.h>
69 #include "modest-account-protocol.h"
74 * Remove all these #ifdef stuff when the tinymail's idle calls become
77 #define TINYMAIL_IDLES_NOT_LOCKED_YET 1
79 /* 'private'/'protected' functions */
80 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
81 static void modest_mail_operation_init (ModestMailOperation *obj);
82 static void modest_mail_operation_finalize (GObject *obj);
84 static void get_msg_async_cb (TnyFolder *folder,
90 static void get_msg_status_cb (GObject *obj,
94 static void modest_mail_operation_notify_start (ModestMailOperation *self);
95 static void modest_mail_operation_notify_end (ModestMailOperation *self);
97 static void notify_progress_of_multiple_messages (ModestMailOperation *self,
99 gint *last_total_bytes,
100 gint *sum_total_bytes,
102 gboolean increment_done);
104 static guint compute_message_list_size (TnyList *headers, guint num_elements);
106 static int compare_headers_by_date (gconstpointer a,
109 static void sync_folder_finish_callback (TnyFolder *self,
114 static gboolean _check_memory_low (ModestMailOperation *mail_op);
118 ModestTnySendQueue *queue;
119 ModestMailOperation *self;
125 static void run_queue_notify_and_destroy (RunQueueHelper *helper,
126 ModestMailOperationStatus status);
128 /* Helpers for the update account operation (send & receive)*/
131 ModestMailOperation *mail_op;
133 UpdateAccountCallback callback;
138 TnyFolderObserver *inbox_observer;
139 RetrieveAllCallback retrieve_all_cb;
140 gboolean interactive;
144 static void destroy_update_account_info (UpdateAccountInfo *info);
146 static void update_account_send_mail (UpdateAccountInfo *info);
148 static void update_account_get_msg_async_cb (TnyFolder *folder,
154 static void update_account_notify_user_and_free (UpdateAccountInfo *info,
155 TnyList *new_headers);
157 enum _ModestMailOperationSignals
159 PROGRESS_CHANGED_SIGNAL,
160 OPERATION_STARTED_SIGNAL,
161 OPERATION_FINISHED_SIGNAL,
165 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
166 struct _ModestMailOperationPrivate {
172 ErrorCheckingUserCallback error_checking;
173 gpointer error_checking_user_data;
174 ErrorCheckingUserDataDestroyer error_checking_user_data_destroyer;
175 ModestMailOperationStatus status;
176 ModestMailOperationTypeOperation op_type;
179 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
180 MODEST_TYPE_MAIL_OPERATION, \
181 ModestMailOperationPrivate))
183 #define CHECK_EXCEPTION(priv, new_status) if (priv->error) {\
184 priv->status = new_status;\
189 GetMsgAsyncUserCallback user_callback;
191 TnyIterator *more_msgs;
193 ModestMailOperation *mail_op;
194 GDestroyNotify destroy_notify;
195 gint last_total_bytes;
196 gint sum_total_bytes;
200 typedef struct _RefreshAsyncHelper {
201 ModestMailOperation *mail_op;
202 RefreshAsyncUserCallback user_callback;
204 } RefreshAsyncHelper;
206 typedef struct _XFerMsgsAsyncHelper
208 ModestMailOperation *mail_op;
210 TnyIterator *more_msgs;
211 TnyFolder *dest_folder;
212 XferMsgsAsyncUserCallback user_callback;
215 gint last_total_bytes;
216 gint sum_total_bytes;
218 } XFerMsgsAsyncHelper;
220 typedef struct _XFerFolderAsyncHelper
222 ModestMailOperation *mail_op;
223 XferFolderAsyncUserCallback user_callback;
225 } XFerFolderAsyncHelper;
227 typedef void (*ModestMailOperationCreateMsgCallback) (ModestMailOperation *mail_op,
231 static void modest_mail_operation_create_msg (ModestMailOperation *self,
232 const gchar *from, const gchar *to,
233 const gchar *cc, const gchar *bcc,
234 const gchar *subject, const gchar *plain_body,
235 const gchar *html_body, const GList *attachments_list,
236 const GList *images_list,
237 TnyHeaderFlags priority_flags,
238 const gchar *references, const gchar *in_reply_to,
239 ModestMailOperationCreateMsgCallback callback,
242 static gboolean idle_notify_queue (gpointer data);
245 ModestMailOperation *mail_op;
255 GList *attachments_list;
257 TnyHeaderFlags priority_flags;
258 ModestMailOperationCreateMsgCallback callback;
264 ModestMailOperation *mail_op;
266 ModestMailOperationCreateMsgCallback callback;
271 static GObjectClass *parent_class = NULL;
273 static guint signals[NUM_SIGNALS] = {0};
276 modest_mail_operation_get_type (void)
278 static GType my_type = 0;
280 static const GTypeInfo my_info = {
281 sizeof(ModestMailOperationClass),
282 NULL, /* base init */
283 NULL, /* base finalize */
284 (GClassInitFunc) modest_mail_operation_class_init,
285 NULL, /* class finalize */
286 NULL, /* class data */
287 sizeof(ModestMailOperation),
289 (GInstanceInitFunc) modest_mail_operation_init,
292 my_type = g_type_register_static (G_TYPE_OBJECT,
293 "ModestMailOperation",
300 modest_mail_operation_class_init (ModestMailOperationClass *klass)
302 GObjectClass *gobject_class;
303 gobject_class = (GObjectClass*) klass;
305 parent_class = g_type_class_peek_parent (klass);
306 gobject_class->finalize = modest_mail_operation_finalize;
308 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
311 * ModestMailOperation::progress-changed
312 * @self: the #MailOperation that emits the signal
313 * @user_data: user data set when the signal handler was connected
315 * Emitted when the progress of a mail operation changes
317 signals[PROGRESS_CHANGED_SIGNAL] =
318 g_signal_new ("progress-changed",
319 G_TYPE_FROM_CLASS (gobject_class),
321 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
323 g_cclosure_marshal_VOID__POINTER,
324 G_TYPE_NONE, 1, G_TYPE_POINTER);
328 * This signal is issued whenever a mail operation starts, and
329 * starts mean when the tinymail operation is issued. This
330 * means that it could happen that something wrong happens and
331 * the tinymail function is never called. In this situation a
332 * operation-finished will be issued without any
335 signals[OPERATION_STARTED_SIGNAL] =
336 g_signal_new ("operation-started",
337 G_TYPE_FROM_CLASS (gobject_class),
339 G_STRUCT_OFFSET (ModestMailOperationClass, operation_started),
341 g_cclosure_marshal_VOID__VOID,
346 * This signal is issued whenever a mail operation
347 * finishes. Note that this signal could be issued without any
348 * previous "operation-started" signal, because this last one
349 * is only issued when the tinymail operation is successfully
352 signals[OPERATION_FINISHED_SIGNAL] =
353 g_signal_new ("operation-finished",
354 G_TYPE_FROM_CLASS (gobject_class),
356 G_STRUCT_OFFSET (ModestMailOperationClass, operation_finished),
358 g_cclosure_marshal_VOID__VOID,
363 modest_mail_operation_init (ModestMailOperation *obj)
365 ModestMailOperationPrivate *priv;
367 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
369 priv->account = NULL;
370 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
371 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
376 priv->error_checking = NULL;
377 priv->error_checking_user_data = NULL;
381 modest_mail_operation_finalize (GObject *obj)
383 ModestMailOperationPrivate *priv;
385 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
390 g_error_free (priv->error);
394 g_object_unref (priv->source);
398 g_object_unref (priv->account);
399 priv->account = NULL;
403 G_OBJECT_CLASS(parent_class)->finalize (obj);
407 modest_mail_operation_new (GObject *source)
409 ModestMailOperation *obj;
410 ModestMailOperationPrivate *priv;
412 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
413 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
416 priv->source = g_object_ref(source);
422 modest_mail_operation_new_with_error_handling (GObject *source,
423 ErrorCheckingUserCallback error_handler,
425 ErrorCheckingUserDataDestroyer error_handler_destroyer)
427 ModestMailOperation *obj;
428 ModestMailOperationPrivate *priv;
430 obj = modest_mail_operation_new (source);
431 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
433 g_return_val_if_fail (error_handler != NULL, obj);
434 priv->error_checking = error_handler;
435 priv->error_checking_user_data = user_data;
436 priv->error_checking_user_data_destroyer = error_handler_destroyer;
442 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
444 ModestMailOperationPrivate *priv;
446 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION(self));
448 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
449 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
451 /* Call the user callback */
452 if (priv->error_checking != NULL)
453 priv->error_checking (self, priv->error_checking_user_data);
457 ModestMailOperationTypeOperation
458 modest_mail_operation_get_type_operation (ModestMailOperation *self)
460 ModestMailOperationPrivate *priv;
462 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
463 MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
465 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
467 return priv->op_type;
471 modest_mail_operation_is_mine (ModestMailOperation *self,
474 ModestMailOperationPrivate *priv;
476 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
479 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
480 if (priv->source == NULL) return FALSE;
482 return priv->source == me;
486 modest_mail_operation_get_source (ModestMailOperation *self)
488 ModestMailOperationPrivate *priv;
490 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
493 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
495 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
499 return (priv->source) ? g_object_ref (priv->source) : NULL;
502 ModestMailOperationStatus
503 modest_mail_operation_get_status (ModestMailOperation *self)
505 ModestMailOperationPrivate *priv;
507 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
508 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
509 MODEST_MAIL_OPERATION_STATUS_INVALID);
511 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
513 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
514 return MODEST_MAIL_OPERATION_STATUS_INVALID;
521 modest_mail_operation_get_error (ModestMailOperation *self)
523 ModestMailOperationPrivate *priv;
525 g_return_val_if_fail (self, NULL);
526 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
528 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
531 g_warning ("BUG: %s: priv == NULL", __FUNCTION__);
539 modest_mail_operation_cancel (ModestMailOperation *self)
541 ModestMailOperationPrivate *priv;
542 gboolean canceled = FALSE;
544 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION (self), FALSE);
546 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
549 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
551 /* Cancel the mail operation */
552 g_return_val_if_fail (priv->account, FALSE);
553 tny_account_cancel (priv->account);
555 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SEND) {
556 ModestTnySendQueue *queue;
557 queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (priv->account),
560 /* Cancel the sending of the following next messages */
561 if (TNY_IS_SEND_QUEUE (queue))
562 tny_send_queue_cancel (TNY_SEND_QUEUE (queue), TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, NULL);
569 modest_mail_operation_get_task_done (ModestMailOperation *self)
571 ModestMailOperationPrivate *priv;
573 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
576 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
581 modest_mail_operation_get_task_total (ModestMailOperation *self)
583 ModestMailOperationPrivate *priv;
585 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
588 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
593 modest_mail_operation_is_finished (ModestMailOperation *self)
595 ModestMailOperationPrivate *priv;
596 gboolean retval = FALSE;
598 g_return_val_if_fail (self && MODEST_IS_MAIL_OPERATION(self),
601 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
603 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
604 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
605 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
606 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
616 * Creates an image of the current state of a mail operation, the
617 * caller must free it
619 static ModestMailOperationState *
620 modest_mail_operation_clone_state (ModestMailOperation *self)
622 ModestMailOperationState *state;
623 ModestMailOperationPrivate *priv;
625 g_return_val_if_fail (self, NULL);
626 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
627 g_return_val_if_fail (priv, NULL);
632 state = g_slice_new (ModestMailOperationState);
634 state->status = priv->status;
635 state->op_type = priv->op_type;
636 state->done = priv->done;
637 state->total = priv->total;
638 state->finished = modest_mail_operation_is_finished (self);
639 state->bytes_done = 0;
640 state->bytes_total = 0;
645 /* ******************************************************************* */
646 /* ************************** SEND ACTIONS ************************* */
647 /* ******************************************************************* */
651 ModestMailOperation *mail_op;
656 send_mail_on_sync_async_cb (TnyFolder *folder,
661 ModestMailOperationPrivate *priv;
662 ModestMailOperation *self;
663 SendNewMailHelper *helper;
665 helper = (SendNewMailHelper *) user_data;
666 self = helper->mail_op;
667 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
673 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
674 MODEST_MAIL_OPERATION_ERROR_SEND_QUEUE_ADD_ERROR,
675 "Error adding a msg to the send queue\n");
676 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
678 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
683 modest_mail_operation_notify_end (self);
685 g_object_unref (helper->mail_op);
686 g_slice_free (SendNewMailHelper, helper);
690 run_queue_start (TnySendQueue *self,
693 RunQueueHelper *helper = (RunQueueHelper *) user_data;
694 ModestMailOperation *mail_op;
696 g_debug ("%s sending queue successfully started", __FUNCTION__);
698 /* Wait for the message to be sent */
699 mail_op = modest_mail_operation_new (NULL);
700 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
702 modest_mail_operation_run_queue (mail_op, helper->queue);
703 g_object_unref (mail_op);
705 /* Free the helper and end operation */
706 run_queue_notify_and_destroy (helper, MODEST_MAIL_OPERATION_STATUS_SUCCESS);
710 run_queue_error_happened (TnySendQueue *queue,
716 RunQueueHelper *helper = (RunQueueHelper *) user_data;
717 ModestMailOperationPrivate *priv;
719 /* If we are here this means that the send queue could not
720 start to send emails. Shouldn't happen as this means that
721 we could not create the thread */
722 g_debug ("%s sending queue failed to create the thread", __FUNCTION__);
724 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (helper->self);
725 priv->error = g_error_copy ((const GError *) error);
727 if (error->code != TNY_SYSTEM_ERROR_UNKNOWN) {
728 /* This code is here for safety reasons. It should
729 never be called, because that would mean that we
730 are not controlling some error case */
731 g_warning ("%s Error %s should not happen",
732 __FUNCTION__, error->message);
735 /* Free helper and end operation */
736 run_queue_notify_and_destroy (helper, MODEST_MAIL_OPERATION_STATUS_FAILED);
740 send_mail_on_added_to_outbox (TnySendQueue *send_queue,
746 ModestMailOperationPrivate *priv;
747 ModestMailOperation *self;
748 SendNewMailHelper *helper;
750 helper = (SendNewMailHelper *) user_data;
751 self = helper->mail_op;
752 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
758 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
759 MODEST_MAIL_OPERATION_ERROR_SEND_QUEUE_ADD_ERROR,
760 "Error adding a msg to the send queue\n");
761 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
763 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
767 if (helper->notify) {
768 TnyTransportAccount *trans_account;
769 ModestTnySendQueue *queue;
771 trans_account = (TnyTransportAccount *) modest_mail_operation_get_account (self);
773 queue = modest_runtime_get_send_queue (trans_account, TRUE);
775 RunQueueHelper *helper;
777 /* Create the helper */
778 helper = g_slice_new0 (RunQueueHelper);
779 helper->queue = g_object_ref (queue);
780 helper->self = g_object_ref (self);
782 /* if sending is ongoing wait for the queue to
783 stop. Otherwise wait for the queue-start
784 signal. It could happen that the queue
785 could not start, then check also the error
787 if (modest_tny_send_queue_sending_in_progress (queue)) {
788 run_queue_start (TNY_SEND_QUEUE (queue), helper);
790 helper->start_handler = g_signal_connect (queue, "queue-start",
791 G_CALLBACK (run_queue_start),
793 helper->error_handler = g_signal_connect (queue, "error-happened",
794 G_CALLBACK (run_queue_error_happened),
798 /* Finalize this mail operation */
799 modest_mail_operation_notify_end (self);
801 g_object_unref (trans_account);
803 g_warning ("No transport account for the operation");
807 g_object_unref (helper->mail_op);
808 g_slice_free (SendNewMailHelper, helper);
812 idle_create_msg_cb (gpointer idle_data)
814 CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data;
816 /* This is a GDK lock because we are an idle callback and
817 * info->callback can contain Gtk+ code */
819 gdk_threads_enter (); /* CHECKED */
820 info->callback (info->mail_op, info->msg, info->userdata);
822 g_object_unref (info->mail_op);
824 g_object_unref (info->msg);
825 g_slice_free (CreateMsgIdleInfo, info);
826 gdk_threads_leave (); /* CHECKED */
832 create_msg_thread (gpointer thread_data)
834 CreateMsgInfo *info = (CreateMsgInfo *) thread_data;
835 TnyMsg *new_msg = NULL;
836 ModestMailOperationPrivate *priv;
839 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
840 if (info->html_body == NULL) {
841 new_msg = modest_tny_msg_new (info->to, info->from, info->cc,
842 info->bcc, info->subject,
843 info->references, info->in_reply_to,
845 info->attachments_list, &attached,
848 new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc,
849 info->bcc, info->subject,
850 info->references, info->in_reply_to,
852 info->plain_body, info->attachments_list,
853 info->images_list, &attached,
860 /* Set priority flags in message */
861 header = tny_msg_get_header (new_msg);
862 tny_header_set_flag (header, info->priority_flags);
864 /* Set attachment flags in message */
865 if (info->attachments_list != NULL && attached > 0)
866 tny_header_set_flag (header, TNY_HEADER_FLAG_ATTACHMENTS);
868 g_object_unref (G_OBJECT(header));
870 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
872 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
873 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
874 "modest: failed to create a new msg\n");
882 g_free (info->plain_body);
883 g_free (info->html_body);
884 g_free (info->subject);
885 g_free (info->references);
886 g_free (info->in_reply_to);
887 g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL);
888 g_list_free (info->attachments_list);
889 g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL);
890 g_list_free (info->images_list);
892 if (info->callback) {
893 CreateMsgIdleInfo *idle_info;
894 idle_info = g_slice_new0 (CreateMsgIdleInfo);
895 idle_info->mail_op = g_object_ref (info->mail_op);
896 idle_info->msg = (new_msg) ? g_object_ref (new_msg) : NULL;
897 idle_info->callback = info->callback;
898 idle_info->userdata = info->userdata;
899 g_idle_add (idle_create_msg_cb, idle_info);
901 g_idle_add (idle_notify_queue, g_object_ref (info->mail_op));
904 g_object_unref (info->mail_op);
905 g_slice_free (CreateMsgInfo, info);
906 if (new_msg) g_object_unref(new_msg);
912 modest_mail_operation_create_msg (ModestMailOperation *self,
913 const gchar *from, const gchar *to,
914 const gchar *cc, const gchar *bcc,
915 const gchar *subject, const gchar *plain_body,
916 const gchar *html_body,
917 const GList *attachments_list,
918 const GList *images_list,
919 TnyHeaderFlags priority_flags,
920 const gchar *references,
921 const gchar *in_reply_to,
922 ModestMailOperationCreateMsgCallback callback,
925 CreateMsgInfo *info = NULL;
927 info = g_slice_new0 (CreateMsgInfo);
928 info->mail_op = g_object_ref (self);
930 info->from = g_strdup (from);
931 info->to = g_strdup (to);
932 info->cc = g_strdup (cc);
933 info->bcc = g_strdup (bcc);
934 info->subject = g_strdup (subject);
935 info->plain_body = g_strdup (plain_body);
936 info->html_body = g_strdup (html_body);
937 info->references = g_strdup (references);
938 info->in_reply_to = g_strdup (in_reply_to);
939 info->attachments_list = g_list_copy ((GList *) attachments_list);
940 g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL);
941 info->images_list = g_list_copy ((GList *) images_list);
942 g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL);
943 info->priority_flags = priority_flags;
945 info->callback = callback;
946 info->userdata = userdata;
948 g_thread_create (create_msg_thread, info, FALSE, NULL);
953 TnyTransportAccount *transport_account;
958 modest_mail_operation_send_new_mail_cb (ModestMailOperation *self,
962 TnySendQueue *send_queue = NULL;
963 ModestMailOperationPrivate *priv = NULL;
964 SendNewMailInfo *info = (SendNewMailInfo *) userdata;
965 TnyFolder *draft_folder = NULL;
966 TnyFolder *outbox_folder = NULL;
967 TnyHeader *header = NULL;
969 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
972 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
973 modest_mail_operation_notify_end (self);
977 if (priv->error && priv->error->code != MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
978 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
979 modest_mail_operation_notify_end (self);
983 /* Add message to send queue */
984 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (info->transport_account, TRUE));
985 if (!TNY_IS_SEND_QUEUE(send_queue)) {
987 g_error_free (priv->error);
990 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
991 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
992 "modest: could not find send queue for account\n");
993 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
994 modest_mail_operation_notify_end (self);
997 SendNewMailHelper *helper = g_slice_new (SendNewMailHelper);
998 helper->mail_op = g_object_ref (self);
999 helper->notify = (info->draft_msg == NULL);
1001 /* Add the msg to the queue. The callback will free
1003 modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue),
1005 tny_send_queue_add_async (send_queue, msg, send_mail_on_added_to_outbox,
1009 if (info->draft_msg != NULL) {
1010 TnyList *tmp_headers = NULL;
1011 TnyFolder *folder = NULL;
1012 TnyFolder *src_folder = NULL;
1013 TnyFolderType folder_type;
1014 TnyTransportAccount *transport_account = NULL;
1015 SendNewMailHelper *helper = NULL;
1017 /* To remove the old mail from its source folder, we need to get the
1018 * transport account of the original draft message (the transport account
1019 * might have been changed by the user) */
1020 header = tny_msg_get_header (info->draft_msg);
1021 transport_account = modest_tny_account_store_get_transport_account_from_outbox_header(
1022 modest_runtime_get_account_store(), header);
1023 if (transport_account == NULL)
1024 transport_account = g_object_ref(info->transport_account);
1025 draft_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
1026 TNY_FOLDER_TYPE_DRAFTS);
1027 outbox_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account),
1028 TNY_FOLDER_TYPE_OUTBOX);
1029 g_object_unref(transport_account);
1031 if (!draft_folder) {
1032 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL drafts folder",
1034 modest_mail_operation_notify_end (self);
1037 if (!outbox_folder) {
1038 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL outbox folder",
1040 modest_mail_operation_notify_end (self);
1044 folder = tny_msg_get_folder (info->draft_msg);
1045 if (folder == NULL) {
1046 modest_mail_operation_notify_end (self);
1049 folder_type = modest_tny_folder_guess_folder_type (folder);
1051 if (folder_type == TNY_FOLDER_TYPE_INVALID)
1052 g_warning ("%s: BUG: folder of type TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1054 if (folder_type == TNY_FOLDER_TYPE_OUTBOX)
1055 src_folder = outbox_folder;
1057 src_folder = draft_folder;
1059 /* Note: This can fail (with a warning) if the message is not really already in a folder,
1060 * because this function requires it to have a UID. */
1061 helper = g_slice_new (SendNewMailHelper);
1062 helper->mail_op = g_object_ref (self);
1063 helper->notify = TRUE;
1065 tmp_headers = tny_simple_list_new ();
1066 tny_list_append (tmp_headers, (GObject*) header);
1067 tny_folder_remove_msgs_async (src_folder, tmp_headers, NULL, NULL, NULL);
1068 g_object_unref (tmp_headers);
1069 tny_folder_sync_async (src_folder, TRUE, send_mail_on_sync_async_cb,
1071 g_object_unref (folder);
1076 g_object_unref (header);
1077 if (info->draft_msg)
1078 g_object_unref (info->draft_msg);
1080 g_object_unref (draft_folder);
1082 g_object_unref (outbox_folder);
1083 if (info->transport_account)
1084 g_object_unref (info->transport_account);
1085 g_slice_free (SendNewMailInfo, info);
1089 modest_mail_operation_send_new_mail (ModestMailOperation *self,
1090 TnyTransportAccount *transport_account,
1092 const gchar *from, const gchar *to,
1093 const gchar *cc, const gchar *bcc,
1094 const gchar *subject, const gchar *plain_body,
1095 const gchar *html_body,
1096 const GList *attachments_list,
1097 const GList *images_list,
1098 const gchar *references,
1099 const gchar *in_reply_to,
1100 TnyHeaderFlags priority_flags)
1102 ModestMailOperationPrivate *priv = NULL;
1103 SendNewMailInfo *info;
1105 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1106 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1108 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1109 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
1110 priv->account = TNY_ACCOUNT (g_object_ref (transport_account));
1111 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1113 modest_mail_operation_notify_start (self);
1115 /* Check parametters */
1117 /* Set status failed and set an error */
1118 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1119 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1120 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
1121 _("Error trying to send a mail. You need to set at least one recipient"));
1122 modest_mail_operation_notify_end (self);
1125 info = g_slice_new0 (SendNewMailInfo);
1126 info->transport_account = transport_account;
1127 if (transport_account)
1128 g_object_ref (transport_account);
1129 info->draft_msg = draft_msg;
1131 g_object_ref (draft_msg);
1134 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1135 attachments_list, images_list, priority_flags,
1136 references, in_reply_to,
1137 modest_mail_operation_send_new_mail_cb, info);
1143 ModestMailOperation *mailop;
1145 SaveToDraftstCallback callback;
1147 } FinishSaveRemoteDraftInfo;
1150 finish_save_remote_draft (ModestAccountProtocol *protocol,
1152 const gchar *account_id,
1153 TnyMsg *new_remote_msg,
1158 FinishSaveRemoteDraftInfo *info = (FinishSaveRemoteDraftInfo *) userdata;
1159 ModestMailOperationPrivate *priv = NULL;
1161 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1163 if (!priv->error && err != NULL) {
1164 /* Priority for errors in save to local stage */
1165 priv->error = g_error_copy (err);
1166 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1170 info->callback (info->mailop, info->msg, info->userdata);
1173 g_object_unref (info->msg);
1175 modest_mail_operation_notify_end (info->mailop);
1176 g_object_unref (info->mailop);
1178 g_slice_free (FinishSaveRemoteDraftInfo, info);
1183 TnyTransportAccount *transport_account;
1185 SaveToDraftstCallback callback;
1189 ModestMailOperation *mailop;
1190 } SaveToDraftsAddMsgInfo;
1193 modest_mail_operation_save_to_drafts_add_msg_cb(TnyFolder *self,
1198 ModestMailOperationPrivate *priv = NULL;
1199 SaveToDraftsAddMsgInfo *info = (SaveToDraftsAddMsgInfo *) userdata;
1200 GError *io_error = NULL;
1201 gboolean callback_called = FALSE;
1203 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mailop);
1205 if (priv->error && priv->error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1206 io_error = priv->error;
1210 g_warning ("%s: priv->error != NULL", __FUNCTION__);
1211 g_error_free(priv->error);
1214 priv->error = (err == NULL) ? NULL : g_error_copy(err);
1216 if ((!priv->error) && (info->draft_msg != NULL)) {
1217 TnyHeader *header = tny_msg_get_header (info->draft_msg);
1218 TnyFolder *src_folder = tny_header_get_folder (header);
1220 g_debug ("--- REMOVE AND SYNC");
1221 /* Remove the old draft */
1222 tny_folder_remove_msg (src_folder, header, NULL);
1224 /* Synchronize to expunge and to update the msg counts */
1225 tny_folder_sync_async (info->drafts, TRUE, NULL, NULL, NULL);
1226 tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL);
1227 g_debug ("--- REMOVED - SYNCED");
1229 g_object_unref (G_OBJECT(header));
1230 g_object_unref (G_OBJECT(src_folder));
1234 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1236 g_error_free (io_error);
1239 } else if (io_error) {
1240 priv->error = io_error;
1241 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
1243 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1246 if (info->transport_account) {
1247 ModestProtocolType transport_protocol_type;
1248 ModestProtocol *transport_protocol;
1250 transport_protocol_type = modest_tny_account_get_protocol_type (TNY_ACCOUNT (info->transport_account));
1252 transport_protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
1253 transport_protocol_type);
1254 if (transport_protocol && MODEST_IS_ACCOUNT_PROTOCOL (transport_protocol)) {
1255 FinishSaveRemoteDraftInfo *srd_info = g_slice_new (FinishSaveRemoteDraftInfo);
1256 srd_info->mailop = info->mailop?g_object_ref (info->mailop):NULL;
1257 srd_info->msg = info->msg?g_object_ref (info->msg):NULL;
1258 srd_info->callback = info->callback;
1259 srd_info->userdata = info->user_data;
1260 modest_account_protocol_save_remote_draft (MODEST_ACCOUNT_PROTOCOL (transport_protocol),
1261 tny_account_get_id (TNY_ACCOUNT (info->transport_account)),
1262 info->msg, info->draft_msg,
1263 finish_save_remote_draft,
1266 callback_called = TRUE;
1270 /* Call the user callback */
1271 if (!callback_called && info->callback)
1272 info->callback (info->mailop, info->msg, info->user_data);
1274 if (info->transport_account)
1275 g_object_unref (G_OBJECT(info->transport_account));
1276 if (info->draft_msg)
1277 g_object_unref (G_OBJECT (info->draft_msg));
1279 g_object_unref (G_OBJECT(info->drafts));
1281 g_object_unref (G_OBJECT (info->msg));
1283 if (!callback_called)
1284 modest_mail_operation_notify_end (info->mailop);
1286 g_object_unref(info->mailop);
1287 g_slice_free (SaveToDraftsAddMsgInfo, info);
1292 TnyTransportAccount *transport_account;
1294 SaveToDraftstCallback callback;
1299 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1303 TnyFolder *drafts = NULL;
1304 ModestMailOperationPrivate *priv = NULL;
1305 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1307 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1310 if (!(priv->error)) {
1311 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1312 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1313 "modest: failed to create a new msg\n");
1316 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1317 TNY_FOLDER_TYPE_DRAFTS);
1318 if (!drafts && !(priv->error)) {
1319 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1320 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1321 "modest: failed to create a new msg\n");
1325 if (!priv->error || priv->error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1327 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1328 cb_info->transport_account = g_object_ref(info->transport_account);
1329 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1330 cb_info->callback = info->callback;
1331 cb_info->user_data = info->user_data;
1332 cb_info->drafts = g_object_ref(drafts);
1333 cb_info->msg = g_object_ref(msg);
1334 cb_info->mailop = g_object_ref(self);
1335 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1339 /* Call the user callback */
1340 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1342 info->callback (self, msg, info->user_data);
1343 modest_mail_operation_notify_end (self);
1347 g_object_unref (G_OBJECT(drafts));
1348 if (info->draft_msg)
1349 g_object_unref (G_OBJECT (info->draft_msg));
1350 if (info->transport_account)
1351 g_object_unref (G_OBJECT(info->transport_account));
1352 g_slice_free (SaveToDraftsInfo, info);
1356 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1357 TnyTransportAccount *transport_account,
1359 const gchar *from, const gchar *to,
1360 const gchar *cc, const gchar *bcc,
1361 const gchar *subject, const gchar *plain_body,
1362 const gchar *html_body,
1363 const GList *attachments_list,
1364 const GList *images_list,
1365 TnyHeaderFlags priority_flags,
1366 const gchar *references,
1367 const gchar *in_reply_to,
1368 SaveToDraftstCallback callback,
1371 ModestMailOperationPrivate *priv = NULL;
1372 SaveToDraftsInfo *info = NULL;
1374 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1375 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1377 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1379 /* Get account and set it into mail_operation */
1380 priv->account = g_object_ref (transport_account);
1381 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1383 info = g_slice_new0 (SaveToDraftsInfo);
1384 info->transport_account = g_object_ref (transport_account);
1385 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1386 info->callback = callback;
1387 info->user_data = user_data;
1389 g_debug ("--- CREATE MESSAGE");
1390 modest_mail_operation_notify_start (self);
1391 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1392 attachments_list, images_list, priority_flags,
1393 references, in_reply_to,
1394 modest_mail_operation_save_to_drafts_cb, info);
1399 ModestMailOperation *mail_op;
1400 TnyMimePart *mime_part;
1402 GetMimePartSizeCallback callback;
1404 } GetMimePartSizeInfo;
1406 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1407 /* We use this folder observer to track the headers that have been
1408 * added to a folder */
1411 TnyList *new_headers;
1412 } InternalFolderObserver;
1415 GObjectClass parent;
1416 } InternalFolderObserverClass;
1418 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1420 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1421 internal_folder_observer,
1423 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1427 foreach_add_item (gpointer header, gpointer user_data)
1429 tny_list_append (TNY_LIST (user_data), G_OBJECT (header));
1432 /* This is the method that looks for new messages in a folder */
1434 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1436 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1438 TnyFolderChangeChanged changed;
1440 changed = tny_folder_change_get_changed (change);
1442 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1445 /* Get added headers */
1446 list = tny_simple_list_new ();
1447 tny_folder_change_get_added_headers (change, list);
1449 /* Add them to the folder observer */
1450 tny_list_foreach (list, foreach_add_item,
1451 derived->new_headers);
1453 g_object_unref (G_OBJECT (list));
1458 internal_folder_observer_init (InternalFolderObserver *self)
1460 self->new_headers = tny_simple_list_new ();
1463 internal_folder_observer_finalize (GObject *object)
1465 InternalFolderObserver *self;
1467 self = (InternalFolderObserver *) object;
1468 g_object_unref (self->new_headers);
1470 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1473 tny_folder_observer_init (TnyFolderObserverIface *iface)
1475 iface->update = internal_folder_observer_update;
1478 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1480 GObjectClass *object_class;
1482 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1483 object_class = (GObjectClass*) klass;
1484 object_class->finalize = internal_folder_observer_finalize;
1488 destroy_update_account_info (UpdateAccountInfo *info)
1490 g_free (info->account_name);
1491 g_object_unref (info->folders);
1492 g_object_unref (info->mail_op);
1493 g_slice_free (UpdateAccountInfo, info);
1498 update_account_send_mail (UpdateAccountInfo *info)
1500 TnyTransportAccount *transport_account = NULL;
1501 ModestTnyAccountStore *account_store;
1503 account_store = modest_runtime_get_account_store ();
1505 /* We don't try to send messages while sending mails is blocked */
1506 if (modest_tny_account_store_is_send_mail_blocked (account_store))
1509 /* Get the transport account */
1510 transport_account = (TnyTransportAccount *)
1511 modest_tny_account_store_get_server_account (account_store, info->account_name,
1512 TNY_ACCOUNT_TYPE_TRANSPORT);
1514 if (transport_account) {
1515 ModestTnySendQueue *send_queue;
1519 send_queue = modest_runtime_get_send_queue (transport_account, TRUE);
1520 g_object_unref (transport_account);
1522 if (TNY_IS_SEND_QUEUE (send_queue)) {
1523 /* Get outbox folder */
1524 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1525 if (outbox) { /* this could fail in some cases */
1526 num_messages = tny_folder_get_all_count (outbox);
1527 g_object_unref (outbox);
1529 g_warning ("%s: could not get outbox", __FUNCTION__);
1533 if (num_messages != 0) {
1534 ModestMailOperation *mail_op;
1535 /* Reenable suspended items */
1536 mail_op = modest_mail_operation_new (NULL);
1537 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1539 modest_mail_operation_queue_wakeup (mail_op, MODEST_TNY_SEND_QUEUE (send_queue));
1542 modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue),
1550 update_account_get_msg_async_cb (TnyFolder *folder,
1556 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1557 ModestMailOperationPrivate *priv;
1559 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (msg_info->mail_op);
1562 if (TNY_IS_MSG (msg)) {
1563 TnyHeader *header = tny_msg_get_header (msg);
1566 ModestMailOperationState *state;
1567 state = modest_mail_operation_clone_state (msg_info->mail_op);
1568 msg_info->sum_total_bytes += tny_header_get_message_size (header);
1569 state->bytes_done = msg_info->sum_total_bytes;
1570 state->bytes_total = msg_info->total_bytes;
1572 /* Notify the status change. Only notify about changes
1573 referred to bytes */
1574 g_signal_emit (G_OBJECT (msg_info->mail_op),
1575 signals[PROGRESS_CHANGED_SIGNAL],
1578 g_object_unref (header);
1579 g_slice_free (ModestMailOperationState, state);
1583 if (priv->done == priv->total) {
1584 TnyList *new_headers;
1585 UpdateAccountInfo *info;
1587 /* After getting all the messages send the ones in the
1589 info = (UpdateAccountInfo *) msg_info->user_data;
1590 update_account_send_mail (info);
1592 /* Check if the operation was a success */
1594 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1596 /* Call the user callback and free */
1597 new_headers = tny_iterator_get_list (msg_info->more_msgs);
1598 update_account_notify_user_and_free (info, new_headers);
1599 g_object_unref (new_headers);
1601 /* Delete the helper */
1602 g_object_unref (msg_info->more_msgs);
1603 g_object_unref (msg_info->mail_op);
1604 g_slice_free (GetMsgInfo, msg_info);
1609 update_account_notify_user_and_free (UpdateAccountInfo *info,
1610 TnyList *new_headers)
1612 /* Set the account back to not busy */
1613 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (),
1614 info->account_name, FALSE);
1618 info->callback (info->mail_op, new_headers, info->user_data);
1620 /* Mail operation end */
1621 modest_mail_operation_notify_end (info->mail_op);
1625 g_object_unref (new_headers);
1626 destroy_update_account_info (info);
1630 inbox_refreshed_cb (TnyFolder *inbox,
1635 UpdateAccountInfo *info;
1636 ModestMailOperationPrivate *priv;
1637 TnyIterator *new_headers_iter;
1638 GPtrArray *new_headers_array = NULL;
1639 gint max_size, retrieve_limit, i;
1640 ModestAccountMgr *mgr;
1641 ModestAccountRetrieveType retrieve_type;
1642 TnyList *new_headers = NULL;
1643 gboolean headers_only, ignore_limit;
1644 time_t time_to_store;
1646 info = (UpdateAccountInfo *) user_data;
1647 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1648 mgr = modest_runtime_get_account_mgr ();
1650 if (canceled || err) {
1651 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1653 priv->error = g_error_copy (err);
1655 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1656 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1660 tny_folder_remove_observer (inbox, info->inbox_observer);
1661 g_object_unref (info->inbox_observer);
1662 info->inbox_observer = NULL;
1664 /* Notify the user about the error and then exit */
1665 update_account_notify_user_and_free (info, NULL);
1670 /* Try to send anyway */
1674 /* Set the last updated as the current time */
1675 #ifdef MODEST_USE_LIBTIME
1677 time_get_utc (&utc_tm);
1678 time_to_store = time_mktime (&utc_tm, "GMT");
1680 time_to_store = time (NULL);
1682 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time_to_store);
1684 /* Get the message max size */
1685 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1686 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1688 max_size = G_MAXINT;
1690 max_size = max_size * KB;
1692 /* Create the new headers array. We need it to sort the
1693 new headers by date */
1694 new_headers_array = g_ptr_array_new ();
1695 if (info->inbox_observer) {
1696 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1697 while (!tny_iterator_is_done (new_headers_iter)) {
1698 TnyHeader *header = NULL;
1700 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1701 /* Apply per-message size limits */
1702 if (tny_header_get_message_size (header) < max_size)
1703 g_ptr_array_add (new_headers_array, g_object_ref (header));
1705 g_object_unref (header);
1706 tny_iterator_next (new_headers_iter);
1708 g_object_unref (new_headers_iter);
1710 tny_folder_remove_observer (inbox, info->inbox_observer);
1711 g_object_unref (info->inbox_observer);
1712 info->inbox_observer = NULL;
1715 if (new_headers_array->len == 0) {
1716 g_ptr_array_free (new_headers_array, FALSE);
1720 /* Get per-account message amount retrieval limit */
1721 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1722 if (retrieve_limit == 0)
1723 retrieve_limit = G_MAXINT;
1725 /* Get per-account retrieval type */
1726 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1727 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1730 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1732 /* Ask the users if they want to retrieve all the messages
1733 even though the limit was exceeded */
1734 ignore_limit = FALSE;
1735 if (new_headers_array->len > retrieve_limit) {
1736 /* Ask the user if a callback has been specified and
1737 if the mail operation has a source (this means that
1738 was invoked by the user and not automatically by a
1740 if (info->retrieve_all_cb && info->interactive)
1741 ignore_limit = info->retrieve_all_cb (priv->source,
1742 new_headers_array->len,
1746 /* Copy the headers to a list and free the array */
1747 new_headers = tny_simple_list_new ();
1748 for (i=0; i < new_headers_array->len; i++) {
1749 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1750 /* We want the first element to be the most recent
1751 one, that's why we reverse the list */
1752 tny_list_prepend (new_headers, G_OBJECT (header));
1754 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1755 g_ptr_array_free (new_headers_array, FALSE);
1757 if (!headers_only && (tny_list_get_length (new_headers) > 0)) {
1760 GetMsgInfo *msg_info;
1764 priv->total = tny_list_get_length (new_headers);
1766 priv->total = MIN (tny_list_get_length (new_headers), retrieve_limit);
1768 iter = tny_list_create_iterator (new_headers);
1770 /* Create the message info */
1771 msg_info = g_slice_new0 (GetMsgInfo);
1772 msg_info->mail_op = g_object_ref (info->mail_op);
1773 msg_info->total_bytes = compute_message_list_size (new_headers, priv->total);
1774 msg_info->more_msgs = g_object_ref (iter);
1775 msg_info->user_data = info;
1777 while ((msg_num < priv->total ) && !tny_iterator_is_done (iter)) {
1778 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1779 TnyFolder *folder = tny_header_get_folder (header);
1781 /* Get message in an async way */
1782 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1785 g_object_unref (folder);
1788 tny_iterator_next (iter);
1790 g_object_unref (iter);
1792 /* The mail operation will finish when the last
1793 message is retrieved */
1797 /* If we don't have to retrieve the new messages then
1799 update_account_send_mail (info);
1801 /* Check if the operation was a success */
1803 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1805 /* Call the user callback and free */
1806 update_account_notify_user_and_free (info, new_headers);
1810 inbox_refresh_status_update (GObject *obj,
1814 UpdateAccountInfo *info = NULL;
1815 ModestMailOperation *self = NULL;
1816 ModestMailOperationPrivate *priv = NULL;
1817 ModestMailOperationState *state;
1819 g_return_if_fail (user_data != NULL);
1820 g_return_if_fail (status != NULL);
1822 /* Show only the status information we want */
1823 if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
1826 info = (UpdateAccountInfo *) user_data;
1827 self = info->mail_op;
1828 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
1830 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1832 priv->done = status->position;
1833 priv->total = status->of_total;
1835 state = modest_mail_operation_clone_state (self);
1837 /* This is not a GDK lock because we are a Tinymail callback and
1838 * Tinymail already acquires the Gdk lock */
1839 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1841 g_slice_free (ModestMailOperationState, state);
1845 recurse_folders_async_cb (TnyFolderStore *folder_store,
1851 UpdateAccountInfo *info;
1852 ModestMailOperationPrivate *priv;
1854 info = (UpdateAccountInfo *) user_data;
1855 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1857 if (err || canceled) {
1858 /* If the error was previosly set by another callback
1859 don't set it again */
1861 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1863 priv->error = g_error_copy (err);
1865 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1866 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1870 /* We're not getting INBOX children if we don't want to poke all */
1871 TnyIterator *iter = tny_list_create_iterator (list);
1872 while (!tny_iterator_is_done (iter)) {
1873 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1875 /* Add to the list of all folders */
1876 tny_list_append (info->folders, (GObject *) folder);
1878 if (info->poke_all) {
1879 TnyList *folders = tny_simple_list_new ();
1880 /* Add pending call */
1881 info->pending_calls++;
1883 tny_folder_store_get_folders_async (folder, folders, NULL, FALSE,
1884 recurse_folders_async_cb,
1886 g_object_unref (folders);
1889 g_object_unref (G_OBJECT (folder));
1891 tny_iterator_next (iter);
1893 g_object_unref (G_OBJECT (iter));
1896 /* Remove my own pending call */
1897 info->pending_calls--;
1899 /* This means that we have all the folders */
1900 if (info->pending_calls == 0) {
1901 TnyIterator *iter_all_folders;
1902 TnyFolder *inbox = NULL;
1904 /* If there was any error do not continue */
1906 update_account_notify_user_and_free (info, NULL);
1910 iter_all_folders = tny_list_create_iterator (info->folders);
1912 /* Do a poke status over all folders */
1913 while (!tny_iterator_is_done (iter_all_folders) &&
1914 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1915 TnyFolder *folder = NULL;
1917 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1919 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1920 /* Get a reference to the INBOX */
1921 inbox = g_object_ref (folder);
1923 /* Issue a poke status over the folder */
1925 tny_folder_poke_status (folder);
1928 /* Free and go to next */
1929 g_object_unref (folder);
1930 tny_iterator_next (iter_all_folders);
1932 g_object_unref (iter_all_folders);
1934 /* Refresh the INBOX */
1936 /* Refresh the folder. Our observer receives
1937 * the new emails during folder refreshes, so
1938 * we can use observer->new_headers
1940 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1941 tny_folder_add_observer (inbox, info->inbox_observer);
1943 /* Refresh the INBOX */
1944 tny_folder_refresh_async (inbox, inbox_refreshed_cb, inbox_refresh_status_update, info);
1945 g_object_unref (inbox);
1947 /* We could not perform the inbox refresh but
1948 we'll try to send mails anyway */
1949 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1955 modest_mail_operation_update_account (ModestMailOperation *self,
1956 const gchar *account_name,
1958 gboolean interactive,
1959 RetrieveAllCallback retrieve_all_cb,
1960 UpdateAccountCallback callback,
1963 UpdateAccountInfo *info = NULL;
1964 ModestMailOperationPrivate *priv = NULL;
1965 ModestTnyAccountStore *account_store = NULL;
1967 ModestMailOperationState *state;
1969 /* Init mail operation */
1970 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1973 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1974 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1976 /* Get the store account */
1977 account_store = modest_runtime_get_account_store ();
1979 modest_tny_account_store_get_server_account (account_store,
1981 TNY_ACCOUNT_TYPE_STORE);
1983 /* The above function could return NULL */
1984 if (!priv->account) {
1985 /* Check if the operation was a success */
1986 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1987 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1989 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1991 /* Call the user callback */
1993 callback (self, NULL, user_data);
1995 /* Notify about operation end */
1996 modest_mail_operation_notify_end (self);
2001 /* We have once seen priv->account getting finalized during this code,
2002 * therefore adding a reference (bug #82296) */
2004 g_object_ref (priv->account);
2006 /* Create the helper object */
2007 info = g_slice_new0 (UpdateAccountInfo);
2008 info->pending_calls = 1;
2009 info->folders = tny_simple_list_new ();
2010 info->mail_op = g_object_ref (self);
2011 info->poke_all = poke_all;
2012 info->interactive = interactive;
2013 info->account_name = g_strdup (account_name);
2014 info->callback = callback;
2015 info->user_data = user_data;
2016 info->retrieve_all_cb = retrieve_all_cb;
2018 /* Set account busy */
2019 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
2020 modest_mail_operation_notify_start (self);
2022 /* notify about the start of the operation */
2023 state = modest_mail_operation_clone_state (self);
2027 /* Start notifying progress */
2028 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2029 g_slice_free (ModestMailOperationState, state);
2031 /* Get all folders and continue in the callback */
2032 folders = tny_simple_list_new ();
2033 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (priv->account),
2034 folders, NULL, FALSE,
2035 recurse_folders_async_cb,
2037 g_object_unref (folders);
2039 g_object_unref (priv->account);
2044 * Used to notify the queue from the main
2045 * loop. We call it inside an idle call to achieve that
2048 idle_notify_queue (gpointer data)
2050 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
2052 gdk_threads_enter ();
2053 modest_mail_operation_notify_end (mail_op);
2054 gdk_threads_leave ();
2055 g_object_unref (mail_op);
2061 compare_headers_by_date (gconstpointer a,
2064 TnyHeader **header1, **header2;
2065 time_t sent1, sent2;
2067 header1 = (TnyHeader **) a;
2068 header2 = (TnyHeader **) b;
2070 sent1 = tny_header_get_date_sent (*header1);
2071 sent2 = tny_header_get_date_sent (*header2);
2073 /* We want the most recent ones (greater time_t) at the
2082 /* ******************************************************************* */
2083 /* ************************** STORE ACTIONS ************************* */
2084 /* ******************************************************************* */
2087 ModestMailOperation *mail_op;
2088 CreateFolderUserCallback callback;
2094 create_folder_cb (TnyFolderStore *parent_folder,
2096 TnyFolder *new_folder,
2100 ModestMailOperationPrivate *priv;
2101 CreateFolderInfo *info;
2103 info = (CreateFolderInfo *) user_data;
2104 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2106 if (canceled || err) {
2107 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2109 priv->error = g_error_copy (err);
2111 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2112 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2115 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2118 /* The user will unref the new_folder */
2120 info->callback (info->mail_op, parent_folder,
2121 new_folder, info->user_data);
2123 /* Notify about operation end */
2124 modest_mail_operation_notify_end (info->mail_op);
2127 g_object_unref (info->mail_op);
2128 g_slice_free (CreateFolderInfo, info);
2132 modest_mail_operation_create_folder (ModestMailOperation *self,
2133 TnyFolderStore *parent,
2135 CreateFolderUserCallback callback,
2138 ModestMailOperationPrivate *priv;
2140 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2141 g_return_if_fail (name);
2143 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2144 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2145 priv->account = (TNY_IS_ACCOUNT (parent)) ?
2146 g_object_ref (parent) :
2147 modest_tny_folder_get_account (TNY_FOLDER (parent));
2149 /* Check for already existing folder */
2150 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
2151 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2152 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2153 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2154 _CS("ckdg_ib_folder_already_exists"));
2158 if (TNY_IS_FOLDER (parent)) {
2159 /* Check folder rules */
2160 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2161 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2162 /* Set status failed and set an error */
2163 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2164 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2165 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2166 _("mail_in_ui_folder_create_error"));
2170 if (!priv->error && (!strcmp (name, " ") || strchr (name, '/'))) {
2171 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2172 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2173 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2174 _("mail_in_ui_folder_create_error"));
2178 CreateFolderInfo *info;
2180 info = g_slice_new0 (CreateFolderInfo);
2181 info->mail_op = g_object_ref (self);
2182 info->callback = callback;
2183 info->user_data = user_data;
2185 modest_mail_operation_notify_start (self);
2187 /* Create the folder */
2188 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
2191 /* Call the user callback anyway */
2193 callback (self, parent, NULL, user_data);
2194 /* Notify about operation end */
2195 modest_mail_operation_notify_end (self);
2200 modest_mail_operation_remove_folder (ModestMailOperation *self,
2202 gboolean remove_to_trash)
2204 ModestMailOperationPrivate *priv;
2205 ModestTnyFolderRules rules;
2207 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2208 g_return_if_fail (TNY_IS_FOLDER (folder));
2210 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2212 /* Check folder rules */
2213 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2214 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
2215 /* Set status failed and set an error */
2216 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2217 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2218 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2219 _("mail_in_ui_folder_delete_error"));
2223 /* Get the account */
2224 priv->account = modest_tny_folder_get_account (folder);
2225 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2227 /* Delete folder or move to trash */
2228 if (remove_to_trash) {
2229 TnyFolder *trash_folder = NULL;
2230 trash_folder = modest_tny_account_get_special_folder (priv->account,
2231 TNY_FOLDER_TYPE_TRASH);
2232 /* TODO: error_handling */
2234 modest_mail_operation_notify_start (self);
2235 modest_mail_operation_xfer_folder (self, folder,
2236 TNY_FOLDER_STORE (trash_folder),
2238 g_object_unref (trash_folder);
2240 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
2243 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
2245 modest_mail_operation_notify_start (self);
2246 tny_folder_store_remove_folder (parent, folder, &(priv->error));
2247 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
2250 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2252 g_object_unref (parent);
2254 g_warning ("%s: could not get parent folder", __FUNCTION__);
2258 /* Notify about operation end */
2259 modest_mail_operation_notify_end (self);
2263 transfer_folder_status_cb (GObject *obj,
2267 ModestMailOperation *self;
2268 ModestMailOperationPrivate *priv;
2269 ModestMailOperationState *state;
2270 XFerFolderAsyncHelper *helper;
2272 g_return_if_fail (status != NULL);
2274 /* Show only the status information we want */
2275 if (status->code != TNY_FOLDER_STATUS_CODE_COPY_FOLDER)
2278 helper = (XFerFolderAsyncHelper *) user_data;
2279 g_return_if_fail (helper != NULL);
2281 self = helper->mail_op;
2282 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2284 priv->done = status->position;
2285 priv->total = status->of_total;
2287 state = modest_mail_operation_clone_state (self);
2289 /* This is not a GDK lock because we are a Tinymail callback
2290 * which is already GDK locked by Tinymail */
2292 /* no gdk_threads_enter (), CHECKED */
2294 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2296 /* no gdk_threads_leave (), CHECKED */
2298 g_slice_free (ModestMailOperationState, state);
2302 transfer_folder_cb (TnyFolder *folder,
2304 TnyFolderStore *into,
2305 TnyFolder *new_folder,
2309 XFerFolderAsyncHelper *helper;
2310 ModestMailOperation *self = NULL;
2311 ModestMailOperationPrivate *priv = NULL;
2313 helper = (XFerFolderAsyncHelper *) user_data;
2314 g_return_if_fail (helper != NULL);
2316 self = helper->mail_op;
2317 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2320 priv->error = g_error_copy (err);
2322 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2323 } else if (cancelled) {
2324 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2325 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2326 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2327 _("Transference of %s was cancelled."),
2328 tny_folder_get_name (folder));
2331 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2334 /* Update state of new folder */
2336 tny_folder_refresh_async (new_folder, NULL, NULL, NULL);
2337 tny_folder_poke_status (new_folder);
2340 /* Notify about operation end */
2341 modest_mail_operation_notify_end (self);
2343 /* If user defined callback function was defined, call it */
2344 if (helper->user_callback) {
2346 /* This is not a GDK lock because we are a Tinymail callback
2347 * which is already GDK locked by Tinymail */
2349 /* no gdk_threads_enter (), CHECKED */
2350 helper->user_callback (self, new_folder, helper->user_data);
2351 /* no gdk_threads_leave () , CHECKED */
2355 g_object_unref (helper->mail_op);
2356 g_slice_free (XFerFolderAsyncHelper, helper);
2361 * This function checks if the new name is a valid name for our local
2362 * folders account. The new name could not be the same than then name
2363 * of any of the mandatory local folders
2365 * We can not rely on tinymail because tinymail does not check the
2366 * name of the virtual folders that the account could have in the case
2367 * that we're doing a rename (because it directly calls Camel which
2368 * knows nothing about our virtual folders).
2370 * In the case of an actual copy/move (i.e. move/copy a folder between
2371 * accounts) tinymail uses the tny_folder_store_create_account which
2372 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
2373 * checks the new name of the folder, so this call in that case
2374 * wouldn't be needed. *But* NOTE that if tinymail changes its
2375 * implementation (if folder transfers within the same account is no
2376 * longer implemented as a rename) this call will allow Modest to work
2379 * If the new name is not valid, this function will set the status to
2380 * failed and will set also an error in the mail operation
2383 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
2384 TnyFolderStore *into,
2385 const gchar *new_name)
2387 if (TNY_IS_ACCOUNT (into) &&
2388 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
2389 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
2391 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2392 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2393 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2394 _CS("ckdg_ib_folder_already_exists"));
2401 modest_mail_operation_xfer_folder (ModestMailOperation *self,
2403 TnyFolderStore *parent,
2404 gboolean delete_original,
2405 XferFolderAsyncUserCallback user_callback,
2408 ModestMailOperationPrivate *priv = NULL;
2409 ModestTnyFolderRules parent_rules = 0, rules;
2410 XFerFolderAsyncHelper *helper = NULL;
2411 const gchar *folder_name = NULL;
2412 const gchar *error_msg;
2414 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2415 g_return_if_fail (TNY_IS_FOLDER (folder));
2416 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2418 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2419 folder_name = tny_folder_get_name (folder);
2421 /* Set the error msg */
2422 error_msg = _("mail_in_ui_folder_move_target_error");
2424 /* Get account and set it into mail_operation */
2425 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2426 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2427 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2429 /* Get folder rules */
2430 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2431 if (TNY_IS_FOLDER (parent))
2432 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2434 /* Apply operation constraints */
2435 if ((gpointer) parent == (gpointer) folder ||
2436 (!TNY_IS_FOLDER_STORE (parent)) ||
2437 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
2440 } else if (TNY_IS_FOLDER (parent) &&
2441 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2445 } else if (TNY_IS_FOLDER (parent) &&
2446 TNY_IS_FOLDER_STORE (folder) &&
2447 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2448 TNY_FOLDER_STORE (folder))) {
2449 /* Do not move a parent into a child */
2451 } else if (TNY_IS_FOLDER_STORE (parent) &&
2452 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2453 /* Check that the new folder name is not used by any
2456 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2457 /* Check that the new folder name is not used by any
2458 special local folder */
2461 /* Create the helper */
2462 helper = g_slice_new0 (XFerFolderAsyncHelper);
2463 helper->mail_op = g_object_ref (self);
2464 helper->user_callback = user_callback;
2465 helper->user_data = user_data;
2467 /* Move/Copy folder */
2468 modest_mail_operation_notify_start (self);
2469 tny_folder_copy_async (folder,
2471 tny_folder_get_name (folder),
2474 transfer_folder_status_cb,
2480 /* Set status failed and set an error */
2481 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2482 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2483 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2486 /* Call the user callback if exists */
2488 user_callback (self, NULL, user_data);
2490 /* Notify the queue */
2491 modest_mail_operation_notify_end (self);
2495 modest_mail_operation_rename_folder (ModestMailOperation *self,
2498 XferFolderAsyncUserCallback user_callback,
2501 ModestMailOperationPrivate *priv;
2502 ModestTnyFolderRules rules;
2503 XFerFolderAsyncHelper *helper;
2505 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2506 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2507 g_return_if_fail (name);
2509 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2511 /* Get account and set it into mail_operation */
2512 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2513 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2515 /* Check folder rules */
2516 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2517 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2519 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2522 TnyFolderStore *into;
2524 into = tny_folder_get_folder_store (folder);
2526 /* Check that the new folder name is not used by any
2527 special local folder */
2528 if (new_name_valid_if_local_account (priv, into, name)) {
2529 /* Create the helper */
2530 helper = g_slice_new0 (XFerFolderAsyncHelper);
2531 helper->mail_op = g_object_ref(self);
2532 helper->user_callback = user_callback;
2533 helper->user_data = user_data;
2535 /* Rename. Camel handles folder subscription/unsubscription */
2536 modest_mail_operation_notify_start (self);
2537 tny_folder_copy_async (folder, into, name, TRUE,
2539 transfer_folder_status_cb,
2541 g_object_unref (into);
2543 g_object_unref (into);
2550 /* Set status failed and set an error */
2551 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2552 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2553 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2554 _("FIXME: unable to rename"));
2557 user_callback (self, NULL, user_data);
2559 /* Notify about operation end */
2560 modest_mail_operation_notify_end (self);
2563 /* ******************************************************************* */
2564 /* ************************** MSG ACTIONS ************************* */
2565 /* ******************************************************************* */
2568 modest_mail_operation_find_msg (ModestMailOperation *self,
2570 const gchar *msg_uid,
2571 gboolean progress_feedback,
2572 GetMsgAsyncUserCallback user_callback,
2575 GetMsgInfo *helper = NULL;
2576 ModestMailOperationPrivate *priv;
2578 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2579 g_return_if_fail (msg_uid != NULL);
2581 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2582 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2586 /* Check memory low */
2587 if (_check_memory_low (self)) {
2589 user_callback (self, NULL, FALSE, NULL, priv->error, user_data);
2590 modest_mail_operation_notify_end (self);
2594 /* Get account and set it into mail_operation */
2595 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2597 /* Check for cached messages */
2598 if (progress_feedback) {
2599 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2601 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
2604 /* Create the helper */
2605 helper = g_slice_new0 (GetMsgInfo);
2606 helper->header = NULL;
2607 helper->mail_op = g_object_ref (self);
2608 helper->user_callback = user_callback;
2609 helper->user_data = user_data;
2610 helper->destroy_notify = NULL;
2611 helper->last_total_bytes = 0;
2612 helper->sum_total_bytes = 0;
2613 helper->total_bytes = 0;
2614 helper->more_msgs = NULL;
2616 modest_mail_operation_notify_start (self);
2618 /* notify about the start of the operation */
2619 ModestMailOperationState *state;
2620 state = modest_mail_operation_clone_state (self);
2623 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2625 g_slice_free (ModestMailOperationState, state);
2627 tny_folder_find_msg_async (folder, msg_uid, get_msg_async_cb, get_msg_status_cb, helper);
2631 modest_mail_operation_get_msg (ModestMailOperation *self,
2633 gboolean progress_feedback,
2634 GetMsgAsyncUserCallback user_callback,
2637 GetMsgInfo *helper = NULL;
2639 ModestMailOperationPrivate *priv;
2641 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2642 g_return_if_fail (TNY_IS_HEADER (header));
2644 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2645 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2649 /* Check memory low */
2650 if (_check_memory_low (self)) {
2652 user_callback (self, header, FALSE, NULL, priv->error, user_data);
2653 modest_mail_operation_notify_end (self);
2657 /* Get account and set it into mail_operation */
2658 folder = tny_header_get_folder (header);
2659 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2661 /* Check for cached messages */
2662 if (progress_feedback) {
2663 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2664 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2666 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2668 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
2671 /* Create the helper */
2672 helper = g_slice_new0 (GetMsgInfo);
2673 helper->header = g_object_ref (header);
2674 helper->mail_op = g_object_ref (self);
2675 helper->user_callback = user_callback;
2676 helper->user_data = user_data;
2677 helper->destroy_notify = NULL;
2678 helper->last_total_bytes = 0;
2679 helper->sum_total_bytes = 0;
2680 helper->total_bytes = tny_header_get_message_size (header);
2681 helper->more_msgs = NULL;
2683 modest_mail_operation_notify_start (self);
2685 /* notify about the start of the operation */
2686 ModestMailOperationState *state;
2687 state = modest_mail_operation_clone_state (self);
2690 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2692 g_slice_free (ModestMailOperationState, state);
2694 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2696 g_object_unref (G_OBJECT (folder));
2700 get_msg_status_cb (GObject *obj,
2704 GetMsgInfo *helper = NULL;
2706 g_return_if_fail (status != NULL);
2708 /* Show only the status information we want */
2709 if (status->code != TNY_FOLDER_STATUS_CODE_GET_MSG)
2712 helper = (GetMsgInfo *) user_data;
2713 g_return_if_fail (helper != NULL);
2715 /* Notify progress */
2716 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2717 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2721 get_msg_async_cb (TnyFolder *folder,
2727 GetMsgInfo *info = NULL;
2728 ModestMailOperationPrivate *priv = NULL;
2731 info = (GetMsgInfo *) user_data;
2733 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2736 if (info->more_msgs) {
2737 tny_iterator_next (info->more_msgs);
2738 finished = (tny_iterator_is_done (info->more_msgs));
2740 finished = (priv->done == priv->total) ? TRUE : FALSE;
2743 /* If canceled by the user, ignore the error given by Tinymail */
2747 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2749 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2750 priv->error = g_error_copy ((const GError *) err);
2752 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2754 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2755 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2758 } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
2759 /* Set the success status before calling the user callback */
2760 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2763 if (info->header == NULL && msg)
2764 info->header = tny_msg_get_header (msg);
2766 /* Call the user callback */
2767 if (info->user_callback)
2768 info->user_callback (info->mail_op, info->header, canceled,
2769 msg, err, info->user_data);
2771 /* Notify about operation end if this is the last callback */
2773 /* Free user data */
2774 if (info->destroy_notify)
2775 info->destroy_notify (info->user_data);
2777 /* Notify about operation end */
2778 modest_mail_operation_notify_end (info->mail_op);
2781 if (info->more_msgs)
2782 g_object_unref (info->more_msgs);
2784 g_object_unref (info->header);
2785 g_object_unref (info->mail_op);
2786 g_slice_free (GetMsgInfo, info);
2787 } else if (info->more_msgs) {
2788 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->more_msgs));
2789 TnyFolder *folder = tny_header_get_folder (header);
2791 g_object_unref (info->header);
2792 info->header = g_object_ref (header);
2794 /* Retrieve the next message */
2795 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, info);
2797 g_object_unref (header);
2798 g_object_unref (folder);
2800 g_warning ("%s: finished != TRUE but no messages left", __FUNCTION__);
2805 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2806 TnyList *header_list,
2807 GetMsgAsyncUserCallback user_callback,
2809 GDestroyNotify notify)
2811 ModestMailOperationPrivate *priv = NULL;
2813 TnyIterator *iter = NULL;
2814 gboolean has_uncached_messages;
2816 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2818 /* Init mail operation */
2819 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2820 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2822 priv->total = tny_list_get_length(header_list);
2824 /* Check memory low */
2825 if (_check_memory_low (self)) {
2826 if (user_callback) {
2827 TnyHeader *header = NULL;
2830 if (tny_list_get_length (header_list) > 0) {
2831 iter = tny_list_create_iterator (header_list);
2832 header = (TnyHeader *) tny_iterator_get_current (iter);
2833 g_object_unref (iter);
2835 user_callback (self, header, FALSE, NULL, priv->error, user_data);
2837 g_object_unref (header);
2841 /* Notify about operation end */
2842 modest_mail_operation_notify_end (self);
2846 /* Check uncached messages */
2847 for (iter = tny_list_create_iterator (header_list), has_uncached_messages = FALSE;
2848 !has_uncached_messages && !tny_iterator_is_done (iter);
2849 tny_iterator_next (iter)) {
2852 header = (TnyHeader *) tny_iterator_get_current (iter);
2853 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
2854 has_uncached_messages = TRUE;
2855 g_object_unref (header);
2857 g_object_unref (iter);
2858 priv->op_type = has_uncached_messages?MODEST_MAIL_OPERATION_TYPE_RECEIVE:MODEST_MAIL_OPERATION_TYPE_OPEN;
2860 /* Get account and set it into mail_operation */
2861 if (tny_list_get_length (header_list) >= 1) {
2862 TnyIterator *iterator = tny_list_create_iterator (header_list);
2863 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iterator));
2865 TnyFolder *folder = tny_header_get_folder (header);
2867 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2868 g_object_unref (folder);
2870 g_object_unref (header);
2872 g_object_unref (iterator);
2875 msg_list_size = compute_message_list_size (header_list, 0);
2877 modest_mail_operation_notify_start (self);
2878 iter = tny_list_create_iterator (header_list);
2879 if (!tny_iterator_is_done (iter)) {
2880 /* notify about the start of the operation */
2881 ModestMailOperationState *state;
2882 state = modest_mail_operation_clone_state (self);
2885 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2888 GetMsgInfo *msg_info = NULL;
2889 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2890 TnyFolder *folder = tny_header_get_folder (header);
2892 /* Create the message info */
2893 msg_info = g_slice_new0 (GetMsgInfo);
2894 msg_info->mail_op = g_object_ref (self);
2895 msg_info->header = g_object_ref (header);
2896 msg_info->more_msgs = g_object_ref (iter);
2897 msg_info->user_callback = user_callback;
2898 msg_info->user_data = user_data;
2899 msg_info->destroy_notify = notify;
2900 msg_info->last_total_bytes = 0;
2901 msg_info->sum_total_bytes = 0;
2902 msg_info->total_bytes = msg_list_size;
2904 /* The callback will call it per each header */
2905 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2907 /* Free and go on */
2908 g_object_unref (header);
2909 g_object_unref (folder);
2910 g_slice_free (ModestMailOperationState, state);
2912 g_object_unref (iter);
2917 remove_msgs_async_cb (TnyFolder *folder,
2922 gboolean expunge, leave_on_server;
2923 const gchar *account_name;
2924 TnyAccount *account;
2925 ModestProtocolType account_proto = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
2926 ModestMailOperation *self;
2927 ModestMailOperationPrivate *priv;
2928 ModestProtocolRegistry *protocol_registry;
2930 self = (ModestMailOperation *) user_data;
2931 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2932 protocol_registry = modest_runtime_get_protocol_registry ();
2934 if (canceled || err) {
2935 /* If canceled by the user, ignore the error given by Tinymail */
2937 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2939 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2940 priv->error = g_error_copy ((const GError *) err);
2941 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2944 modest_mail_operation_notify_end (self);
2945 g_object_unref (self);
2949 account = modest_tny_folder_get_account (folder);
2950 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2952 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2954 account_proto = modest_tny_account_get_protocol_type (account);
2955 g_object_unref (account);
2957 if ((modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_proto) &&
2958 !leave_on_server) ||
2959 !modest_tny_folder_is_remote_folder (folder))
2965 tny_folder_sync_async(folder, expunge, sync_folder_finish_callback,
2970 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2972 gboolean remove_to_trash /*ignored*/)
2974 TnyFolder *folder = NULL;
2975 ModestMailOperationPrivate *priv;
2976 TnyIterator *iter = NULL;
2977 TnyHeader *header = NULL;
2978 TnyList *remove_headers = NULL;
2979 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2980 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2982 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2983 g_return_if_fail (TNY_IS_LIST (headers));
2985 if (remove_to_trash)
2986 g_warning ("remove to trash is not implemented");
2988 if (tny_list_get_length(headers) == 0) {
2989 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2990 goto cleanup; /* nothing to do */
2993 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2995 /* Get folder from first header and sync it */
2996 iter = tny_list_create_iterator (headers);
2997 header = TNY_HEADER (tny_iterator_get_current (iter));
2998 g_object_unref (iter);
3000 folder = tny_header_get_folder (header);
3001 if (!TNY_IS_FOLDER(folder)) {
3002 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
3006 /* Use the merged folder if we're removing messages from outbox */
3007 if (modest_tny_folder_is_local_folder (folder)) {
3008 ModestTnyLocalFoldersAccount *local_account;
3010 local_account = (ModestTnyLocalFoldersAccount *)
3011 modest_tny_account_store_get_local_folders_account (accstore);
3012 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
3013 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
3014 g_object_unref (folder);
3015 folder = modest_tny_local_folders_account_get_merged_outbox (local_account);
3017 g_object_unref (local_account);
3020 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
3021 TnyIterator *headers_iter = tny_list_create_iterator (headers);
3023 while (!tny_iterator_is_done (headers_iter)) {
3024 TnyTransportAccount *traccount = NULL;
3025 TnyHeader *hdr = NULL;
3027 hdr = TNY_HEADER (tny_iterator_get_current (headers_iter));
3028 traccount = modest_tny_account_store_get_transport_account_from_outbox_header (accstore,
3031 ModestTnySendQueueStatus status;
3032 ModestTnySendQueue *send_queue;
3034 send_queue = modest_runtime_get_send_queue(traccount, TRUE);
3035 if (TNY_IS_SEND_QUEUE (send_queue)) {
3038 msg_id = modest_tny_send_queue_get_msg_id (hdr);
3039 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
3040 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
3041 if (G_UNLIKELY (remove_headers == NULL))
3042 remove_headers = tny_simple_list_new ();
3043 tny_list_append(remove_headers, G_OBJECT(hdr));
3047 g_object_unref(traccount);
3049 g_object_unref(hdr);
3050 tny_iterator_next (headers_iter);
3052 g_object_unref(headers_iter);
3055 /* Get account and set it into mail_operation */
3056 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
3057 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
3058 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3060 if (!remove_headers)
3061 remove_headers = g_object_ref (headers);
3063 /* remove message from folder */
3064 modest_mail_operation_notify_start (self);
3065 tny_folder_remove_msgs_async (folder, remove_headers, remove_msgs_async_cb,
3066 NULL, g_object_ref (self));
3070 g_object_unref (remove_headers);
3072 g_object_unref (header);
3074 g_object_unref (folder);
3078 notify_progress_of_multiple_messages (ModestMailOperation *self,
3080 gint *last_total_bytes,
3081 gint *sum_total_bytes,
3083 gboolean increment_done)
3085 ModestMailOperationPrivate *priv;
3086 ModestMailOperationState *state;
3087 gboolean is_num_bytes = FALSE;
3089 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3091 /* We know that tinymail sends us information about
3092 * transferred bytes with this particular message
3094 if (status->message)
3095 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
3097 state = modest_mail_operation_clone_state (self);
3098 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
3099 /* We know that we're in a different message when the
3100 total number of bytes to transfer is different. Of
3101 course it could fail if we're transferring messages
3102 of the same size, but this is a workarround */
3103 if (status->of_total != *last_total_bytes) {
3104 /* We need to increment the done when there is
3105 no information about each individual
3106 message, we need to do this in message
3107 transfers, and we don't do it for getting
3111 *sum_total_bytes += *last_total_bytes;
3112 *last_total_bytes = status->of_total;
3114 state->bytes_done += status->position + *sum_total_bytes;
3115 state->bytes_total = total_bytes;
3117 /* Notify the status change. Only notify about changes
3118 referred to bytes */
3119 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3123 g_slice_free (ModestMailOperationState, state);
3127 transfer_msgs_status_cb (GObject *obj,
3131 XFerMsgsAsyncHelper *helper;
3133 g_return_if_fail (status != NULL);
3135 /* Show only the status information we want */
3136 if (status->code != TNY_FOLDER_STATUS_CODE_XFER_MSGS)
3139 helper = (XFerMsgsAsyncHelper *) user_data;
3140 g_return_if_fail (helper != NULL);
3142 /* Notify progress */
3143 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
3144 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
3148 transfer_msgs_sync_folder_cb (TnyFolder *self,
3153 XFerMsgsAsyncHelper *helper;
3154 /* We don't care here about the results of the
3156 helper = (XFerMsgsAsyncHelper *) user_data;
3158 /* Notify about operation end */
3159 modest_mail_operation_notify_end (helper->mail_op);
3161 /* If user defined callback function was defined, call it */
3162 if (helper->user_callback)
3163 helper->user_callback (helper->mail_op, helper->user_data);
3166 if (helper->more_msgs)
3167 g_object_unref (helper->more_msgs);
3168 if (helper->headers)
3169 g_object_unref (helper->headers);
3170 if (helper->dest_folder)
3171 g_object_unref (helper->dest_folder);
3172 if (helper->mail_op)
3173 g_object_unref (helper->mail_op);
3174 g_slice_free (XFerMsgsAsyncHelper, helper);
3178 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
3180 XFerMsgsAsyncHelper *helper;
3181 ModestMailOperation *self;
3182 ModestMailOperationPrivate *priv;
3183 gboolean finished = TRUE;
3185 helper = (XFerMsgsAsyncHelper *) user_data;
3186 self = helper->mail_op;
3188 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3191 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3193 priv->error = g_error_copy (err);
3195 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3196 } else if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
3197 if (helper->more_msgs) {
3198 /* We'll transfer the next message in the list */
3199 tny_iterator_next (helper->more_msgs);
3200 if (!tny_iterator_is_done (helper->more_msgs)) {
3201 GObject *next_header;
3202 g_object_unref (helper->headers);
3203 helper->headers = tny_simple_list_new ();
3204 next_header = tny_iterator_get_current (helper->more_msgs);
3205 tny_list_append (helper->headers, next_header);
3206 g_object_unref (next_header);
3212 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3217 /* Synchronize the source folder contents. This should
3218 be done by tinymail but the camel_folder_sync it's
3219 actually disabled in transfer_msgs_thread_clean
3220 because it's supposed to cause hangs */
3221 tny_folder_sync_async (folder, helper->delete,
3222 transfer_msgs_sync_folder_cb,
3225 /* Transfer more messages */
3226 tny_folder_transfer_msgs_async (folder,
3228 helper->dest_folder,
3231 transfer_msgs_status_cb,
3236 /* Computes the size of the messages the headers in the list belongs
3237 to. If num_elements is different from 0 then it only takes into
3238 account the first num_elements for the calculation */
3240 compute_message_list_size (TnyList *headers,
3244 guint size = 0, element = 0;
3246 /* If num_elements is not valid then take all into account */
3247 if ((num_elements <= 0) || (num_elements > tny_list_get_length (headers)))
3248 num_elements = tny_list_get_length (headers);
3250 iter = tny_list_create_iterator (headers);
3251 while (!tny_iterator_is_done (iter) && element < num_elements) {
3252 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
3253 size += tny_header_get_message_size (header);
3254 g_object_unref (header);
3255 tny_iterator_next (iter);
3258 g_object_unref (iter);
3264 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
3267 gboolean delete_original,
3268 XferMsgsAsyncUserCallback user_callback,
3271 ModestMailOperationPrivate *priv = NULL;
3272 TnyIterator *iter = NULL;
3273 TnyFolder *src_folder = NULL;
3274 XFerMsgsAsyncHelper *helper = NULL;
3275 TnyHeader *header = NULL;
3276 ModestTnyFolderRules rules = 0;
3277 TnyAccount *dst_account = NULL;
3278 gboolean leave_on_server;
3279 ModestMailOperationState *state;
3280 ModestProtocolRegistry *protocol_registry;
3281 ModestProtocolType account_protocol;
3283 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
3284 g_return_if_fail (headers && TNY_IS_LIST (headers));
3285 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
3287 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3288 protocol_registry = modest_runtime_get_protocol_registry ();
3290 priv->total = tny_list_get_length (headers);
3292 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3293 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3295 /* Apply folder rules */
3296 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
3297 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3298 /* Set status failed and set an error */
3299 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3300 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3301 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
3302 _CS("ckct_ib_unable_to_paste_here"));
3303 /* Notify the queue */
3304 modest_mail_operation_notify_end (self);
3308 /* Get source folder */
3309 iter = tny_list_create_iterator (headers);
3310 header = TNY_HEADER (tny_iterator_get_current (iter));
3312 src_folder = tny_header_get_folder (header);
3313 g_object_unref (header);
3315 g_object_unref (iter);
3317 if (src_folder == NULL) {
3318 /* Notify the queue */
3319 modest_mail_operation_notify_end (self);
3321 g_warning ("%s: cannot find folder from header", __FUNCTION__);
3326 /* Check folder source and destination */
3327 if (src_folder == folder) {
3328 /* Set status failed and set an error */
3329 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3330 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3331 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
3332 _("mail_in_ui_folder_copy_target_error"));
3334 /* Notify the queue */
3335 modest_mail_operation_notify_end (self);
3338 g_object_unref (src_folder);
3342 /* Create the helper */
3343 helper = g_slice_new0 (XFerMsgsAsyncHelper);
3344 helper->mail_op = g_object_ref(self);
3345 helper->dest_folder = g_object_ref(folder);
3346 helper->user_callback = user_callback;
3347 helper->user_data = user_data;
3348 helper->last_total_bytes = 0;
3349 helper->sum_total_bytes = 0;
3350 helper->total_bytes = compute_message_list_size (headers, 0);
3352 /* Get account and set it into mail_operation */
3353 priv->account = modest_tny_folder_get_account (src_folder);
3354 dst_account = modest_tny_folder_get_account (folder);
3356 if (priv->account == dst_account) {
3357 /* Transfer all messages at once using the fast
3358 * method. Note that depending on the server this
3359 * might not be that fast, and might not be
3360 * user-cancellable either */
3361 helper->headers = g_object_ref (headers);
3362 helper->more_msgs = NULL;
3364 /* Transfer messages one by one so the user can cancel
3367 helper->headers = tny_simple_list_new ();
3368 helper->more_msgs = tny_list_create_iterator (headers);
3369 hdr = tny_iterator_get_current (helper->more_msgs);
3370 tny_list_append (helper->headers, hdr);
3371 g_object_unref (hdr);
3374 /* If leave_on_server is set to TRUE then don't use
3375 delete_original, we always pass FALSE. This is because
3376 otherwise tinymail will try to sync the source folder and
3377 this could cause an error if we're offline while
3378 transferring an already downloaded message from a POP
3380 account_protocol = modest_tny_account_get_protocol_type (priv->account);
3381 if (modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_protocol)) {
3382 const gchar *account_name;
3384 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (priv->account);
3385 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
3388 leave_on_server = FALSE;
3391 /* Do not delete messages if leave on server is TRUE */
3392 helper->delete = (leave_on_server) ? FALSE : delete_original;
3394 modest_mail_operation_notify_start (self);
3396 /* Start notifying progress */
3397 state = modest_mail_operation_clone_state (self);
3400 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
3401 g_slice_free (ModestMailOperationState, state);
3403 tny_folder_transfer_msgs_async (src_folder,
3408 transfer_msgs_status_cb,
3410 g_object_unref (src_folder);
3411 g_object_unref (dst_account);
3416 on_refresh_folder (TnyFolder *folder,
3421 RefreshAsyncHelper *helper = NULL;
3422 ModestMailOperation *self = NULL;
3423 ModestMailOperationPrivate *priv = NULL;
3425 helper = (RefreshAsyncHelper *) user_data;
3426 self = helper->mail_op;
3427 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3429 g_return_if_fail(priv!=NULL);
3432 priv->error = g_error_copy (error);
3433 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3438 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3439 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3440 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
3441 _("Error trying to refresh the contents of %s"),
3442 tny_folder_get_name (folder));
3446 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3449 /* Call user defined callback, if it exists */
3450 if (helper->user_callback) {
3452 /* This is not a GDK lock because we are a Tinymail callback and
3453 * Tinymail already acquires the Gdk lock */
3454 helper->user_callback (self, folder, helper->user_data);
3458 g_slice_free (RefreshAsyncHelper, helper);
3460 /* Notify about operation end */
3461 modest_mail_operation_notify_end (self);
3462 g_object_unref(self);
3466 on_refresh_folder_status_update (GObject *obj,
3470 RefreshAsyncHelper *helper = NULL;
3471 ModestMailOperation *self = NULL;
3472 ModestMailOperationPrivate *priv = NULL;
3473 ModestMailOperationState *state;
3475 g_return_if_fail (user_data != NULL);
3476 g_return_if_fail (status != NULL);
3478 /* Show only the status information we want */
3479 if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
3482 helper = (RefreshAsyncHelper *) user_data;
3483 self = helper->mail_op;
3484 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
3486 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3488 priv->done = status->position;
3489 priv->total = status->of_total;
3491 state = modest_mail_operation_clone_state (self);
3493 /* This is not a GDK lock because we are a Tinymail callback and
3494 * Tinymail already acquires the Gdk lock */
3495 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
3497 g_slice_free (ModestMailOperationState, state);
3501 modest_mail_operation_refresh_folder (ModestMailOperation *self,
3503 RefreshAsyncUserCallback user_callback,
3506 ModestMailOperationPrivate *priv = NULL;
3507 RefreshAsyncHelper *helper = NULL;
3509 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3511 /* Check memory low */
3512 if (_check_memory_low (self)) {
3514 user_callback (self, folder, user_data);
3515 /* Notify about operation end */
3516 modest_mail_operation_notify_end (self);
3520 /* Get account and set it into mail_operation */
3521 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3522 priv->account = modest_tny_folder_get_account (folder);
3523 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3525 /* Create the helper */
3526 helper = g_slice_new0 (RefreshAsyncHelper);
3527 helper->mail_op = g_object_ref(self);
3528 helper->user_callback = user_callback;
3529 helper->user_data = user_data;
3531 modest_mail_operation_notify_start (self);
3533 /* notify that the operation was started */
3534 ModestMailOperationState *state;
3535 state = modest_mail_operation_clone_state (self);
3538 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3540 g_slice_free (ModestMailOperationState, state);
3542 tny_folder_refresh_async (folder,
3544 on_refresh_folder_status_update,
3549 run_queue_notify_and_destroy (RunQueueHelper *helper,
3550 ModestMailOperationStatus status)
3552 ModestMailOperationPrivate *priv;
3555 if (helper->error_handler &&
3556 g_signal_handler_is_connected (helper->queue, helper->error_handler))
3557 g_signal_handler_disconnect (helper->queue, helper->error_handler);
3558 if (helper->start_handler &&
3559 g_signal_handler_is_connected (helper->queue, helper->start_handler))
3560 g_signal_handler_disconnect (helper->queue, helper->start_handler);
3561 if (helper->stop_handler &&
3562 g_signal_handler_is_connected (helper->queue, helper->stop_handler))
3563 g_signal_handler_disconnect (helper->queue, helper->stop_handler);
3566 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (helper->self);
3567 priv->status = status;
3570 modest_mail_operation_notify_end (helper->self);
3573 g_object_unref (helper->queue);
3574 g_object_unref (helper->self);
3575 g_slice_free (RunQueueHelper, helper);
3579 run_queue_stop (ModestTnySendQueue *queue,
3582 RunQueueHelper *helper;
3584 g_debug ("%s sending queue stopped", __FUNCTION__);
3586 helper = (RunQueueHelper *) user_data;
3587 run_queue_notify_and_destroy (helper, MODEST_MAIL_OPERATION_STATUS_SUCCESS);
3591 modest_mail_operation_run_queue (ModestMailOperation *self,
3592 ModestTnySendQueue *queue)
3594 ModestMailOperationPrivate *priv;
3595 RunQueueHelper *helper;
3597 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3598 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
3599 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3601 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3602 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
3603 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
3605 /* Create the helper */
3606 helper = g_slice_new0 (RunQueueHelper);
3607 helper->queue = g_object_ref (queue);
3608 helper->self = g_object_ref (self);
3609 helper->stop_handler = g_signal_connect (queue, "queue-stop",
3610 G_CALLBACK (run_queue_stop),
3613 /* Notify operation has started */
3614 modest_mail_operation_notify_start (self);
3615 g_debug ("%s, run queue started", __FUNCTION__);
3619 queue_wakeup_callback (ModestTnySendQueue *queue,
3624 ModestMailOperation *mail_op;
3625 ModestMailOperationPrivate *priv;
3627 mail_op = (ModestMailOperation *) userdata;
3628 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3630 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3631 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (queue));
3634 modest_mail_operation_notify_end (mail_op);
3635 g_object_unref (mail_op);
3639 modest_mail_operation_queue_wakeup (ModestMailOperation *self,
3640 ModestTnySendQueue *queue)
3642 ModestMailOperationPrivate *priv;
3644 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3645 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
3646 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3648 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3649 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
3650 priv->op_type = MODEST_MAIL_OPERATION_TYPE_QUEUE_WAKEUP;
3652 g_object_ref (self);
3654 modest_tny_send_queue_wakeup (queue, queue_wakeup_callback, self);
3655 modest_mail_operation_notify_start (self);
3659 shutdown_callback (ModestTnyAccountStore *account_store, gpointer userdata)
3661 ModestMailOperation *self = (ModestMailOperation *) userdata;
3662 ModestMailOperationPrivate *priv;
3664 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3665 g_return_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (account_store));
3666 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3668 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3670 modest_mail_operation_notify_end (self);
3671 g_object_unref (self);
3675 modest_mail_operation_shutdown (ModestMailOperation *self, ModestTnyAccountStore *account_store)
3677 ModestMailOperationPrivate *priv;
3679 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3680 g_return_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (account_store));
3681 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3683 modest_mail_operation_queue_set_running_shutdown (modest_runtime_get_mail_operation_queue ());
3685 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3686 priv->account = NULL;
3687 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SHUTDOWN;
3689 modest_mail_operation_notify_start (self);
3690 g_object_ref (self);
3691 modest_tny_account_store_shutdown (account_store, shutdown_callback, self);
3695 sync_folder_finish_callback (TnyFolder *self,
3701 ModestMailOperation *mail_op;
3702 ModestMailOperationPrivate *priv;
3704 mail_op = (ModestMailOperation *) user_data;
3705 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3707 /* If canceled by the user, ignore the error given by Tinymail */
3709 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3711 /* If the operation was a sync then the status is
3712 failed, but if it's part of another operation then
3713 just set it as finished with errors */
3714 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER)
3715 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3717 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
3718 priv->error = g_error_copy ((const GError *) err);
3719 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
3721 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3724 modest_mail_operation_notify_end (mail_op);
3725 g_object_unref (mail_op);
3729 modest_mail_operation_sync_folder (ModestMailOperation *self,
3730 TnyFolder *folder, gboolean expunge)
3732 ModestMailOperationPrivate *priv;
3734 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3735 g_return_if_fail (TNY_IS_FOLDER (folder));
3736 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3738 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3739 priv->account = modest_tny_folder_get_account (folder);
3740 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
3742 modest_mail_operation_notify_start (self);
3743 g_object_ref (self);
3744 tny_folder_sync_async (folder, expunge,
3745 (TnyFolderCallback) sync_folder_finish_callback,
3750 modest_mail_operation_notify_start (ModestMailOperation *self)
3752 ModestMailOperationPrivate *priv = NULL;
3754 g_return_if_fail (self);
3756 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3758 /* Ensure that all the fields are filled correctly */
3759 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
3761 /* Notify the observers about the mail operation. We do not
3762 wrapp this emission because we assume that this function is
3763 always called from within the main lock */
3764 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
3769 * It's used by the mail operation queue to notify the observers
3770 * attached to that signal that the operation finished. We need to use
3771 * that because tinymail does not give us the progress of a given
3772 * operation when it finishes (it directly calls the operation
3776 modest_mail_operation_notify_end (ModestMailOperation *self)
3778 ModestMailOperationPrivate *priv = NULL;
3780 g_return_if_fail (self);
3782 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3784 /* Notify the observers about the mail operation end. We do
3785 not wrapp this emission because we assume that this
3786 function is always called from within the main lock */
3787 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3789 /* Remove the error user data */
3790 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3791 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3795 modest_mail_operation_get_account (ModestMailOperation *self)
3797 ModestMailOperationPrivate *priv = NULL;
3799 g_return_val_if_fail (self, NULL);
3801 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3803 return (priv->account) ? g_object_ref (priv->account) : NULL;
3807 modest_mail_operation_noop (ModestMailOperation *self)
3809 ModestMailOperationPrivate *priv = NULL;
3811 g_return_if_fail (self);
3813 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3814 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3815 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3819 /* This mail operation does nothing actually */
3820 modest_mail_operation_notify_start (self);
3821 modest_mail_operation_notify_end (self);
3826 modest_mail_operation_to_string (ModestMailOperation *self)
3828 const gchar *type, *status, *account_id;
3829 ModestMailOperationPrivate *priv = NULL;
3831 g_return_val_if_fail (self, NULL);
3833 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3835 /* new operations don't have anything interesting */
3836 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3837 return g_strdup_printf ("%p <new operation>", self);
3839 switch (priv->op_type) {
3840 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3841 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3842 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3843 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3844 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3845 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3846 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3847 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3848 default: type = "UNEXPECTED"; break;
3851 switch (priv->status) {
3852 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3853 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3854 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3855 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3856 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3857 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3858 default: status= "UNEXPECTED"; break;
3861 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3863 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3864 priv->done, priv->total,
3865 priv->error && priv->error->message ? priv->error->message : "");
3869 * Once the mail operations were objects this will be no longer
3870 * needed. I don't like it, but we need it for the moment
3873 _check_memory_low (ModestMailOperation *mail_op)
3875 if (modest_platform_check_memory_low (NULL, FALSE)) {
3876 ModestMailOperationPrivate *priv;
3878 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3879 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3880 g_set_error (&(priv->error),
3881 MODEST_MAIL_OPERATION_ERROR,
3882 MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY,
3883 "Not enough memory to complete the operation");