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.
30 #include "modest-mail-operation.h"
31 /* include other impl specific header files */
34 #include <tny-mime-part.h>
35 #include <tny-store-account.h>
36 #include <tny-folder-store.h>
37 #include <tny-folder-store-query.h>
38 #include <tny-camel-stream.h>
39 #include <tny-simple-list.h>
40 #include <tny-send-queue.h>
41 #include <tny-status.h>
42 #include <camel/camel-stream-mem.h>
43 #include <glib/gi18n.h>
44 #include "modest-platform.h"
45 #include <modest-tny-account.h>
46 #include <modest-tny-send-queue.h>
47 #include <modest-runtime.h>
48 #include "modest-text-utils.h"
49 #include "modest-tny-msg.h"
50 #include "modest-tny-folder.h"
51 #include "modest-tny-platform-factory.h"
52 #include "modest-marshal.h"
53 #include "modest-error.h"
55 /* 'private'/'protected' functions */
56 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
57 static void modest_mail_operation_init (ModestMailOperation *obj);
58 static void modest_mail_operation_finalize (GObject *obj);
60 static void get_msg_cb (TnyFolder *folder,
66 static void get_msg_status_cb (GObject *obj,
70 static void modest_mail_operation_notify_end (ModestMailOperation *self);
72 enum _ModestMailOperationSignals
74 PROGRESS_CHANGED_SIGNAL,
79 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
80 struct _ModestMailOperationPrivate {
83 ModestMailOperationStatus status;
84 ModestMailOperationId id;
86 ErrorCheckingUserCallback error_checking;
90 #define MODEST_MAIL_OPERATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
91 MODEST_TYPE_MAIL_OPERATION, \
92 ModestMailOperationPrivate))
94 #define CHECK_EXCEPTION(priv, new_status) if (priv->error) {\
95 priv->status = new_status;\
98 typedef struct _GetMsgAsyncHelper {
99 ModestMailOperation *mail_op;
100 GetMsgAsyncUserCallback user_callback;
105 typedef struct _XFerMsgAsyncHelper
107 ModestMailOperation *mail_op;
109 TnyFolder *dest_folder;
110 XferMsgsAsynUserCallback user_callback;
112 } XFerMsgAsyncHelper;
114 typedef struct _XFerFolderAsyncHelper
116 ModestMailOperation *mail_op;
118 } XFerFolderAsyncHelper;
121 static GObjectClass *parent_class = NULL;
123 static guint signals[NUM_SIGNALS] = {0};
126 modest_mail_operation_get_type (void)
128 static GType my_type = 0;
130 static const GTypeInfo my_info = {
131 sizeof(ModestMailOperationClass),
132 NULL, /* base init */
133 NULL, /* base finalize */
134 (GClassInitFunc) modest_mail_operation_class_init,
135 NULL, /* class finalize */
136 NULL, /* class data */
137 sizeof(ModestMailOperation),
139 (GInstanceInitFunc) modest_mail_operation_init,
142 my_type = g_type_register_static (G_TYPE_OBJECT,
143 "ModestMailOperation",
150 modest_mail_operation_class_init (ModestMailOperationClass *klass)
152 GObjectClass *gobject_class;
153 gobject_class = (GObjectClass*) klass;
155 parent_class = g_type_class_peek_parent (klass);
156 gobject_class->finalize = modest_mail_operation_finalize;
158 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
161 * ModestMailOperation::progress-changed
162 * @self: the #MailOperation that emits the signal
163 * @user_data: user data set when the signal handler was connected
165 * Emitted when the progress of a mail operation changes
167 signals[PROGRESS_CHANGED_SIGNAL] =
168 g_signal_new ("progress-changed",
169 G_TYPE_FROM_CLASS (gobject_class),
171 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
173 g_cclosure_marshal_VOID__VOID,
178 modest_mail_operation_init (ModestMailOperation *obj)
180 ModestMailOperationPrivate *priv;
182 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
184 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
185 priv->id = MODEST_MAIL_OPERATION_ID_UNKNOWN;
193 modest_mail_operation_finalize (GObject *obj)
195 ModestMailOperationPrivate *priv;
197 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
200 g_error_free (priv->error);
204 g_object_unref (priv->source);
208 G_OBJECT_CLASS(parent_class)->finalize (obj);
212 modest_mail_operation_new (ModestMailOperationId id,
215 ModestMailOperation *obj;
216 ModestMailOperationPrivate *priv;
218 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
219 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
223 priv->source = g_object_ref(source);
229 modest_mail_operation_new_with_error_handling (ModestMailOperationId id,
231 ErrorCheckingUserCallback error_handler)
233 ModestMailOperation *obj;
234 ModestMailOperationPrivate *priv;
236 obj = modest_mail_operation_new (id, source);
237 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
239 g_return_val_if_fail (error_handler != NULL, obj);
240 priv->error_checking = error_handler;
246 modest_mail_operation_execute_error_handler (ModestMailOperation *self)
248 ModestMailOperationPrivate *priv;
250 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
251 g_return_if_fail(priv->status != MODEST_MAIL_OPERATION_STATUS_SUCCESS);
253 if (priv->error_checking == NULL) return;
254 priv->error_checking (priv->source, self);
258 ModestMailOperationId
259 modest_mail_operation_get_id (ModestMailOperation *self)
261 ModestMailOperationPrivate *priv;
263 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
269 modest_mail_operation_is_mine (ModestMailOperation *self,
272 ModestMailOperationPrivate *priv;
274 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
275 if (priv->source == NULL) return FALSE;
277 return priv->source == me;
281 modest_mail_operation_get_source (ModestMailOperation *self)
283 ModestMailOperationPrivate *priv;
285 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
287 return g_object_ref (priv->source);
291 modest_mail_operation_send_mail (ModestMailOperation *self,
292 TnyTransportAccount *transport_account,
295 TnySendQueue *send_queue;
297 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
298 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
299 g_return_if_fail (TNY_IS_MSG (msg));
301 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
302 if (!TNY_IS_SEND_QUEUE(send_queue))
303 g_printerr ("modest: could not find send queue for account\n");
306 tny_send_queue_add (send_queue, msg, &err);
308 g_printerr ("modest: error adding msg to send queue: %s\n",
312 /* g_message ("modest: message added to send queue"); */
316 /* Notify about operation end */
317 modest_mail_operation_notify_end (self);
321 modest_mail_operation_send_new_mail (ModestMailOperation *self,
322 TnyTransportAccount *transport_account,
323 const gchar *from, const gchar *to,
324 const gchar *cc, const gchar *bcc,
325 const gchar *subject, const gchar *plain_body,
326 const gchar *html_body,
327 const GList *attachments_list,
328 TnyHeaderFlags priority_flags)
331 ModestMailOperationPrivate *priv = NULL;
332 /* GList *node = NULL; */
334 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
335 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
337 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
339 /* Check parametters */
341 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
342 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
343 _("Error trying to send a mail. You need to set at least one recipient"));
347 if (html_body == NULL) {
348 new_msg = modest_tny_msg_new (to, from, cc, bcc, subject, plain_body, (GSList *) attachments_list); /* FIXME: attachments */
350 new_msg = modest_tny_msg_new_html_plain (to, from, cc, bcc, subject, html_body, plain_body, (GSList *) attachments_list);
353 g_printerr ("modest: failed to create a new msg\n");
357 /* TODO: add priority handling. It's received in the priority_flags operator, and
358 it should have effect in the sending operation */
360 /* Call mail operation */
361 modest_mail_operation_send_mail (self, transport_account, new_msg);
364 g_object_unref (G_OBJECT (new_msg));
368 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
369 TnyTransportAccount *transport_account,
370 const gchar *from, const gchar *to,
371 const gchar *cc, const gchar *bcc,
372 const gchar *subject, const gchar *plain_body,
373 const gchar *html_body,
374 const GList *attachments_list,
375 TnyHeaderFlags priority_flags)
378 TnyFolder *folder = NULL;
379 ModestMailOperationPrivate *priv = NULL;
382 /* GList *node = NULL; */
384 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
385 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
387 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
389 if (html_body == NULL) {
390 msg = modest_tny_msg_new (to, from, cc, bcc, subject, plain_body, (GSList *) attachments_list); /* FIXME: attachments */
392 msg = modest_tny_msg_new_html_plain (to, from, cc, bcc, subject, html_body, plain_body, (GSList *) attachments_list);
395 g_printerr ("modest: failed to create a new msg\n");
399 folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account), TNY_FOLDER_TYPE_DRAFTS);
401 g_printerr ("modest: failed to find Drafts folder\n");
405 tny_folder_add_msg (folder, msg, &err);
407 g_printerr ("modest: error adding msg to Drafts folder: %s",
413 modest_mail_operation_notify_end (self);
418 g_object_unref (G_OBJECT(msg));
420 g_object_unref (G_OBJECT(folder));
425 ModestMailOperation *mail_op;
426 TnyStoreAccount *account;
427 TnyTransportAccount *transport_account;
431 recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all_folders)
434 TnyList *folders = tny_simple_list_new ();
436 tny_folder_store_get_folders (store, folders, query, NULL);
437 iter = tny_list_create_iterator (folders);
439 while (!tny_iterator_is_done (iter)) {
441 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
443 tny_list_prepend (all_folders, G_OBJECT (folder));
444 recurse_folders (folder, query, all_folders);
445 g_object_unref (G_OBJECT (folder));
447 tny_iterator_next (iter);
449 g_object_unref (G_OBJECT (iter));
450 g_object_unref (G_OBJECT (folders));
454 * Used by update_account_thread to emit the "progress-changed" signal
455 * from the main loop. We call it inside an idle call to achieve that
458 notify_update_account_observers (gpointer data)
460 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
462 g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
468 * Used by update_account_thread to notify the queue from the main
469 * loop. We call it inside an idle call to achieve that
472 notify_update_account_queue (gpointer data)
474 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
476 modest_mail_operation_notify_end (mail_op);
477 g_object_unref (mail_op);
483 update_account_thread (gpointer thr_user_data)
485 UpdateAccountInfo *info;
486 TnyList *all_folders = NULL;
487 TnyIterator *iter = NULL;
488 TnyFolderStoreQuery *query = NULL;
489 ModestMailOperationPrivate *priv;
490 ModestTnySendQueue *send_queue;
493 info = (UpdateAccountInfo *) thr_user_data;
494 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
496 /* Get all the folders We can do it synchronously because
497 we're already running in a different thread than the UI */
498 all_folders = tny_simple_list_new ();
499 query = tny_folder_store_query_new ();
500 tny_folder_store_query_add_item (query, NULL, TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
501 tny_folder_store_get_folders (TNY_FOLDER_STORE (info->account),
506 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
510 iter = tny_list_create_iterator (all_folders);
511 while (!tny_iterator_is_done (iter)) {
512 TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter));
514 recurse_folders (folder, query, all_folders);
515 tny_iterator_next (iter);
517 g_object_unref (G_OBJECT (iter));
519 /* Update status and notify. We need to call the notification
520 with a source functopm in order to call it from the main
521 loop. We need that in order not to get into trouble with
522 Gtk+. We use a timeout in order to provide more status
523 information, because the sync tinymail call does not
524 provide it for the moment */
525 timeout = g_timeout_add (250, notify_update_account_observers, info->mail_op);
527 /* Refresh folders */
528 iter = tny_list_create_iterator (all_folders);
529 while (!tny_iterator_is_done (iter) && !priv->error) {
531 TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter));
533 /* Refresh the folder */
534 tny_folder_refresh (TNY_FOLDER (folder), &(priv->error));
536 /* TODO: Apply retrieval types */
538 /* TODO: apply per-message size limits */
540 /* TODO: apply message count limit */
543 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
546 g_object_unref (G_OBJECT (folder));
547 tny_iterator_next (iter);
549 g_object_unref (G_OBJECT (iter));
550 g_source_remove (timeout);
553 priv->id = MODEST_MAIL_OPERATION_ID_SEND;
555 send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(info->transport_account));
557 timeout = g_timeout_add (250, notify_update_account_observers, info->mail_op);
558 modest_tny_send_queue_flush (send_queue);
559 g_source_remove (timeout);
561 g_object_unref (G_OBJECT(send_queue));
563 /* Check if the operation was a success */
565 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
567 /* Update the last updated key */
568 modest_account_mgr_set_int (modest_runtime_get_account_mgr (),
569 tny_account_get_id (TNY_ACCOUNT (info->account)),
570 MODEST_ACCOUNT_LAST_UPDATED,
576 /* Notify about operation end. Note that the info could be
577 freed before this idle happens, but the mail operation will
579 g_idle_add (notify_update_account_queue, info->mail_op);
582 g_object_unref (query);
583 g_object_unref (all_folders);
584 g_object_unref (info->account);
585 g_object_unref (info->transport_account);
586 g_slice_free (UpdateAccountInfo, info);
592 modest_mail_operation_update_account (ModestMailOperation *self,
593 const gchar *account_name)
596 UpdateAccountInfo *info;
597 ModestMailOperationPrivate *priv;
598 TnyStoreAccount *modest_account;
599 TnyTransportAccount *transport_account;
601 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE);
602 g_return_val_if_fail (account_name, FALSE);
604 /* Init mail operation. Set total and done to 0, and do not
605 update them, this way the progress objects will know that
606 we have no clue about the number of the objects */
607 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
610 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
612 /* Get the Modest account */
613 modest_account = (TnyStoreAccount *)
614 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store (),
616 TNY_ACCOUNT_TYPE_STORE);
618 if (!modest_account) {
619 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
620 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
621 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
622 "cannot get tny store account for %s\n", account_name);
623 modest_mail_operation_notify_end (self);
627 /* Get the transport account, we can not do it in the thread
628 due to some problems with dbus */
629 transport_account = (TnyTransportAccount *)
630 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
632 if (!transport_account) {
633 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
634 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
635 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
636 "cannot get tny transport account for %s\n", account_name);
637 modest_mail_operation_notify_end (self);
641 /* Create the helper object */
642 info = g_slice_new (UpdateAccountInfo);
643 info->mail_op = self;
644 info->account = modest_account;
645 info->transport_account = transport_account;
647 thread = g_thread_create (update_account_thread, info, FALSE, NULL);
652 ModestMailOperationStatus
653 modest_mail_operation_get_status (ModestMailOperation *self)
655 ModestMailOperationPrivate *priv;
657 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
658 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
659 MODEST_MAIL_OPERATION_STATUS_INVALID);
661 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
666 modest_mail_operation_get_error (ModestMailOperation *self)
668 ModestMailOperationPrivate *priv;
670 g_return_val_if_fail (self, NULL);
671 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
673 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
678 modest_mail_operation_cancel (ModestMailOperation *self)
680 ModestMailOperationPrivate *priv;
682 if (!MODEST_IS_MAIL_OPERATION (self)) {
683 g_warning ("%s: invalid parametter", G_GNUC_FUNCTION);
687 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
689 /* TODO: Tinymail does not support cancel operation */
690 /* tny_account_cancel (); */
693 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
695 /* Notify about operation end */
696 modest_mail_operation_notify_end (self);
702 modest_mail_operation_get_task_done (ModestMailOperation *self)
704 ModestMailOperationPrivate *priv;
706 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), 0);
708 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
713 modest_mail_operation_get_task_total (ModestMailOperation *self)
715 ModestMailOperationPrivate *priv;
717 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), 0);
719 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
724 modest_mail_operation_is_finished (ModestMailOperation *self)
726 ModestMailOperationPrivate *priv;
727 gboolean retval = FALSE;
729 if (!MODEST_IS_MAIL_OPERATION (self)) {
730 g_warning ("%s: invalid parametter", G_GNUC_FUNCTION);
734 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
736 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
737 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
738 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
739 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
748 /* ******************************************************************* */
749 /* ************************** STORE ACTIONS ************************* */
750 /* ******************************************************************* */
754 modest_mail_operation_create_folder (ModestMailOperation *self,
755 TnyFolderStore *parent,
758 ModestTnyFolderRules rules;
759 ModestMailOperationPrivate *priv;
760 TnyFolder *new_folder = NULL;
761 gboolean can_create = FALSE;
763 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL);
764 g_return_val_if_fail (name, NULL);
766 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
769 if (!TNY_IS_FOLDER (parent)) {
770 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
771 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
772 _("mail_in_ui_folder_create_error"));
774 /* Check folder rules */
775 rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
776 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)
777 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
778 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
779 _("mail_in_ui_folder_create_error"));
785 /* Create the folder */
786 new_folder = tny_folder_store_create_folder (parent, name, &(priv->error));
787 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
790 /* Notify about operation end */
791 modest_mail_operation_notify_end (self);
797 modest_mail_operation_remove_folder (ModestMailOperation *self,
799 gboolean remove_to_trash)
802 ModestMailOperationPrivate *priv;
803 ModestTnyFolderRules rules;
805 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
806 g_return_if_fail (TNY_IS_FOLDER (folder));
808 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
810 /* Check folder rules */
811 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
812 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
813 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
814 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
815 _("mail_in_ui_folder_delete_error"));
819 /* Get the account */
820 account = tny_folder_get_account (folder);
822 /* Delete folder or move to trash */
823 if (remove_to_trash) {
824 TnyFolder *trash_folder = NULL;
825 trash_folder = modest_tny_account_get_special_folder (account,
826 TNY_FOLDER_TYPE_TRASH);
827 /* TODO: error_handling */
828 modest_mail_operation_xfer_folder (self, folder,
829 TNY_FOLDER_STORE (trash_folder), TRUE);
831 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
833 tny_folder_store_remove_folder (parent, folder, &(priv->error));
834 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
837 g_object_unref (G_OBJECT (parent));
839 g_object_unref (G_OBJECT (account));
842 /* Notify about operation end */
843 modest_mail_operation_notify_end (self);
847 modest_mail_operation_rename_folder (ModestMailOperation *self,
851 ModestMailOperationPrivate *priv;
852 ModestTnyFolderRules rules;
854 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
855 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
856 g_return_if_fail (name);
858 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
860 /* Check folder rules */
861 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
862 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
863 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
864 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
865 _("FIXME: unable to rename"));
867 /* Rename. Camel handles folder subscription/unsubscription */
868 TnyFolderStore *into;
871 into = tny_folder_get_folder_store (folder);
872 nfol = tny_folder_copy (folder, into, name, TRUE, &(priv->error));
874 g_object_unref (into);
876 g_object_unref (nfol);
878 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
882 /* Notify about operation end */
883 modest_mail_operation_notify_end (self);
887 transfer_folder_status_cb (GObject *obj,
891 XFerMsgAsyncHelper *helper = NULL;
892 ModestMailOperation *self;
893 ModestMailOperationPrivate *priv;
895 g_return_if_fail (status != NULL);
896 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
898 helper = (XFerMsgAsyncHelper *) user_data;
899 g_return_if_fail (helper != NULL);
901 self = helper->mail_op;
902 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
904 if ((status->position == 1) && (status->of_total == 100))
907 priv->done = status->position;
908 priv->total = status->of_total;
910 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
915 transfer_folder_cb (TnyFolder *folder, TnyFolderStore *into, gboolean cancelled, TnyFolder *new_folder, GError **err, gpointer user_data)
917 XFerFolderAsyncHelper *helper = NULL;
918 ModestMailOperation *self = NULL;
919 ModestMailOperationPrivate *priv = NULL;
921 helper = (XFerFolderAsyncHelper *) user_data;
922 self = helper->mail_op;
924 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
927 priv->error = g_error_copy (*err);
929 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
930 } else if (cancelled) {
931 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
932 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
933 MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
934 _("Transference of %s was cancelled."),
935 tny_folder_get_name (folder));
938 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
942 g_slice_free (XFerFolderAsyncHelper, helper);
943 g_object_unref (folder);
944 g_object_unref (into);
945 if (new_folder != NULL)
946 g_object_unref (new_folder);
948 /* Notify about operation end */
949 modest_mail_operation_notify_end (self);
953 modest_mail_operation_xfer_folder (ModestMailOperation *self,
955 TnyFolderStore *parent,
956 gboolean delete_original)
958 XFerFolderAsyncHelper *helper = NULL;
959 ModestMailOperationPrivate *priv = NULL;
960 ModestTnyFolderRules rules;
962 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
963 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
964 g_return_if_fail (TNY_IS_FOLDER (folder));
966 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
968 /* Pick references for async calls */
969 g_object_ref (folder);
970 g_object_ref (parent);
972 /* The moveable restriction is applied also to copy operation */
973 rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
974 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE) {
975 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
976 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
977 _("FIXME: unable to rename"));
979 /* Notify the queue */
980 modest_mail_operation_notify_end (self);
982 helper = g_slice_new0 (XFerFolderAsyncHelper);
983 helper->mail_op = self;
985 /* Move/Copy folder */
986 tny_folder_copy_async (folder,
988 tny_folder_get_name (folder),
991 transfer_folder_status_cb,
997 /* ******************************************************************* */
998 /* ************************** MSG ACTIONS ************************* */
999 /* ******************************************************************* */
1001 void modest_mail_operation_get_msg (ModestMailOperation *self,
1003 GetMsgAsyncUserCallback user_callback,
1006 GetMsgAsyncHelper *helper = NULL;
1008 ModestMailOperationPrivate *priv;
1010 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1011 g_return_if_fail (TNY_IS_HEADER (header));
1013 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1014 folder = tny_header_get_folder (header);
1016 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1018 /* Get message from folder */
1020 helper = g_slice_new0 (GetMsgAsyncHelper);
1021 helper->mail_op = self;
1022 helper->user_callback = user_callback;
1023 helper->pending_ops = 1;
1024 helper->user_data = user_data;
1026 tny_folder_get_msg_async (folder, header, get_msg_cb, get_msg_status_cb, helper);
1028 g_object_unref (G_OBJECT (folder));
1030 /* Set status failed and set an error */
1031 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1032 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1033 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1034 _("Error trying to get a message. No folder found for header"));
1039 get_msg_cb (TnyFolder *folder,
1045 GetMsgAsyncHelper *helper = NULL;
1046 ModestMailOperation *self = NULL;
1047 ModestMailOperationPrivate *priv = NULL;
1049 helper = (GetMsgAsyncHelper *) user_data;
1050 g_return_if_fail (helper != NULL);
1051 self = helper->mail_op;
1052 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
1053 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1055 helper->pending_ops--;
1057 /* Check errors and cancel */
1059 priv->error = g_error_copy (*error);
1060 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1064 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1065 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1066 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1067 _("Error trying to refresh the contents of %s"),
1068 tny_folder_get_name (folder));
1072 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1074 /* If user defined callback function was defined, call it */
1075 if (helper->user_callback) {
1076 helper->user_callback (self, NULL, msg, helper->user_data);
1081 if (helper->pending_ops == 0) {
1082 g_slice_free (GetMsgAsyncHelper, helper);
1084 /* Notify about operation end */
1085 modest_mail_operation_notify_end (self);
1090 get_msg_status_cb (GObject *obj,
1094 GetMsgAsyncHelper *helper = NULL;
1095 ModestMailOperation *self;
1096 ModestMailOperationPrivate *priv;
1098 g_return_if_fail (status != NULL);
1099 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
1101 helper = (GetMsgAsyncHelper *) user_data;
1102 g_return_if_fail (helper != NULL);
1104 /* Temporary FIX: useful when tinymail send us status
1105 information *after* calling the function callback */
1106 if (!MODEST_IS_MAIL_OPERATION (helper->mail_op))
1109 self = helper->mail_op;
1110 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1112 if ((status->position == 1) && (status->of_total == 100))
1118 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1121 /****************************************************/
1123 ModestMailOperation *mail_op;
1125 GetMsgAsyncUserCallback user_callback;
1127 GDestroyNotify notify;
1131 * Used by get_msgs_full_thread to emit the "progress-changed" signal
1132 * from the main loop. We call it inside an idle call to achieve that
1135 notify_get_msgs_full_observers (gpointer data)
1137 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
1139 g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1145 GetMsgAsyncUserCallback user_callback;
1149 ModestMailOperation *mail_op;
1150 } NotifyGetMsgsInfo;
1154 * Used by get_msgs_full_thread to call the user_callback for each
1155 * message that has been read
1158 notify_get_msgs_full (gpointer data)
1160 NotifyGetMsgsInfo *info;
1162 info = (NotifyGetMsgsInfo *) data;
1164 /* Call the user callback */
1165 info->user_callback (info->mail_op, info->header, info->msg, info->user_data);
1167 g_slice_free (NotifyGetMsgsInfo, info);
1173 * Used by get_msgs_full_thread to free al the thread resources and to
1174 * call the destroy function for the passed user_data
1177 get_msgs_full_destroyer (gpointer data)
1179 GetFullMsgsInfo *info;
1181 info = (GetFullMsgsInfo *) data;
1184 info->notify (info->user_data);
1187 g_object_unref (info->headers);
1188 g_slice_free (GetFullMsgsInfo, info);
1194 get_msgs_full_thread (gpointer thr_user_data)
1196 GetFullMsgsInfo *info;
1197 ModestMailOperationPrivate *priv = NULL;
1198 TnyIterator *iter = NULL;
1200 info = (GetFullMsgsInfo *) thr_user_data;
1201 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
1203 iter = tny_list_create_iterator (info->headers);
1204 while (!tny_iterator_is_done (iter)) {
1208 header = TNY_HEADER (tny_iterator_get_current (iter));
1209 folder = tny_header_get_folder (header);
1211 /* Get message from folder */
1214 /* The callback will call it per each header */
1215 msg = tny_folder_get_msg (folder, header, &(priv->error));
1220 /* notify progress */
1221 g_idle_add_full (G_PRIORITY_HIGH_IDLE,
1222 notify_get_msgs_full_observers,
1223 info->mail_op, NULL);
1225 /* The callback is the responsible for
1226 freeing the message */
1227 if (info->user_callback) {
1228 NotifyGetMsgsInfo *info_notify;
1229 info_notify = g_slice_new0 (NotifyGetMsgsInfo);
1230 info_notify->user_callback = info->user_callback;
1231 info_notify->mail_op = info->mail_op;
1232 info_notify->header = g_object_ref (header);
1233 info_notify->msg = g_object_ref (msg);
1234 info_notify->user_data = info->user_data;
1235 g_idle_add_full (G_PRIORITY_HIGH_IDLE,
1236 notify_get_msgs_full,
1239 g_object_unref (msg);
1242 /* Set status failed and set an error */
1243 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1244 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1245 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1246 "Error trying to get a message. No folder found for header");
1248 g_object_unref (header);
1249 tny_iterator_next (iter);
1252 /* Notify about operation end */
1253 g_idle_add (notify_update_account_queue, info->mail_op);
1255 /* Free thread resources. Will be called after all previous idles */
1256 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 1, get_msgs_full_destroyer, info, NULL);
1262 modest_mail_operation_get_msgs_full (ModestMailOperation *self,
1263 TnyList *header_list,
1264 GetMsgAsyncUserCallback user_callback,
1266 GDestroyNotify notify)
1269 ModestMailOperationPrivate *priv = NULL;
1270 GetFullMsgsInfo *info = NULL;
1271 gboolean size_ok = TRUE;
1273 GError *error = NULL;
1274 const gint KB = 1024;
1276 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1278 /* Init mail operation */
1279 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1280 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1282 priv->total = tny_list_get_length(header_list);
1284 /* Get msg size limit */
1285 max_size = modest_conf_get_int (modest_runtime_get_conf (),
1286 MODEST_CONF_MSG_SIZE_LIMIT,
1289 g_clear_error (&error);
1290 max_size = G_MAXINT;
1292 max_size = max_size * KB;
1295 /* Check message size limits. If there is only one message
1296 always retrieve it */
1297 if (tny_list_get_length (header_list) > 1) {
1300 iter = tny_list_create_iterator (header_list);
1301 while (!tny_iterator_is_done (iter) && size_ok) {
1302 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1303 if (tny_header_get_message_size (header) >= max_size)
1305 g_object_unref (header);
1306 tny_iterator_next (iter);
1308 g_object_unref (iter);
1312 /* Create the info */
1313 info = g_slice_new0 (GetFullMsgsInfo);
1314 info->mail_op = self;
1315 info->user_callback = user_callback;
1316 info->user_data = user_data;
1317 info->headers = g_object_ref (header_list);
1318 info->notify = notify;
1320 thread = g_thread_create (get_msgs_full_thread, info, FALSE, NULL);
1322 /* FIXME: the error msg is different for pop */
1323 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1324 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
1325 _("emev_ni_ui_imap_msg_sizelimit_error"));
1326 /* Remove from queue and free resources */
1327 modest_mail_operation_notify_end (self);
1335 modest_mail_operation_remove_msg (ModestMailOperation *self,
1337 gboolean remove_to_trash)
1340 ModestMailOperationPrivate *priv;
1342 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1343 g_return_if_fail (TNY_IS_HEADER (header));
1345 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1346 folder = tny_header_get_folder (header);
1348 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1350 /* Delete or move to trash */
1351 if (remove_to_trash) {
1352 TnyFolder *trash_folder;
1353 TnyStoreAccount *store_account;
1355 store_account = TNY_STORE_ACCOUNT (tny_folder_get_account (folder));
1356 trash_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT(store_account),
1357 TNY_FOLDER_TYPE_TRASH);
1362 headers = tny_simple_list_new ();
1363 tny_list_append (headers, G_OBJECT (header));
1364 g_object_unref (header);
1367 modest_mail_operation_xfer_msgs (self, headers, trash_folder, TRUE, NULL, NULL);
1368 g_object_unref (headers);
1369 /* g_object_unref (trash_folder); */
1371 ModestMailOperationPrivate *priv;
1373 /* Set status failed and set an error */
1374 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1375 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1376 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1377 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1378 _("Error trying to delete a message. Trash folder not found"));
1381 g_object_unref (G_OBJECT (store_account));
1383 tny_folder_remove_msg (folder, header, &(priv->error));
1385 tny_folder_sync(folder, TRUE, &(priv->error));
1390 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1392 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1395 g_object_unref (G_OBJECT (folder));
1397 /* Notify about operation end */
1398 modest_mail_operation_notify_end (self);
1402 transfer_msgs_status_cb (GObject *obj,
1406 XFerMsgAsyncHelper *helper = NULL;
1407 ModestMailOperation *self;
1408 ModestMailOperationPrivate *priv;
1410 g_return_if_fail (status != NULL);
1411 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
1413 helper = (XFerMsgAsyncHelper *) user_data;
1414 g_return_if_fail (helper != NULL);
1416 self = helper->mail_op;
1417 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1419 if ((status->position == 1) && (status->of_total == 100))
1422 priv->done = status->position;
1423 priv->total = status->of_total;
1425 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1430 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer user_data)
1432 XFerMsgAsyncHelper *helper;
1433 ModestMailOperation *self;
1434 ModestMailOperationPrivate *priv;
1436 helper = (XFerMsgAsyncHelper *) user_data;
1437 self = helper->mail_op;
1439 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1442 priv->error = g_error_copy (*err);
1444 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1445 } else if (cancelled) {
1446 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1447 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1448 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1449 _("Error trying to refresh the contents of %s"),
1450 tny_folder_get_name (folder));
1453 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1456 /* If user defined callback function was defined, call it */
1457 if (helper->user_callback) {
1458 helper->user_callback (priv->source, helper->user_data);
1462 g_object_unref (helper->headers);
1463 g_object_unref (helper->dest_folder);
1464 g_object_unref (helper->mail_op);
1465 g_slice_free (XFerMsgAsyncHelper, helper);
1466 g_object_unref (folder);
1468 /* Notify about operation end */
1469 modest_mail_operation_notify_end (self);
1473 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
1476 gboolean delete_original,
1477 XferMsgsAsynUserCallback user_callback,
1480 ModestMailOperationPrivate *priv;
1482 TnyFolder *src_folder;
1483 XFerMsgAsyncHelper *helper;
1486 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1487 g_return_if_fail (TNY_IS_LIST (headers));
1488 g_return_if_fail (TNY_IS_FOLDER (folder));
1490 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1493 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1495 /* Create the helper */
1496 helper = g_slice_new0 (XFerMsgAsyncHelper);
1497 helper->mail_op = g_object_ref(self);
1498 helper->dest_folder = g_object_ref(folder);
1499 helper->headers = g_object_ref(headers);
1500 helper->user_callback = user_callback;
1501 helper->user_data = user_data;
1503 /* Get source folder */
1504 iter = tny_list_create_iterator (headers);
1505 header = TNY_HEADER (tny_iterator_get_current (iter));
1506 src_folder = tny_header_get_folder (header);
1507 g_object_unref (header);
1508 g_object_unref (iter);
1510 /* Transfer messages */
1511 tny_folder_transfer_msgs_async (src_folder,
1516 transfer_msgs_status_cb,
1522 on_refresh_folder (TnyFolder *folder,
1527 ModestMailOperation *self;
1528 ModestMailOperationPrivate *priv;
1530 self = MODEST_MAIL_OPERATION (user_data);
1531 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1534 priv->error = g_error_copy (*error);
1535 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1540 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1541 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1542 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1543 _("Error trying to refresh the contents of %s"),
1544 tny_folder_get_name (folder));
1548 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1552 g_object_unref (folder);
1554 /* Notify about operation end */
1555 modest_mail_operation_notify_end (self);
1559 on_refresh_folder_status_update (GObject *obj,
1563 ModestMailOperation *self;
1564 ModestMailOperationPrivate *priv;
1566 g_return_if_fail (status != NULL);
1567 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
1569 /* Temporary FIX: useful when tinymail send us status
1570 information *after* calling the function callback */
1571 if (!MODEST_IS_MAIL_OPERATION (user_data))
1574 self = MODEST_MAIL_OPERATION (user_data);
1575 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1577 priv->done = status->position;
1578 priv->total = status->of_total;
1580 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1584 modest_mail_operation_refresh_folder (ModestMailOperation *self,
1587 ModestMailOperationPrivate *priv;
1589 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1591 /* Pick a reference */
1592 g_object_ref (folder);
1594 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1596 /* Refresh the folder. TODO: tinymail could issue a status
1597 updates before the callback call then this could happen. We
1598 must review the design */
1599 tny_folder_refresh_async (folder,
1601 on_refresh_folder_status_update,
1607 * It's used by the mail operation queue to notify the observers
1608 * attached to that signal that the operation finished. We need to use
1609 * that because tinymail does not give us the progress of a given
1610 * operation when it finishes (it directly calls the operation
1614 modest_mail_operation_notify_end (ModestMailOperation *self)
1616 /* Notify the observers about the mail opertation end */
1617 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1619 /* Notify the queue */
1620 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);