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);
1285 g_object_unref(info->mailop);
1286 g_slice_free (SaveToDraftsAddMsgInfo, info);
1291 TnyTransportAccount *transport_account;
1293 SaveToDraftstCallback callback;
1298 modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self,
1302 TnyFolder *drafts = NULL;
1303 ModestMailOperationPrivate *priv = NULL;
1304 SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata;
1306 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1309 if (!(priv->error)) {
1310 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1311 MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
1312 "modest: failed to create a new msg\n");
1315 drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account),
1316 TNY_FOLDER_TYPE_DRAFTS);
1317 if (!drafts && !(priv->error)) {
1318 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1319 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1320 "modest: failed to create a new msg\n");
1324 if (!priv->error || priv->error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1326 SaveToDraftsAddMsgInfo *cb_info = g_slice_new(SaveToDraftsAddMsgInfo);
1327 cb_info->transport_account = g_object_ref(info->transport_account);
1328 cb_info->draft_msg = info->draft_msg ? g_object_ref(info->draft_msg) : NULL;
1329 cb_info->callback = info->callback;
1330 cb_info->user_data = info->user_data;
1331 cb_info->drafts = g_object_ref(drafts);
1332 cb_info->msg = g_object_ref(msg);
1333 cb_info->mailop = g_object_ref(self);
1334 tny_folder_add_msg_async(drafts, msg, modest_mail_operation_save_to_drafts_add_msg_cb,
1338 /* Call the user callback */
1339 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1341 info->callback (self, msg, info->user_data);
1342 modest_mail_operation_notify_end (self);
1346 g_object_unref (G_OBJECT(drafts));
1347 if (info->draft_msg)
1348 g_object_unref (G_OBJECT (info->draft_msg));
1349 if (info->transport_account)
1350 g_object_unref (G_OBJECT(info->transport_account));
1351 g_slice_free (SaveToDraftsInfo, info);
1355 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
1356 TnyTransportAccount *transport_account,
1358 const gchar *from, const gchar *to,
1359 const gchar *cc, const gchar *bcc,
1360 const gchar *subject, const gchar *plain_body,
1361 const gchar *html_body,
1362 const GList *attachments_list,
1363 const GList *images_list,
1364 TnyHeaderFlags priority_flags,
1365 const gchar *references,
1366 const gchar *in_reply_to,
1367 SaveToDraftstCallback callback,
1370 ModestMailOperationPrivate *priv = NULL;
1371 SaveToDraftsInfo *info = NULL;
1373 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1374 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
1376 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1378 /* Get account and set it into mail_operation */
1379 priv->account = g_object_ref (transport_account);
1380 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
1382 info = g_slice_new0 (SaveToDraftsInfo);
1383 info->transport_account = g_object_ref (transport_account);
1384 info->draft_msg = (draft_msg) ? g_object_ref (draft_msg) : NULL;
1385 info->callback = callback;
1386 info->user_data = user_data;
1388 g_debug ("--- CREATE MESSAGE");
1389 modest_mail_operation_notify_start (self);
1390 modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body,
1391 attachments_list, images_list, priority_flags,
1392 references, in_reply_to,
1393 modest_mail_operation_save_to_drafts_cb, info);
1398 ModestMailOperation *mail_op;
1399 TnyMimePart *mime_part;
1401 GetMimePartSizeCallback callback;
1403 } GetMimePartSizeInfo;
1405 /***** I N T E R N A L F O L D E R O B S E R V E R *****/
1406 /* We use this folder observer to track the headers that have been
1407 * added to a folder */
1410 TnyList *new_headers;
1411 } InternalFolderObserver;
1414 GObjectClass parent;
1415 } InternalFolderObserverClass;
1417 static void tny_folder_observer_init (TnyFolderObserverIface *idace);
1419 G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
1420 internal_folder_observer,
1422 G_IMPLEMENT_INTERFACE(TNY_TYPE_FOLDER_OBSERVER, tny_folder_observer_init));
1426 foreach_add_item (gpointer header, gpointer user_data)
1428 tny_list_append (TNY_LIST (user_data), G_OBJECT (header));
1431 /* This is the method that looks for new messages in a folder */
1433 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
1435 InternalFolderObserver *derived = (InternalFolderObserver *)self;
1437 TnyFolderChangeChanged changed;
1439 changed = tny_folder_change_get_changed (change);
1441 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1444 /* Get added headers */
1445 list = tny_simple_list_new ();
1446 tny_folder_change_get_added_headers (change, list);
1448 /* Add them to the folder observer */
1449 tny_list_foreach (list, foreach_add_item,
1450 derived->new_headers);
1452 g_object_unref (G_OBJECT (list));
1457 internal_folder_observer_init (InternalFolderObserver *self)
1459 self->new_headers = tny_simple_list_new ();
1462 internal_folder_observer_finalize (GObject *object)
1464 InternalFolderObserver *self;
1466 self = (InternalFolderObserver *) object;
1467 g_object_unref (self->new_headers);
1469 G_OBJECT_CLASS (internal_folder_observer_parent_class)->finalize (object);
1472 tny_folder_observer_init (TnyFolderObserverIface *iface)
1474 iface->update = internal_folder_observer_update;
1477 internal_folder_observer_class_init (InternalFolderObserverClass *klass)
1479 GObjectClass *object_class;
1481 internal_folder_observer_parent_class = g_type_class_peek_parent (klass);
1482 object_class = (GObjectClass*) klass;
1483 object_class->finalize = internal_folder_observer_finalize;
1487 destroy_update_account_info (UpdateAccountInfo *info)
1489 g_free (info->account_name);
1490 g_object_unref (info->folders);
1491 g_object_unref (info->mail_op);
1492 g_slice_free (UpdateAccountInfo, info);
1497 update_account_send_mail (UpdateAccountInfo *info)
1499 TnyTransportAccount *transport_account = NULL;
1500 ModestTnyAccountStore *account_store;
1502 account_store = modest_runtime_get_account_store ();
1504 /* We don't try to send messages while sending mails is blocked */
1505 if (modest_tny_account_store_is_send_mail_blocked (account_store))
1508 /* Get the transport account */
1509 transport_account = (TnyTransportAccount *)
1510 modest_tny_account_store_get_server_account (account_store, info->account_name,
1511 TNY_ACCOUNT_TYPE_TRANSPORT);
1513 if (transport_account) {
1514 ModestTnySendQueue *send_queue;
1518 send_queue = modest_runtime_get_send_queue (transport_account, TRUE);
1519 g_object_unref (transport_account);
1521 if (TNY_IS_SEND_QUEUE (send_queue)) {
1522 /* Get outbox folder */
1523 outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue));
1524 if (outbox) { /* this could fail in some cases */
1525 num_messages = tny_folder_get_all_count (outbox);
1526 g_object_unref (outbox);
1528 g_warning ("%s: could not get outbox", __FUNCTION__);
1532 if (num_messages != 0) {
1533 ModestMailOperation *mail_op;
1534 /* Reenable suspended items */
1535 mail_op = modest_mail_operation_new (NULL);
1536 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1538 modest_mail_operation_queue_wakeup (mail_op, MODEST_TNY_SEND_QUEUE (send_queue));
1541 modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue),
1549 update_account_get_msg_async_cb (TnyFolder *folder,
1555 GetMsgInfo *msg_info = (GetMsgInfo *) user_data;
1556 ModestMailOperationPrivate *priv;
1558 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (msg_info->mail_op);
1561 if (TNY_IS_MSG (msg)) {
1562 TnyHeader *header = tny_msg_get_header (msg);
1565 ModestMailOperationState *state;
1566 state = modest_mail_operation_clone_state (msg_info->mail_op);
1567 msg_info->sum_total_bytes += tny_header_get_message_size (header);
1568 state->bytes_done = msg_info->sum_total_bytes;
1569 state->bytes_total = msg_info->total_bytes;
1571 /* Notify the status change. Only notify about changes
1572 referred to bytes */
1573 g_signal_emit (G_OBJECT (msg_info->mail_op),
1574 signals[PROGRESS_CHANGED_SIGNAL],
1577 g_object_unref (header);
1578 g_slice_free (ModestMailOperationState, state);
1582 if (priv->done == priv->total) {
1583 TnyList *new_headers;
1584 UpdateAccountInfo *info;
1586 /* After getting all the messages send the ones in the
1588 info = (UpdateAccountInfo *) msg_info->user_data;
1589 update_account_send_mail (info);
1591 /* Check if the operation was a success */
1593 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1595 /* Call the user callback and free */
1596 new_headers = tny_iterator_get_list (msg_info->more_msgs);
1597 update_account_notify_user_and_free (info, new_headers);
1598 g_object_unref (new_headers);
1600 /* Delete the helper */
1601 g_object_unref (msg_info->more_msgs);
1602 g_object_unref (msg_info->mail_op);
1603 g_slice_free (GetMsgInfo, msg_info);
1608 update_account_notify_user_and_free (UpdateAccountInfo *info,
1609 TnyList *new_headers)
1611 /* Set the account back to not busy */
1612 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (),
1613 info->account_name, FALSE);
1617 info->callback (info->mail_op, new_headers, info->user_data);
1619 /* Mail operation end */
1620 modest_mail_operation_notify_end (info->mail_op);
1624 g_object_unref (new_headers);
1625 destroy_update_account_info (info);
1629 inbox_refreshed_cb (TnyFolder *inbox,
1634 UpdateAccountInfo *info;
1635 ModestMailOperationPrivate *priv;
1636 TnyIterator *new_headers_iter;
1637 GPtrArray *new_headers_array = NULL;
1638 gint max_size, retrieve_limit, i;
1639 ModestAccountMgr *mgr;
1640 ModestAccountRetrieveType retrieve_type;
1641 TnyList *new_headers = NULL;
1642 gboolean headers_only, ignore_limit;
1643 time_t time_to_store;
1645 info = (UpdateAccountInfo *) user_data;
1646 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1647 mgr = modest_runtime_get_account_mgr ();
1649 if (canceled || err) {
1650 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1652 priv->error = g_error_copy (err);
1654 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1655 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1659 tny_folder_remove_observer (inbox, info->inbox_observer);
1660 g_object_unref (info->inbox_observer);
1661 info->inbox_observer = NULL;
1663 /* Notify the user about the error and then exit */
1664 update_account_notify_user_and_free (info, NULL);
1669 /* Try to send anyway */
1673 /* Set the last updated as the current time */
1674 #ifdef MODEST_USE_LIBTIME
1676 time_get_utc (&utc_tm);
1677 time_to_store = time_mktime (&utc_tm, "GMT");
1679 time_to_store = time (NULL);
1681 modest_account_mgr_set_last_updated (mgr, tny_account_get_id (priv->account), time_to_store);
1683 /* Get the message max size */
1684 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1685 MODEST_CONF_MSG_SIZE_LIMIT, NULL);
1687 max_size = G_MAXINT;
1689 max_size = max_size * KB;
1691 /* Create the new headers array. We need it to sort the
1692 new headers by date */
1693 new_headers_array = g_ptr_array_new ();
1694 if (info->inbox_observer) {
1695 new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_observer)->new_headers);
1696 while (!tny_iterator_is_done (new_headers_iter)) {
1697 TnyHeader *header = NULL;
1699 header = TNY_HEADER (tny_iterator_get_current (new_headers_iter));
1700 /* Apply per-message size limits */
1701 if (tny_header_get_message_size (header) < max_size)
1702 g_ptr_array_add (new_headers_array, g_object_ref (header));
1704 g_object_unref (header);
1705 tny_iterator_next (new_headers_iter);
1707 g_object_unref (new_headers_iter);
1709 tny_folder_remove_observer (inbox, info->inbox_observer);
1710 g_object_unref (info->inbox_observer);
1711 info->inbox_observer = NULL;
1714 if (new_headers_array->len == 0) {
1715 g_ptr_array_free (new_headers_array, FALSE);
1719 /* Get per-account message amount retrieval limit */
1720 retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name);
1721 if (retrieve_limit == 0)
1722 retrieve_limit = G_MAXINT;
1724 /* Get per-account retrieval type */
1725 retrieve_type = modest_account_mgr_get_retrieve_type (mgr, info->account_name);
1726 headers_only = (retrieve_type == MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY);
1729 g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date);
1731 /* Ask the users if they want to retrieve all the messages
1732 even though the limit was exceeded */
1733 ignore_limit = FALSE;
1734 if (new_headers_array->len > retrieve_limit) {
1735 /* Ask the user if a callback has been specified and
1736 if the mail operation has a source (this means that
1737 was invoked by the user and not automatically by a
1739 if (info->retrieve_all_cb && info->interactive)
1740 ignore_limit = info->retrieve_all_cb (priv->source,
1741 new_headers_array->len,
1745 /* Copy the headers to a list and free the array */
1746 new_headers = tny_simple_list_new ();
1747 for (i=0; i < new_headers_array->len; i++) {
1748 TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i));
1749 /* We want the first element to be the most recent
1750 one, that's why we reverse the list */
1751 tny_list_prepend (new_headers, G_OBJECT (header));
1753 g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL);
1754 g_ptr_array_free (new_headers_array, FALSE);
1756 if (!headers_only && (tny_list_get_length (new_headers) > 0)) {
1759 GetMsgInfo *msg_info;
1763 priv->total = tny_list_get_length (new_headers);
1765 priv->total = MIN (tny_list_get_length (new_headers), retrieve_limit);
1767 iter = tny_list_create_iterator (new_headers);
1769 /* Create the message info */
1770 msg_info = g_slice_new0 (GetMsgInfo);
1771 msg_info->mail_op = g_object_ref (info->mail_op);
1772 msg_info->total_bytes = compute_message_list_size (new_headers, priv->total);
1773 msg_info->more_msgs = g_object_ref (iter);
1774 msg_info->user_data = info;
1776 while ((msg_num < priv->total ) && !tny_iterator_is_done (iter)) {
1777 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1778 TnyFolder *folder = tny_header_get_folder (header);
1780 /* Get message in an async way */
1781 tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb,
1784 g_object_unref (folder);
1787 tny_iterator_next (iter);
1789 g_object_unref (iter);
1791 /* The mail operation will finish when the last
1792 message is retrieved */
1796 /* If we don't have to retrieve the new messages then
1798 update_account_send_mail (info);
1800 /* Check if the operation was a success */
1802 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1804 /* Call the user callback and free */
1805 update_account_notify_user_and_free (info, new_headers);
1809 inbox_refresh_status_update (GObject *obj,
1813 UpdateAccountInfo *info = NULL;
1814 ModestMailOperation *self = NULL;
1815 ModestMailOperationPrivate *priv = NULL;
1816 ModestMailOperationState *state;
1818 g_return_if_fail (user_data != NULL);
1819 g_return_if_fail (status != NULL);
1821 /* Show only the status information we want */
1822 if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
1825 info = (UpdateAccountInfo *) user_data;
1826 self = info->mail_op;
1827 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
1829 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1831 priv->done = status->position;
1832 priv->total = status->of_total;
1834 state = modest_mail_operation_clone_state (self);
1836 /* This is not a GDK lock because we are a Tinymail callback and
1837 * Tinymail already acquires the Gdk lock */
1838 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
1840 g_slice_free (ModestMailOperationState, state);
1844 recurse_folders_async_cb (TnyFolderStore *folder_store,
1850 UpdateAccountInfo *info;
1851 ModestMailOperationPrivate *priv;
1853 info = (UpdateAccountInfo *) user_data;
1854 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1856 if (err || canceled) {
1857 /* If the error was previosly set by another callback
1858 don't set it again */
1860 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1862 priv->error = g_error_copy (err);
1864 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1865 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
1869 /* We're not getting INBOX children if we don't want to poke all */
1870 TnyIterator *iter = tny_list_create_iterator (list);
1871 while (!tny_iterator_is_done (iter)) {
1872 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
1874 /* Add to the list of all folders */
1875 tny_list_append (info->folders, (GObject *) folder);
1877 if (info->poke_all) {
1878 TnyList *folders = tny_simple_list_new ();
1879 /* Add pending call */
1880 info->pending_calls++;
1882 tny_folder_store_get_folders_async (folder, folders, NULL, FALSE,
1883 recurse_folders_async_cb,
1885 g_object_unref (folders);
1888 g_object_unref (G_OBJECT (folder));
1890 tny_iterator_next (iter);
1892 g_object_unref (G_OBJECT (iter));
1895 /* Remove my own pending call */
1896 info->pending_calls--;
1898 /* This means that we have all the folders */
1899 if (info->pending_calls == 0) {
1900 TnyIterator *iter_all_folders;
1901 TnyFolder *inbox = NULL;
1903 /* If there was any error do not continue */
1905 update_account_notify_user_and_free (info, NULL);
1909 iter_all_folders = tny_list_create_iterator (info->folders);
1911 /* Do a poke status over all folders */
1912 while (!tny_iterator_is_done (iter_all_folders) &&
1913 priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
1914 TnyFolder *folder = NULL;
1916 folder = TNY_FOLDER (tny_iterator_get_current (iter_all_folders));
1918 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
1919 /* Get a reference to the INBOX */
1920 inbox = g_object_ref (folder);
1922 /* Issue a poke status over the folder */
1924 tny_folder_poke_status (folder);
1927 /* Free and go to next */
1928 g_object_unref (folder);
1929 tny_iterator_next (iter_all_folders);
1931 g_object_unref (iter_all_folders);
1933 /* Refresh the INBOX */
1935 /* Refresh the folder. Our observer receives
1936 * the new emails during folder refreshes, so
1937 * we can use observer->new_headers
1939 info->inbox_observer = g_object_new (internal_folder_observer_get_type (), NULL);
1940 tny_folder_add_observer (inbox, info->inbox_observer);
1942 /* Refresh the INBOX */
1943 tny_folder_refresh_async (inbox, inbox_refreshed_cb, inbox_refresh_status_update, info);
1944 g_object_unref (inbox);
1946 /* We could not perform the inbox refresh but
1947 we'll try to send mails anyway */
1948 inbox_refreshed_cb (inbox, FALSE, NULL, info);
1954 modest_mail_operation_update_account (ModestMailOperation *self,
1955 const gchar *account_name,
1957 gboolean interactive,
1958 RetrieveAllCallback retrieve_all_cb,
1959 UpdateAccountCallback callback,
1962 UpdateAccountInfo *info = NULL;
1963 ModestMailOperationPrivate *priv = NULL;
1964 ModestTnyAccountStore *account_store = NULL;
1966 ModestMailOperationState *state;
1968 /* Init mail operation */
1969 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1972 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1973 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE;
1975 /* Get the store account */
1976 account_store = modest_runtime_get_account_store ();
1978 modest_tny_account_store_get_server_account (account_store,
1980 TNY_ACCOUNT_TYPE_STORE);
1982 /* The above function could return NULL */
1983 if (!priv->account) {
1984 /* Check if the operation was a success */
1985 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1986 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1988 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1990 /* Call the user callback */
1992 callback (self, NULL, user_data);
1994 /* Notify about operation end */
1995 modest_mail_operation_notify_end (self);
2000 /* We have once seen priv->account getting finalized during this code,
2001 * therefore adding a reference (bug #82296) */
2003 g_object_ref (priv->account);
2005 /* Create the helper object */
2006 info = g_slice_new0 (UpdateAccountInfo);
2007 info->pending_calls = 1;
2008 info->folders = tny_simple_list_new ();
2009 info->mail_op = g_object_ref (self);
2010 info->poke_all = poke_all;
2011 info->interactive = interactive;
2012 info->account_name = g_strdup (account_name);
2013 info->callback = callback;
2014 info->user_data = user_data;
2015 info->retrieve_all_cb = retrieve_all_cb;
2017 /* Set account busy */
2018 modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr (), account_name, TRUE);
2019 modest_mail_operation_notify_start (self);
2021 /* notify about the start of the operation */
2022 state = modest_mail_operation_clone_state (self);
2026 /* Start notifying progress */
2027 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2028 g_slice_free (ModestMailOperationState, state);
2030 /* Get all folders and continue in the callback */
2031 folders = tny_simple_list_new ();
2032 tny_folder_store_get_folders_async (TNY_FOLDER_STORE (priv->account),
2033 folders, NULL, FALSE,
2034 recurse_folders_async_cb,
2036 g_object_unref (folders);
2038 g_object_unref (priv->account);
2043 * Used to notify the queue from the main
2044 * loop. We call it inside an idle call to achieve that
2047 idle_notify_queue (gpointer data)
2049 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
2051 gdk_threads_enter ();
2052 modest_mail_operation_notify_end (mail_op);
2053 gdk_threads_leave ();
2054 g_object_unref (mail_op);
2060 compare_headers_by_date (gconstpointer a,
2063 TnyHeader **header1, **header2;
2064 time_t sent1, sent2;
2066 header1 = (TnyHeader **) a;
2067 header2 = (TnyHeader **) b;
2069 sent1 = tny_header_get_date_sent (*header1);
2070 sent2 = tny_header_get_date_sent (*header2);
2072 /* We want the most recent ones (greater time_t) at the
2081 /* ******************************************************************* */
2082 /* ************************** STORE ACTIONS ************************* */
2083 /* ******************************************************************* */
2086 ModestMailOperation *mail_op;
2087 CreateFolderUserCallback callback;
2093 create_folder_cb (TnyFolderStore *parent_folder,
2095 TnyFolder *new_folder,
2099 ModestMailOperationPrivate *priv;
2100 CreateFolderInfo *info;
2102 info = (CreateFolderInfo *) user_data;
2103 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2105 if (canceled || err) {
2106 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2108 priv->error = g_error_copy (err);
2110 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2111 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2114 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2117 /* The user will unref the new_folder */
2119 info->callback (info->mail_op, parent_folder,
2120 new_folder, info->user_data);
2122 /* Notify about operation end */
2123 modest_mail_operation_notify_end (info->mail_op);
2126 g_object_unref (info->mail_op);
2127 g_slice_free (CreateFolderInfo, info);
2131 modest_mail_operation_create_folder (ModestMailOperation *self,
2132 TnyFolderStore *parent,
2134 CreateFolderUserCallback callback,
2137 ModestMailOperationPrivate *priv;
2139 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2140 g_return_if_fail (name);
2142 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2143 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2144 priv->account = (TNY_IS_ACCOUNT (parent)) ?
2145 g_object_ref (parent) :
2146 modest_tny_folder_get_account (TNY_FOLDER (parent));
2148 /* Check for already existing folder */
2149 if (modest_tny_folder_has_subfolder_with_name (parent, name, TRUE)) {
2150 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2151 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2152 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2153 _CS("ckdg_ib_folder_already_exists"));
2157 if (TNY_IS_FOLDER (parent)) {
2158 /* Check folder rules */
2159 ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2160 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
2161 /* Set status failed and set an error */
2162 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2163 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2164 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2165 _("mail_in_ui_folder_create_error"));
2169 if (!priv->error && (!strcmp (name, " ") || strchr (name, '/'))) {
2170 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2171 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2172 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2173 _("mail_in_ui_folder_create_error"));
2177 CreateFolderInfo *info;
2179 info = g_slice_new0 (CreateFolderInfo);
2180 info->mail_op = g_object_ref (self);
2181 info->callback = callback;
2182 info->user_data = user_data;
2184 modest_mail_operation_notify_start (self);
2186 /* Create the folder */
2187 tny_folder_store_create_folder_async (parent, name, create_folder_cb,
2190 /* Call the user callback anyway */
2192 callback (self, parent, NULL, user_data);
2193 /* Notify about operation end */
2194 modest_mail_operation_notify_end (self);
2199 modest_mail_operation_remove_folder (ModestMailOperation *self,
2201 gboolean remove_to_trash)
2203 ModestMailOperationPrivate *priv;
2204 ModestTnyFolderRules rules;
2206 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2207 g_return_if_fail (TNY_IS_FOLDER (folder));
2209 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2211 /* Check folder rules */
2212 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2213 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
2214 /* Set status failed and set an error */
2215 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2216 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2217 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2218 _("mail_in_ui_folder_delete_error"));
2222 /* Get the account */
2223 priv->account = modest_tny_folder_get_account (folder);
2224 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
2226 /* Delete folder or move to trash */
2227 if (remove_to_trash) {
2228 TnyFolder *trash_folder = NULL;
2229 trash_folder = modest_tny_account_get_special_folder (priv->account,
2230 TNY_FOLDER_TYPE_TRASH);
2231 /* TODO: error_handling */
2233 modest_mail_operation_notify_start (self);
2234 modest_mail_operation_xfer_folder (self, folder,
2235 TNY_FOLDER_STORE (trash_folder),
2237 g_object_unref (trash_folder);
2239 g_warning ("%s: modest_tny_account_get_special_folder(..) returned a NULL trash folder", __FUNCTION__);
2242 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
2244 modest_mail_operation_notify_start (self);
2245 tny_folder_store_remove_folder (parent, folder, &(priv->error));
2246 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
2249 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2251 g_object_unref (parent);
2253 g_warning ("%s: could not get parent folder", __FUNCTION__);
2257 /* Notify about operation end */
2258 modest_mail_operation_notify_end (self);
2262 transfer_folder_status_cb (GObject *obj,
2266 ModestMailOperation *self;
2267 ModestMailOperationPrivate *priv;
2268 ModestMailOperationState *state;
2269 XFerFolderAsyncHelper *helper;
2271 g_return_if_fail (status != NULL);
2273 /* Show only the status information we want */
2274 if (status->code != TNY_FOLDER_STATUS_CODE_COPY_FOLDER)
2277 helper = (XFerFolderAsyncHelper *) user_data;
2278 g_return_if_fail (helper != NULL);
2280 self = helper->mail_op;
2281 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2283 priv->done = status->position;
2284 priv->total = status->of_total;
2286 state = modest_mail_operation_clone_state (self);
2288 /* This is not a GDK lock because we are a Tinymail callback
2289 * which is already GDK locked by Tinymail */
2291 /* no gdk_threads_enter (), CHECKED */
2293 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
2295 /* no gdk_threads_leave (), CHECKED */
2297 g_slice_free (ModestMailOperationState, state);
2301 transfer_folder_cb (TnyFolder *folder,
2303 TnyFolderStore *into,
2304 TnyFolder *new_folder,
2308 XFerFolderAsyncHelper *helper;
2309 ModestMailOperation *self = NULL;
2310 ModestMailOperationPrivate *priv = NULL;
2312 helper = (XFerFolderAsyncHelper *) user_data;
2313 g_return_if_fail (helper != NULL);
2315 self = helper->mail_op;
2316 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
2319 priv->error = g_error_copy (err);
2321 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2322 } else if (cancelled) {
2323 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2324 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2325 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
2326 _("Transference of %s was cancelled."),
2327 tny_folder_get_name (folder));
2330 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2333 /* Update state of new folder */
2335 tny_folder_refresh_async (new_folder, NULL, NULL, NULL);
2336 tny_folder_poke_status (new_folder);
2339 /* Notify about operation end */
2340 modest_mail_operation_notify_end (self);
2342 /* If user defined callback function was defined, call it */
2343 if (helper->user_callback) {
2345 /* This is not a GDK lock because we are a Tinymail callback
2346 * which is already GDK locked by Tinymail */
2348 /* no gdk_threads_enter (), CHECKED */
2349 helper->user_callback (self, new_folder, helper->user_data);
2350 /* no gdk_threads_leave () , CHECKED */
2354 g_object_unref (helper->mail_op);
2355 g_slice_free (XFerFolderAsyncHelper, helper);
2360 * This function checks if the new name is a valid name for our local
2361 * folders account. The new name could not be the same than then name
2362 * of any of the mandatory local folders
2364 * We can not rely on tinymail because tinymail does not check the
2365 * name of the virtual folders that the account could have in the case
2366 * that we're doing a rename (because it directly calls Camel which
2367 * knows nothing about our virtual folders).
2369 * In the case of an actual copy/move (i.e. move/copy a folder between
2370 * accounts) tinymail uses the tny_folder_store_create_account which
2371 * is reimplemented by our ModestTnyLocalFoldersAccount that indeed
2372 * checks the new name of the folder, so this call in that case
2373 * wouldn't be needed. *But* NOTE that if tinymail changes its
2374 * implementation (if folder transfers within the same account is no
2375 * longer implemented as a rename) this call will allow Modest to work
2378 * If the new name is not valid, this function will set the status to
2379 * failed and will set also an error in the mail operation
2382 new_name_valid_if_local_account (ModestMailOperationPrivate *priv,
2383 TnyFolderStore *into,
2384 const gchar *new_name)
2386 if (TNY_IS_ACCOUNT (into) &&
2387 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (into)) &&
2388 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (into),
2390 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2391 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2392 MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS,
2393 _CS("ckdg_ib_folder_already_exists"));
2400 modest_mail_operation_xfer_folder (ModestMailOperation *self,
2402 TnyFolderStore *parent,
2403 gboolean delete_original,
2404 XferFolderAsyncUserCallback user_callback,
2407 ModestMailOperationPrivate *priv = NULL;
2408 ModestTnyFolderRules parent_rules = 0, rules;
2409 XFerFolderAsyncHelper *helper = NULL;
2410 const gchar *folder_name = NULL;
2411 const gchar *error_msg;
2413 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2414 g_return_if_fail (TNY_IS_FOLDER (folder));
2415 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
2417 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2418 folder_name = tny_folder_get_name (folder);
2420 /* Set the error msg */
2421 error_msg = _("mail_in_ui_folder_move_target_error");
2423 /* Get account and set it into mail_operation */
2424 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2425 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2426 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2428 /* Get folder rules */
2429 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2430 if (TNY_IS_FOLDER (parent))
2431 parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
2433 /* Apply operation constraints */
2434 if ((gpointer) parent == (gpointer) folder ||
2435 (!TNY_IS_FOLDER_STORE (parent)) ||
2436 (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
2439 } else if (TNY_IS_FOLDER (parent) &&
2440 (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
2444 } else if (TNY_IS_FOLDER (parent) &&
2445 TNY_IS_FOLDER_STORE (folder) &&
2446 modest_tny_folder_is_ancestor (TNY_FOLDER (parent),
2447 TNY_FOLDER_STORE (folder))) {
2448 /* Do not move a parent into a child */
2450 } else if (TNY_IS_FOLDER_STORE (parent) &&
2451 modest_tny_folder_has_subfolder_with_name (parent, folder_name, TRUE)) {
2452 /* Check that the new folder name is not used by any
2455 } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) {
2456 /* Check that the new folder name is not used by any
2457 special local folder */
2460 /* Create the helper */
2461 helper = g_slice_new0 (XFerFolderAsyncHelper);
2462 helper->mail_op = g_object_ref (self);
2463 helper->user_callback = user_callback;
2464 helper->user_data = user_data;
2466 /* Move/Copy folder */
2467 modest_mail_operation_notify_start (self);
2468 tny_folder_copy_async (folder,
2470 tny_folder_get_name (folder),
2473 transfer_folder_status_cb,
2479 /* Set status failed and set an error */
2480 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2481 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2482 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2485 /* Call the user callback if exists */
2487 user_callback (self, NULL, user_data);
2489 /* Notify the queue */
2490 modest_mail_operation_notify_end (self);
2494 modest_mail_operation_rename_folder (ModestMailOperation *self,
2497 XferFolderAsyncUserCallback user_callback,
2500 ModestMailOperationPrivate *priv;
2501 ModestTnyFolderRules rules;
2502 XFerFolderAsyncHelper *helper;
2504 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2505 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
2506 g_return_if_fail (name);
2508 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2510 /* Get account and set it into mail_operation */
2511 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2512 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
2514 /* Check folder rules */
2515 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
2516 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
2518 } else if (!strcmp (name, " ") || strchr (name, '/')) {
2521 TnyFolderStore *into;
2523 into = tny_folder_get_folder_store (folder);
2525 /* Check that the new folder name is not used by any
2526 special local folder */
2527 if (new_name_valid_if_local_account (priv, into, name)) {
2528 /* Create the helper */
2529 helper = g_slice_new0 (XFerFolderAsyncHelper);
2530 helper->mail_op = g_object_ref(self);
2531 helper->user_callback = user_callback;
2532 helper->user_data = user_data;
2534 /* Rename. Camel handles folder subscription/unsubscription */
2535 modest_mail_operation_notify_start (self);
2536 tny_folder_copy_async (folder, into, name, TRUE,
2538 transfer_folder_status_cb,
2540 g_object_unref (into);
2542 g_object_unref (into);
2549 /* Set status failed and set an error */
2550 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
2551 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2552 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
2553 _("FIXME: unable to rename"));
2556 user_callback (self, NULL, user_data);
2558 /* Notify about operation end */
2559 modest_mail_operation_notify_end (self);
2562 /* ******************************************************************* */
2563 /* ************************** MSG ACTIONS ************************* */
2564 /* ******************************************************************* */
2567 modest_mail_operation_find_msg (ModestMailOperation *self,
2569 const gchar *msg_uid,
2570 gboolean progress_feedback,
2571 GetMsgAsyncUserCallback user_callback,
2574 GetMsgInfo *helper = NULL;
2575 ModestMailOperationPrivate *priv;
2577 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2578 g_return_if_fail (msg_uid != NULL);
2580 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2581 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2585 /* Check memory low */
2586 if (_check_memory_low (self)) {
2588 user_callback (self, NULL, FALSE, NULL, priv->error, user_data);
2589 modest_mail_operation_notify_end (self);
2593 /* Get account and set it into mail_operation */
2594 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2596 /* Check for cached messages */
2597 if (progress_feedback) {
2598 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2600 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
2603 /* Create the helper */
2604 helper = g_slice_new0 (GetMsgInfo);
2605 helper->header = NULL;
2606 helper->mail_op = g_object_ref (self);
2607 helper->user_callback = user_callback;
2608 helper->user_data = user_data;
2609 helper->destroy_notify = NULL;
2610 helper->last_total_bytes = 0;
2611 helper->sum_total_bytes = 0;
2612 helper->total_bytes = 0;
2613 helper->more_msgs = NULL;
2615 modest_mail_operation_notify_start (self);
2617 /* notify about the start of the operation */
2618 ModestMailOperationState *state;
2619 state = modest_mail_operation_clone_state (self);
2622 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2624 g_slice_free (ModestMailOperationState, state);
2626 tny_folder_find_msg_async (folder, msg_uid, get_msg_async_cb, get_msg_status_cb, helper);
2630 modest_mail_operation_get_msg (ModestMailOperation *self,
2632 gboolean progress_feedback,
2633 GetMsgAsyncUserCallback user_callback,
2636 GetMsgInfo *helper = NULL;
2638 ModestMailOperationPrivate *priv;
2640 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2641 g_return_if_fail (TNY_IS_HEADER (header));
2643 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2644 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2648 /* Check memory low */
2649 if (_check_memory_low (self)) {
2651 user_callback (self, header, FALSE, NULL, priv->error, user_data);
2652 modest_mail_operation_notify_end (self);
2656 /* Get account and set it into mail_operation */
2657 folder = tny_header_get_folder (header);
2658 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2660 /* Check for cached messages */
2661 if (progress_feedback) {
2662 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)
2663 priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
2665 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
2667 priv->op_type = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
2670 /* Create the helper */
2671 helper = g_slice_new0 (GetMsgInfo);
2672 helper->header = g_object_ref (header);
2673 helper->mail_op = g_object_ref (self);
2674 helper->user_callback = user_callback;
2675 helper->user_data = user_data;
2676 helper->destroy_notify = NULL;
2677 helper->last_total_bytes = 0;
2678 helper->sum_total_bytes = 0;
2679 helper->total_bytes = tny_header_get_message_size (header);
2680 helper->more_msgs = NULL;
2682 modest_mail_operation_notify_start (self);
2684 /* notify about the start of the operation */
2685 ModestMailOperationState *state;
2686 state = modest_mail_operation_clone_state (self);
2689 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2691 g_slice_free (ModestMailOperationState, state);
2693 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, helper);
2695 g_object_unref (G_OBJECT (folder));
2699 get_msg_status_cb (GObject *obj,
2703 GetMsgInfo *helper = NULL;
2705 g_return_if_fail (status != NULL);
2707 /* Show only the status information we want */
2708 if (status->code != TNY_FOLDER_STATUS_CODE_GET_MSG)
2711 helper = (GetMsgInfo *) user_data;
2712 g_return_if_fail (helper != NULL);
2714 /* Notify progress */
2715 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
2716 &(helper->sum_total_bytes), helper->total_bytes, FALSE);
2720 get_msg_async_cb (TnyFolder *folder,
2726 GetMsgInfo *info = NULL;
2727 ModestMailOperationPrivate *priv = NULL;
2730 info = (GetMsgInfo *) user_data;
2732 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
2735 if (info->more_msgs) {
2736 tny_iterator_next (info->more_msgs);
2737 finished = (tny_iterator_is_done (info->more_msgs));
2739 finished = (priv->done == priv->total) ? TRUE : FALSE;
2742 /* If canceled by the user, ignore the error given by Tinymail */
2746 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2748 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2749 priv->error = g_error_copy ((const GError *) err);
2751 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2753 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
2754 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2757 } else if (finished && priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS) {
2758 /* Set the success status before calling the user callback */
2759 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
2762 if (info->header == NULL && msg)
2763 info->header = tny_msg_get_header (msg);
2765 /* Call the user callback */
2766 if (info->user_callback)
2767 info->user_callback (info->mail_op, info->header, canceled,
2768 msg, err, info->user_data);
2770 /* Notify about operation end if this is the last callback */
2772 /* Free user data */
2773 if (info->destroy_notify)
2774 info->destroy_notify (info->user_data);
2776 /* Notify about operation end */
2777 modest_mail_operation_notify_end (info->mail_op);
2780 if (info->more_msgs)
2781 g_object_unref (info->more_msgs);
2783 g_object_unref (info->header);
2784 g_object_unref (info->mail_op);
2785 g_slice_free (GetMsgInfo, info);
2786 } else if (info->more_msgs) {
2787 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (info->more_msgs));
2788 TnyFolder *folder = tny_header_get_folder (header);
2790 g_object_unref (info->header);
2791 info->header = g_object_ref (header);
2793 /* Retrieve the next message */
2794 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, info);
2796 g_object_unref (header);
2797 g_object_unref (folder);
2799 g_warning ("%s: finished != TRUE but no messages left", __FUNCTION__);
2804 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
2805 TnyList *header_list,
2806 GetMsgAsyncUserCallback user_callback,
2808 GDestroyNotify notify)
2810 ModestMailOperationPrivate *priv = NULL;
2812 TnyIterator *iter = NULL;
2813 gboolean has_uncached_messages;
2815 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2817 /* Init mail operation */
2818 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2819 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
2821 priv->total = tny_list_get_length(header_list);
2823 /* Check memory low */
2824 if (_check_memory_low (self)) {
2825 if (user_callback) {
2826 TnyHeader *header = NULL;
2829 if (tny_list_get_length (header_list) > 0) {
2830 iter = tny_list_create_iterator (header_list);
2831 header = (TnyHeader *) tny_iterator_get_current (iter);
2832 g_object_unref (iter);
2834 user_callback (self, header, FALSE, NULL, priv->error, user_data);
2836 g_object_unref (header);
2840 /* Notify about operation end */
2841 modest_mail_operation_notify_end (self);
2845 /* Check uncached messages */
2846 for (iter = tny_list_create_iterator (header_list), has_uncached_messages = FALSE;
2847 !has_uncached_messages && !tny_iterator_is_done (iter);
2848 tny_iterator_next (iter)) {
2851 header = (TnyHeader *) tny_iterator_get_current (iter);
2852 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
2853 has_uncached_messages = TRUE;
2854 g_object_unref (header);
2856 g_object_unref (iter);
2857 priv->op_type = has_uncached_messages?MODEST_MAIL_OPERATION_TYPE_RECEIVE:MODEST_MAIL_OPERATION_TYPE_OPEN;
2859 /* Get account and set it into mail_operation */
2860 if (tny_list_get_length (header_list) >= 1) {
2861 TnyIterator *iterator = tny_list_create_iterator (header_list);
2862 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iterator));
2864 TnyFolder *folder = tny_header_get_folder (header);
2866 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
2867 g_object_unref (folder);
2869 g_object_unref (header);
2871 g_object_unref (iterator);
2874 msg_list_size = compute_message_list_size (header_list, 0);
2876 modest_mail_operation_notify_start (self);
2877 iter = tny_list_create_iterator (header_list);
2878 if (!tny_iterator_is_done (iter)) {
2879 /* notify about the start of the operation */
2880 ModestMailOperationState *state;
2881 state = modest_mail_operation_clone_state (self);
2884 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
2887 GetMsgInfo *msg_info = NULL;
2888 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2889 TnyFolder *folder = tny_header_get_folder (header);
2891 /* Create the message info */
2892 msg_info = g_slice_new0 (GetMsgInfo);
2893 msg_info->mail_op = g_object_ref (self);
2894 msg_info->header = g_object_ref (header);
2895 msg_info->more_msgs = g_object_ref (iter);
2896 msg_info->user_callback = user_callback;
2897 msg_info->user_data = user_data;
2898 msg_info->destroy_notify = notify;
2899 msg_info->last_total_bytes = 0;
2900 msg_info->sum_total_bytes = 0;
2901 msg_info->total_bytes = msg_list_size;
2903 /* The callback will call it per each header */
2904 tny_folder_get_msg_async (folder, header, get_msg_async_cb, get_msg_status_cb, msg_info);
2906 /* Free and go on */
2907 g_object_unref (header);
2908 g_object_unref (folder);
2909 g_slice_free (ModestMailOperationState, state);
2911 g_object_unref (iter);
2916 remove_msgs_async_cb (TnyFolder *folder,
2921 gboolean expunge, leave_on_server;
2922 const gchar *account_name;
2923 TnyAccount *account;
2924 ModestProtocolType account_proto = MODEST_PROTOCOL_REGISTRY_TYPE_INVALID;
2925 ModestMailOperation *self;
2926 ModestMailOperationPrivate *priv;
2927 ModestProtocolRegistry *protocol_registry;
2929 self = (ModestMailOperation *) user_data;
2930 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2931 protocol_registry = modest_runtime_get_protocol_registry ();
2933 if (canceled || err) {
2934 /* If canceled by the user, ignore the error given by Tinymail */
2936 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
2938 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
2939 priv->error = g_error_copy ((const GError *) err);
2940 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
2943 modest_mail_operation_notify_end (self);
2944 g_object_unref (self);
2948 account = modest_tny_folder_get_account (folder);
2949 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2951 modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
2953 account_proto = modest_tny_account_get_protocol_type (account);
2954 g_object_unref (account);
2956 if ((modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_proto) &&
2957 !leave_on_server) ||
2958 !modest_tny_folder_is_remote_folder (folder))
2964 tny_folder_sync_async(folder, expunge, sync_folder_finish_callback,
2969 modest_mail_operation_remove_msgs (ModestMailOperation *self,
2971 gboolean remove_to_trash /*ignored*/)
2973 TnyFolder *folder = NULL;
2974 ModestMailOperationPrivate *priv;
2975 TnyIterator *iter = NULL;
2976 TnyHeader *header = NULL;
2977 TnyList *remove_headers = NULL;
2978 TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
2979 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
2981 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
2982 g_return_if_fail (TNY_IS_LIST (headers));
2984 if (remove_to_trash)
2985 g_warning ("remove to trash is not implemented");
2987 if (tny_list_get_length(headers) == 0) {
2988 g_warning ("%s: list of headers is empty\n", __FUNCTION__);
2989 goto cleanup; /* nothing to do */
2992 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
2994 /* Get folder from first header and sync it */
2995 iter = tny_list_create_iterator (headers);
2996 header = TNY_HEADER (tny_iterator_get_current (iter));
2997 g_object_unref (iter);
2999 folder = tny_header_get_folder (header);
3000 if (!TNY_IS_FOLDER(folder)) {
3001 g_warning ("%s: could not get folder for header\n", __FUNCTION__);
3005 /* Use the merged folder if we're removing messages from outbox */
3006 if (modest_tny_folder_is_local_folder (folder)) {
3007 ModestTnyLocalFoldersAccount *local_account;
3009 local_account = (ModestTnyLocalFoldersAccount *)
3010 modest_tny_account_store_get_local_folders_account (accstore);
3011 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
3012 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
3013 g_object_unref (folder);
3014 folder = modest_tny_local_folders_account_get_merged_outbox (local_account);
3016 g_object_unref (local_account);
3019 if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
3020 TnyIterator *headers_iter = tny_list_create_iterator (headers);
3022 while (!tny_iterator_is_done (headers_iter)) {
3023 TnyTransportAccount *traccount = NULL;
3024 TnyHeader *hdr = NULL;
3026 hdr = TNY_HEADER (tny_iterator_get_current (headers_iter));
3027 traccount = modest_tny_account_store_get_transport_account_from_outbox_header (accstore,
3030 ModestTnySendQueueStatus status;
3031 ModestTnySendQueue *send_queue;
3033 send_queue = modest_runtime_get_send_queue(traccount, TRUE);
3034 if (TNY_IS_SEND_QUEUE (send_queue)) {
3037 msg_id = modest_tny_send_queue_get_msg_id (hdr);
3038 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
3039 if (status != MODEST_TNY_SEND_QUEUE_SENDING) {
3040 if (G_UNLIKELY (remove_headers == NULL))
3041 remove_headers = tny_simple_list_new ();
3042 tny_list_append(remove_headers, G_OBJECT(hdr));
3046 g_object_unref(traccount);
3048 g_object_unref(hdr);
3049 tny_iterator_next (headers_iter);
3051 g_object_unref(headers_iter);
3054 /* Get account and set it into mail_operation */
3055 priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
3056 priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
3057 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3059 if (!remove_headers)
3060 remove_headers = g_object_ref (headers);
3062 /* remove message from folder */
3063 modest_mail_operation_notify_start (self);
3064 tny_folder_remove_msgs_async (folder, remove_headers, remove_msgs_async_cb,
3065 NULL, g_object_ref (self));
3069 g_object_unref (remove_headers);
3071 g_object_unref (header);
3073 g_object_unref (folder);
3077 notify_progress_of_multiple_messages (ModestMailOperation *self,
3079 gint *last_total_bytes,
3080 gint *sum_total_bytes,
3082 gboolean increment_done)
3084 ModestMailOperationPrivate *priv;
3085 ModestMailOperationState *state;
3086 gboolean is_num_bytes = FALSE;
3088 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3090 /* We know that tinymail sends us information about
3091 * transferred bytes with this particular message
3093 if (status->message)
3094 is_num_bytes = (g_ascii_strcasecmp (status->message, "Retrieving message") == 0);
3096 state = modest_mail_operation_clone_state (self);
3097 if (is_num_bytes && !((status->position == 1) && (status->of_total == 100))) {
3098 /* We know that we're in a different message when the
3099 total number of bytes to transfer is different. Of
3100 course it could fail if we're transferring messages
3101 of the same size, but this is a workarround */
3102 if (status->of_total != *last_total_bytes) {
3103 /* We need to increment the done when there is
3104 no information about each individual
3105 message, we need to do this in message
3106 transfers, and we don't do it for getting
3110 *sum_total_bytes += *last_total_bytes;
3111 *last_total_bytes = status->of_total;
3113 state->bytes_done += status->position + *sum_total_bytes;
3114 state->bytes_total = total_bytes;
3116 /* Notify the status change. Only notify about changes
3117 referred to bytes */
3118 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3122 g_slice_free (ModestMailOperationState, state);
3126 transfer_msgs_status_cb (GObject *obj,
3130 XFerMsgsAsyncHelper *helper;
3132 g_return_if_fail (status != NULL);
3134 /* Show only the status information we want */
3135 if (status->code != TNY_FOLDER_STATUS_CODE_XFER_MSGS)
3138 helper = (XFerMsgsAsyncHelper *) user_data;
3139 g_return_if_fail (helper != NULL);
3141 /* Notify progress */
3142 notify_progress_of_multiple_messages (helper->mail_op, status, &(helper->last_total_bytes),
3143 &(helper->sum_total_bytes), helper->total_bytes, TRUE);
3147 transfer_msgs_sync_folder_cb (TnyFolder *self,
3152 XFerMsgsAsyncHelper *helper;
3153 /* We don't care here about the results of the
3155 helper = (XFerMsgsAsyncHelper *) user_data;
3157 /* Notify about operation end */
3158 modest_mail_operation_notify_end (helper->mail_op);
3160 /* If user defined callback function was defined, call it */
3161 if (helper->user_callback)
3162 helper->user_callback (helper->mail_op, helper->user_data);
3165 if (helper->more_msgs)
3166 g_object_unref (helper->more_msgs);
3167 if (helper->headers)
3168 g_object_unref (helper->headers);
3169 if (helper->dest_folder)
3170 g_object_unref (helper->dest_folder);
3171 if (helper->mail_op)
3172 g_object_unref (helper->mail_op);
3173 g_slice_free (XFerMsgsAsyncHelper, helper);
3177 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data)
3179 XFerMsgsAsyncHelper *helper;
3180 ModestMailOperation *self;
3181 ModestMailOperationPrivate *priv;
3182 gboolean finished = TRUE;
3184 helper = (XFerMsgsAsyncHelper *) user_data;
3185 self = helper->mail_op;
3187 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3190 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3192 priv->error = g_error_copy (err);
3194 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3195 } else if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
3196 if (helper->more_msgs) {
3197 /* We'll transfer the next message in the list */
3198 tny_iterator_next (helper->more_msgs);
3199 if (!tny_iterator_is_done (helper->more_msgs)) {
3200 GObject *next_header;
3201 g_object_unref (helper->headers);
3202 helper->headers = tny_simple_list_new ();
3203 next_header = tny_iterator_get_current (helper->more_msgs);
3204 tny_list_append (helper->headers, next_header);
3205 g_object_unref (next_header);
3211 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3216 /* Synchronize the source folder contents. This should
3217 be done by tinymail but the camel_folder_sync it's
3218 actually disabled in transfer_msgs_thread_clean
3219 because it's supposed to cause hangs */
3220 tny_folder_sync_async (folder, helper->delete,
3221 transfer_msgs_sync_folder_cb,
3224 /* Transfer more messages */
3225 tny_folder_transfer_msgs_async (folder,
3227 helper->dest_folder,
3230 transfer_msgs_status_cb,
3235 /* Computes the size of the messages the headers in the list belongs
3236 to. If num_elements is different from 0 then it only takes into
3237 account the first num_elements for the calculation */
3239 compute_message_list_size (TnyList *headers,
3243 guint size = 0, element = 0;
3245 /* If num_elements is not valid then take all into account */
3246 if ((num_elements <= 0) || (num_elements > tny_list_get_length (headers)))
3247 num_elements = tny_list_get_length (headers);
3249 iter = tny_list_create_iterator (headers);
3250 while (!tny_iterator_is_done (iter) && element < num_elements) {
3251 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
3252 size += tny_header_get_message_size (header);
3253 g_object_unref (header);
3254 tny_iterator_next (iter);
3257 g_object_unref (iter);
3263 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
3266 gboolean delete_original,
3267 XferMsgsAsyncUserCallback user_callback,
3270 ModestMailOperationPrivate *priv = NULL;
3271 TnyIterator *iter = NULL;
3272 TnyFolder *src_folder = NULL;
3273 XFerMsgsAsyncHelper *helper = NULL;
3274 TnyHeader *header = NULL;
3275 ModestTnyFolderRules rules = 0;
3276 TnyAccount *dst_account = NULL;
3277 gboolean leave_on_server;
3278 ModestMailOperationState *state;
3279 ModestProtocolRegistry *protocol_registry;
3280 ModestProtocolType account_protocol;
3282 g_return_if_fail (self && MODEST_IS_MAIL_OPERATION (self));
3283 g_return_if_fail (headers && TNY_IS_LIST (headers));
3284 g_return_if_fail (folder && TNY_IS_FOLDER (folder));
3286 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3287 protocol_registry = modest_runtime_get_protocol_registry ();
3289 priv->total = tny_list_get_length (headers);
3291 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3292 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3294 /* Apply folder rules */
3295 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
3296 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3297 /* Set status failed and set an error */
3298 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3299 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3300 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
3301 _CS("ckct_ib_unable_to_paste_here"));
3302 /* Notify the queue */
3303 modest_mail_operation_notify_end (self);
3307 /* Get source folder */
3308 iter = tny_list_create_iterator (headers);
3309 header = TNY_HEADER (tny_iterator_get_current (iter));
3311 src_folder = tny_header_get_folder (header);
3312 g_object_unref (header);
3314 g_object_unref (iter);
3316 if (src_folder == NULL) {
3317 /* Notify the queue */
3318 modest_mail_operation_notify_end (self);
3320 g_warning ("%s: cannot find folder from header", __FUNCTION__);
3325 /* Check folder source and destination */
3326 if (src_folder == folder) {
3327 /* Set status failed and set an error */
3328 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3329 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3330 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
3331 _("mail_in_ui_folder_copy_target_error"));
3333 /* Notify the queue */
3334 modest_mail_operation_notify_end (self);
3337 g_object_unref (src_folder);
3341 /* Create the helper */
3342 helper = g_slice_new0 (XFerMsgsAsyncHelper);
3343 helper->mail_op = g_object_ref(self);
3344 helper->dest_folder = g_object_ref(folder);
3345 helper->user_callback = user_callback;
3346 helper->user_data = user_data;
3347 helper->last_total_bytes = 0;
3348 helper->sum_total_bytes = 0;
3349 helper->total_bytes = compute_message_list_size (headers, 0);
3351 /* Get account and set it into mail_operation */
3352 priv->account = modest_tny_folder_get_account (src_folder);
3353 dst_account = modest_tny_folder_get_account (folder);
3355 if (priv->account == dst_account) {
3356 /* Transfer all messages at once using the fast
3357 * method. Note that depending on the server this
3358 * might not be that fast, and might not be
3359 * user-cancellable either */
3360 helper->headers = g_object_ref (headers);
3361 helper->more_msgs = NULL;
3363 /* Transfer messages one by one so the user can cancel
3366 helper->headers = tny_simple_list_new ();
3367 helper->more_msgs = tny_list_create_iterator (headers);
3368 hdr = tny_iterator_get_current (helper->more_msgs);
3369 tny_list_append (helper->headers, hdr);
3370 g_object_unref (hdr);
3373 /* If leave_on_server is set to TRUE then don't use
3374 delete_original, we always pass FALSE. This is because
3375 otherwise tinymail will try to sync the source folder and
3376 this could cause an error if we're offline while
3377 transferring an already downloaded message from a POP
3379 account_protocol = modest_tny_account_get_protocol_type (priv->account);
3380 if (modest_protocol_registry_protocol_type_has_leave_on_server (protocol_registry, account_protocol)) {
3381 const gchar *account_name;
3383 account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (priv->account);
3384 leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
3387 leave_on_server = FALSE;
3390 /* Do not delete messages if leave on server is TRUE */
3391 helper->delete = (leave_on_server) ? FALSE : delete_original;
3393 modest_mail_operation_notify_start (self);
3395 /* Start notifying progress */
3396 state = modest_mail_operation_clone_state (self);
3399 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
3400 g_slice_free (ModestMailOperationState, state);
3402 tny_folder_transfer_msgs_async (src_folder,
3407 transfer_msgs_status_cb,
3409 g_object_unref (src_folder);
3410 g_object_unref (dst_account);
3415 on_refresh_folder (TnyFolder *folder,
3420 RefreshAsyncHelper *helper = NULL;
3421 ModestMailOperation *self = NULL;
3422 ModestMailOperationPrivate *priv = NULL;
3424 helper = (RefreshAsyncHelper *) user_data;
3425 self = helper->mail_op;
3426 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3428 g_return_if_fail(priv!=NULL);
3431 priv->error = g_error_copy (error);
3432 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3437 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3438 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
3439 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
3440 _("Error trying to refresh the contents of %s"),
3441 tny_folder_get_name (folder));
3445 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3448 /* Call user defined callback, if it exists */
3449 if (helper->user_callback) {
3451 /* This is not a GDK lock because we are a Tinymail callback and
3452 * Tinymail already acquires the Gdk lock */
3453 helper->user_callback (self, folder, helper->user_data);
3457 g_slice_free (RefreshAsyncHelper, helper);
3459 /* Notify about operation end */
3460 modest_mail_operation_notify_end (self);
3461 g_object_unref(self);
3465 on_refresh_folder_status_update (GObject *obj,
3469 RefreshAsyncHelper *helper = NULL;
3470 ModestMailOperation *self = NULL;
3471 ModestMailOperationPrivate *priv = NULL;
3472 ModestMailOperationState *state;
3474 g_return_if_fail (user_data != NULL);
3475 g_return_if_fail (status != NULL);
3477 /* Show only the status information we want */
3478 if (status->code != TNY_FOLDER_STATUS_CODE_REFRESH)
3481 helper = (RefreshAsyncHelper *) user_data;
3482 self = helper->mail_op;
3483 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
3485 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3487 priv->done = status->position;
3488 priv->total = status->of_total;
3490 state = modest_mail_operation_clone_state (self);
3492 /* This is not a GDK lock because we are a Tinymail callback and
3493 * Tinymail already acquires the Gdk lock */
3494 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
3496 g_slice_free (ModestMailOperationState, state);
3500 modest_mail_operation_refresh_folder (ModestMailOperation *self,
3502 RefreshAsyncUserCallback user_callback,
3505 ModestMailOperationPrivate *priv = NULL;
3506 RefreshAsyncHelper *helper = NULL;
3508 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3510 /* Check memory low */
3511 if (_check_memory_low (self)) {
3513 user_callback (self, folder, user_data);
3514 /* Notify about operation end */
3515 modest_mail_operation_notify_end (self);
3519 /* Get account and set it into mail_operation */
3520 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3521 priv->account = modest_tny_folder_get_account (folder);
3522 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
3524 /* Create the helper */
3525 helper = g_slice_new0 (RefreshAsyncHelper);
3526 helper->mail_op = g_object_ref(self);
3527 helper->user_callback = user_callback;
3528 helper->user_data = user_data;
3530 modest_mail_operation_notify_start (self);
3532 /* notify that the operation was started */
3533 ModestMailOperationState *state;
3534 state = modest_mail_operation_clone_state (self);
3537 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL],
3539 g_slice_free (ModestMailOperationState, state);
3541 tny_folder_refresh_async (folder,
3543 on_refresh_folder_status_update,
3548 run_queue_notify_and_destroy (RunQueueHelper *helper,
3549 ModestMailOperationStatus status)
3551 ModestMailOperationPrivate *priv;
3554 if (helper->error_handler &&
3555 g_signal_handler_is_connected (helper->queue, helper->error_handler))
3556 g_signal_handler_disconnect (helper->queue, helper->error_handler);
3557 if (helper->start_handler &&
3558 g_signal_handler_is_connected (helper->queue, helper->start_handler))
3559 g_signal_handler_disconnect (helper->queue, helper->start_handler);
3560 if (helper->stop_handler &&
3561 g_signal_handler_is_connected (helper->queue, helper->stop_handler))
3562 g_signal_handler_disconnect (helper->queue, helper->stop_handler);
3565 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (helper->self);
3566 priv->status = status;
3569 modest_mail_operation_notify_end (helper->self);
3572 g_object_unref (helper->queue);
3573 g_object_unref (helper->self);
3574 g_slice_free (RunQueueHelper, helper);
3578 run_queue_stop (ModestTnySendQueue *queue,
3581 RunQueueHelper *helper;
3583 g_debug ("%s sending queue stopped", __FUNCTION__);
3585 helper = (RunQueueHelper *) user_data;
3586 run_queue_notify_and_destroy (helper, MODEST_MAIL_OPERATION_STATUS_SUCCESS);
3590 modest_mail_operation_run_queue (ModestMailOperation *self,
3591 ModestTnySendQueue *queue)
3593 ModestMailOperationPrivate *priv;
3594 RunQueueHelper *helper;
3596 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3597 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
3598 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3600 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3601 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
3602 priv->op_type = MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE;
3604 /* Create the helper */
3605 helper = g_slice_new0 (RunQueueHelper);
3606 helper->queue = g_object_ref (queue);
3607 helper->self = g_object_ref (self);
3608 helper->stop_handler = g_signal_connect (queue, "queue-stop",
3609 G_CALLBACK (run_queue_stop),
3612 /* Notify operation has started */
3613 modest_mail_operation_notify_start (self);
3614 g_debug ("%s, run queue started", __FUNCTION__);
3618 queue_wakeup_callback (ModestTnySendQueue *queue,
3623 ModestMailOperation *mail_op;
3624 ModestMailOperationPrivate *priv;
3626 mail_op = (ModestMailOperation *) userdata;
3627 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3629 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3630 tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (queue));
3633 modest_mail_operation_notify_end (mail_op);
3634 g_object_unref (mail_op);
3638 modest_mail_operation_queue_wakeup (ModestMailOperation *self,
3639 ModestTnySendQueue *queue)
3641 ModestMailOperationPrivate *priv;
3643 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3644 g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (queue));
3645 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3647 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3648 priv->account = TNY_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (queue)));
3649 priv->op_type = MODEST_MAIL_OPERATION_TYPE_QUEUE_WAKEUP;
3651 g_object_ref (self);
3653 modest_tny_send_queue_wakeup (queue, queue_wakeup_callback, self);
3654 modest_mail_operation_notify_start (self);
3658 shutdown_callback (ModestTnyAccountStore *account_store, gpointer userdata)
3660 ModestMailOperation *self = (ModestMailOperation *) userdata;
3661 ModestMailOperationPrivate *priv;
3663 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3664 g_return_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (account_store));
3665 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3667 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3669 modest_mail_operation_notify_end (self);
3670 g_object_unref (self);
3674 modest_mail_operation_shutdown (ModestMailOperation *self, ModestTnyAccountStore *account_store)
3676 ModestMailOperationPrivate *priv;
3678 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3679 g_return_if_fail (MODEST_IS_TNY_ACCOUNT_STORE (account_store));
3680 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3682 modest_mail_operation_queue_set_running_shutdown (modest_runtime_get_mail_operation_queue ());
3684 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3685 priv->account = NULL;
3686 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SHUTDOWN;
3688 modest_mail_operation_notify_start (self);
3689 g_object_ref (self);
3690 modest_tny_account_store_shutdown (account_store, shutdown_callback, self);
3694 sync_folder_finish_callback (TnyFolder *self,
3700 ModestMailOperation *mail_op;
3701 ModestMailOperationPrivate *priv;
3703 mail_op = (ModestMailOperation *) user_data;
3704 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3706 /* If canceled by the user, ignore the error given by Tinymail */
3708 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
3710 /* If the operation was a sync then the status is
3711 failed, but if it's part of another operation then
3712 just set it as finished with errors */
3713 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER)
3714 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3716 priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
3717 priv->error = g_error_copy ((const GError *) err);
3718 priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
3720 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3723 modest_mail_operation_notify_end (mail_op);
3724 g_object_unref (mail_op);
3728 modest_mail_operation_sync_folder (ModestMailOperation *self,
3729 TnyFolder *folder, gboolean expunge)
3731 ModestMailOperationPrivate *priv;
3733 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
3734 g_return_if_fail (TNY_IS_FOLDER (folder));
3735 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
3737 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
3738 priv->account = modest_tny_folder_get_account (folder);
3739 priv->op_type = MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER;
3741 modest_mail_operation_notify_start (self);
3742 g_object_ref (self);
3743 tny_folder_sync_async (folder, expunge,
3744 (TnyFolderCallback) sync_folder_finish_callback,
3749 modest_mail_operation_notify_start (ModestMailOperation *self)
3751 ModestMailOperationPrivate *priv = NULL;
3753 g_return_if_fail (self);
3755 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3757 /* Ensure that all the fields are filled correctly */
3758 g_return_if_fail (priv->op_type != MODEST_MAIL_OPERATION_TYPE_UNKNOWN);
3760 /* Notify the observers about the mail operation. We do not
3761 wrapp this emission because we assume that this function is
3762 always called from within the main lock */
3763 g_signal_emit (G_OBJECT (self), signals[OPERATION_STARTED_SIGNAL], 0, NULL);
3768 * It's used by the mail operation queue to notify the observers
3769 * attached to that signal that the operation finished. We need to use
3770 * that because tinymail does not give us the progress of a given
3771 * operation when it finishes (it directly calls the operation
3775 modest_mail_operation_notify_end (ModestMailOperation *self)
3777 ModestMailOperationPrivate *priv = NULL;
3779 g_return_if_fail (self);
3781 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3783 /* Notify the observers about the mail operation end. We do
3784 not wrapp this emission because we assume that this
3785 function is always called from within the main lock */
3786 g_signal_emit (G_OBJECT (self), signals[OPERATION_FINISHED_SIGNAL], 0, NULL);
3788 /* Remove the error user data */
3789 if (priv->error_checking_user_data && priv->error_checking_user_data_destroyer)
3790 priv->error_checking_user_data_destroyer (priv->error_checking_user_data);
3794 modest_mail_operation_get_account (ModestMailOperation *self)
3796 ModestMailOperationPrivate *priv = NULL;
3798 g_return_val_if_fail (self, NULL);
3800 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3802 return (priv->account) ? g_object_ref (priv->account) : NULL;
3806 modest_mail_operation_noop (ModestMailOperation *self)
3808 ModestMailOperationPrivate *priv = NULL;
3810 g_return_if_fail (self);
3812 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3813 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
3814 priv->op_type = MODEST_MAIL_OPERATION_TYPE_INFO;
3818 /* This mail operation does nothing actually */
3819 modest_mail_operation_notify_start (self);
3820 modest_mail_operation_notify_end (self);
3825 modest_mail_operation_to_string (ModestMailOperation *self)
3827 const gchar *type, *status, *account_id;
3828 ModestMailOperationPrivate *priv = NULL;
3830 g_return_val_if_fail (self, NULL);
3832 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
3834 /* new operations don't have anything interesting */
3835 if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_UNKNOWN)
3836 return g_strdup_printf ("%p <new operation>", self);
3838 switch (priv->op_type) {
3839 case MODEST_MAIL_OPERATION_TYPE_SEND: type= "SEND"; break;
3840 case MODEST_MAIL_OPERATION_TYPE_RECEIVE: type= "RECEIVE"; break;
3841 case MODEST_MAIL_OPERATION_TYPE_OPEN: type= "OPEN"; break;
3842 case MODEST_MAIL_OPERATION_TYPE_DELETE: type= "DELETE"; break;
3843 case MODEST_MAIL_OPERATION_TYPE_INFO: type= "INFO"; break;
3844 case MODEST_MAIL_OPERATION_TYPE_RUN_QUEUE: type= "RUN-QUEUE"; break;
3845 case MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER: type= "SYNC-FOLDER"; break;
3846 case MODEST_MAIL_OPERATION_TYPE_UNKNOWN: type= "UNKNOWN"; break;
3847 default: type = "UNEXPECTED"; break;
3850 switch (priv->status) {
3851 case MODEST_MAIL_OPERATION_STATUS_INVALID: status= "INVALID"; break;
3852 case MODEST_MAIL_OPERATION_STATUS_SUCCESS: status= "SUCCESS"; break;
3853 case MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS: status= "FINISHED-WITH-ERRORS"; break;
3854 case MODEST_MAIL_OPERATION_STATUS_FAILED: status= "FAILED"; break;
3855 case MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS: status= "IN-PROGRESS"; break;
3856 case MODEST_MAIL_OPERATION_STATUS_CANCELED: status= "CANCELLED"; break;
3857 default: status= "UNEXPECTED"; break;
3860 account_id = priv->account ? tny_account_get_id (priv->account) : "";
3862 return g_strdup_printf ("%p \"%s\" (%s) [%s] {%d/%d} '%s'", self, account_id,type, status,
3863 priv->done, priv->total,
3864 priv->error && priv->error->message ? priv->error->message : "");
3868 * Once the mail operations were objects this will be no longer
3869 * needed. I don't like it, but we need it for the moment
3872 _check_memory_low (ModestMailOperation *mail_op)
3874 if (modest_platform_check_memory_low (NULL, FALSE)) {
3875 ModestMailOperationPrivate *priv;
3877 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
3878 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
3879 g_set_error (&(priv->error),
3880 MODEST_MAIL_OPERATION_ERROR,
3881 MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY,
3882 "Not enough memory to complete the operation");