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-tny-account.h>
45 #include <modest-tny-send-queue.h>
46 #include <modest-runtime.h>
47 #include "modest-text-utils.h"
48 #include "modest-tny-msg.h"
49 #include "modest-tny-folder.h"
50 #include "modest-tny-platform-factory.h"
51 #include "modest-marshal.h"
52 #include "modest-error.h"
54 /* 'private'/'protected' functions */
55 static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
56 static void modest_mail_operation_init (ModestMailOperation *obj);
57 static void modest_mail_operation_finalize (GObject *obj);
59 static void update_process_msg_status_cb (GObject *obj,
62 static void get_msg_cb (TnyFolder *folder,
68 static void get_msg_status_cb (GObject *obj,
73 enum _ModestMailOperationSignals
75 PROGRESS_CHANGED_SIGNAL,
80 typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
81 struct _ModestMailOperationPrivate {
84 ModestMailOperationStatus status;
85 ModestMailOperationId id;
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 GetMsgAsynUserCallback user_callback;
105 typedef struct _RefreshFolderAsyncHelper
107 ModestMailOperation *mail_op;
112 } RefreshFolderAsyncHelper;
114 typedef struct _XFerMsgAsyncHelper
116 ModestMailOperation *mail_op;
118 TnyFolder *dest_folder;
120 } XFerMsgAsyncHelper;
122 typedef struct _XFerFolderAsyncHelper
124 ModestMailOperation *mail_op;
126 } XFerFolderAsyncHelper;
130 static GObjectClass *parent_class = NULL;
132 static guint signals[NUM_SIGNALS] = {0};
135 modest_mail_operation_get_type (void)
137 static GType my_type = 0;
139 static const GTypeInfo my_info = {
140 sizeof(ModestMailOperationClass),
141 NULL, /* base init */
142 NULL, /* base finalize */
143 (GClassInitFunc) modest_mail_operation_class_init,
144 NULL, /* class finalize */
145 NULL, /* class data */
146 sizeof(ModestMailOperation),
148 (GInstanceInitFunc) modest_mail_operation_init,
151 my_type = g_type_register_static (G_TYPE_OBJECT,
152 "ModestMailOperation",
159 modest_mail_operation_class_init (ModestMailOperationClass *klass)
161 GObjectClass *gobject_class;
162 gobject_class = (GObjectClass*) klass;
164 parent_class = g_type_class_peek_parent (klass);
165 gobject_class->finalize = modest_mail_operation_finalize;
167 g_type_class_add_private (gobject_class, sizeof(ModestMailOperationPrivate));
170 * ModestMailOperation::progress-changed
171 * @self: the #MailOperation that emits the signal
172 * @user_data: user data set when the signal handler was connected
174 * Emitted when the progress of a mail operation changes
176 signals[PROGRESS_CHANGED_SIGNAL] =
177 g_signal_new ("progress-changed",
178 G_TYPE_FROM_CLASS (gobject_class),
180 G_STRUCT_OFFSET (ModestMailOperationClass, progress_changed),
182 g_cclosure_marshal_VOID__VOID,
187 modest_mail_operation_init (ModestMailOperation *obj)
189 ModestMailOperationPrivate *priv;
191 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
193 priv->status = MODEST_MAIL_OPERATION_STATUS_INVALID;
194 priv->id = MODEST_MAIL_OPERATION_ID_UNKNOWN;
202 modest_mail_operation_finalize (GObject *obj)
204 ModestMailOperationPrivate *priv;
206 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
209 g_error_free (priv->error);
213 g_object_unref (priv->source);
217 G_OBJECT_CLASS(parent_class)->finalize (obj);
221 modest_mail_operation_new (ModestMailOperationId id,
224 ModestMailOperation *obj;
225 ModestMailOperationPrivate *priv;
227 obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
228 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
232 priv->source = g_object_ref(source);
238 ModestMailOperationId
239 modest_mail_operation_get_id (ModestMailOperation *self)
241 ModestMailOperationPrivate *priv;
243 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
249 modest_mail_operation_is_mine (ModestMailOperation *self,
252 ModestMailOperationPrivate *priv;
254 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
255 if (priv->source == NULL) return FALSE;
257 return priv->source == me;
262 modest_mail_operation_send_mail (ModestMailOperation *self,
263 TnyTransportAccount *transport_account,
266 TnySendQueue *send_queue;
268 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
269 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
270 g_return_if_fail (TNY_IS_MSG (msg));
272 send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
273 if (!TNY_IS_SEND_QUEUE(send_queue))
274 g_printerr ("modest: could not find send queue for account\n");
277 tny_send_queue_add (send_queue, msg, &err);
279 g_printerr ("modest: error adding msg to send queue: %s\n",
283 /* g_message ("modest: message added to send queue"); */
287 /* Notify the queue */
288 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
292 modest_mail_operation_send_new_mail (ModestMailOperation *self,
293 TnyTransportAccount *transport_account,
294 const gchar *from, const gchar *to,
295 const gchar *cc, const gchar *bcc,
296 const gchar *subject, const gchar *plain_body,
297 const gchar *html_body,
298 const GList *attachments_list,
299 TnyHeaderFlags priority_flags)
302 ModestMailOperationPrivate *priv = NULL;
303 /* GList *node = NULL; */
305 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
306 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
308 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
310 /* Check parametters */
312 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
313 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
314 _("Error trying to send a mail. You need to set at least one recipient"));
318 if (html_body == NULL) {
319 new_msg = modest_tny_msg_new (to, from, cc, bcc, subject, plain_body, (GSList *) attachments_list); /* FIXME: attachments */
321 new_msg = modest_tny_msg_new_html_plain (to, from, cc, bcc, subject, html_body, plain_body, (GSList *) attachments_list);
324 g_printerr ("modest: failed to create a new msg\n");
328 /* TODO: add priority handling. It's received in the priority_flags operator, and
329 it should have effect in the sending operation */
331 /* Call mail operation */
332 modest_mail_operation_send_mail (self, transport_account, new_msg);
335 g_object_unref (G_OBJECT (new_msg));
339 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
340 TnyTransportAccount *transport_account,
341 const gchar *from, const gchar *to,
342 const gchar *cc, const gchar *bcc,
343 const gchar *subject, const gchar *plain_body,
344 const gchar *html_body,
345 const GList *attachments_list,
346 TnyHeaderFlags priority_flags)
349 TnyFolder *folder = NULL;
350 ModestMailOperationPrivate *priv = NULL;
353 /* GList *node = NULL; */
355 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
356 g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
358 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
360 if (html_body == NULL) {
361 msg = modest_tny_msg_new (to, from, cc, bcc, subject, plain_body, (GSList *) attachments_list); /* FIXME: attachments */
363 msg = modest_tny_msg_new_html_plain (to, from, cc, bcc, subject, html_body, plain_body, (GSList *) attachments_list);
366 g_printerr ("modest: failed to create a new msg\n");
370 folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account), TNY_FOLDER_TYPE_DRAFTS);
372 g_printerr ("modest: failed to find Drafts folder\n");
376 tny_folder_add_msg (folder, msg, &err);
378 g_printerr ("modest: error adding msg to Drafts folder: %s",
384 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
389 g_object_unref (G_OBJECT(msg));
391 g_object_unref (G_OBJECT(folder));
396 ModestMailOperation *mail_op;
397 TnyStoreAccount *account;
402 recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all_folders)
405 TnyList *folders = tny_simple_list_new ();
407 tny_folder_store_get_folders (store, folders, query, NULL);
408 iter = tny_list_create_iterator (folders);
410 while (!tny_iterator_is_done (iter)) {
412 TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
414 tny_list_prepend (all_folders, G_OBJECT (folder));
415 recurse_folders (folder, query, all_folders);
416 g_object_unref (G_OBJECT (folder));
418 tny_iterator_next (iter);
420 g_object_unref (G_OBJECT (iter));
421 g_object_unref (G_OBJECT (folders));
425 * Used by update_account_thread to emit the signal from the main
426 * loop. We call it inside an idle call to achieve that
429 notify_update_account_observers (gpointer data)
431 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
433 g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
434 g_object_unref (mail_op);
440 * Used by update_account_thread to notify the queue from the main
441 * loop. We call it inside an idle call to achieve that
444 notify_update_account_queue (gpointer data)
446 ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
448 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
450 g_object_unref (mail_op);
456 update_account_thread (gpointer thr_user_data)
458 UpdateAccountInfo *info;
459 TnyList *all_folders = NULL;
460 TnyIterator *iter = NULL;
461 TnyFolderStoreQuery *query = NULL;
462 ModestMailOperationPrivate *priv;
464 info = (UpdateAccountInfo *) thr_user_data;
465 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
467 /* Get all the folders We can do it synchronously because
468 we're already running in a different thread than the UI */
469 all_folders = tny_simple_list_new ();
470 query = tny_folder_store_query_new ();
471 tny_folder_store_query_add_item (query, NULL, TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
472 tny_folder_store_get_folders (TNY_FOLDER_STORE (info->account),
477 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
481 iter = tny_list_create_iterator (all_folders);
482 while (!tny_iterator_is_done (iter)) {
483 TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter));
485 recurse_folders (folder, query, all_folders);
486 tny_iterator_next (iter);
488 g_object_unref (G_OBJECT (iter));
490 /* Refresh folders */
491 iter = tny_list_create_iterator (all_folders);
492 while (!tny_iterator_is_done (iter) && !priv->error) {
494 TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter));
496 /* Refresh the folder */
497 tny_folder_refresh (TNY_FOLDER (folder), &(priv->error));
500 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
502 /* Update status and notify. We need to call
503 the notification with an idle in order to
504 call it from the main loop. We need that in
505 order not to get into trouble with Gtk+ */
506 g_idle_add (notify_update_account_observers, g_object_ref (info->mail_op));
509 g_object_unref (G_OBJECT (folder));
510 tny_iterator_next (iter);
512 g_object_unref (G_OBJECT (iter));
514 /* Check if the operation was a success */
516 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
518 /* Update the last updated key */
519 modest_account_mgr_set_int (modest_runtime_get_account_mgr (),
520 tny_account_get_id (TNY_ACCOUNT (info->account)),
521 MODEST_ACCOUNT_LAST_UPDATED,
527 /* Notify the queue */
528 g_idle_add (notify_update_account_queue, g_object_ref (info->mail_op));
531 g_object_unref (query);
532 g_object_unref (all_folders);
533 g_object_unref (info->mail_op);
534 g_object_unref (info->account);
535 g_slice_free (UpdateAccountInfo, info);
541 modest_mail_operation_update_account (ModestMailOperation *self,
542 const gchar *account_name)
545 UpdateAccountInfo *info;
546 ModestMailOperationPrivate *priv;
547 TnyStoreAccount *modest_account;
549 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE);
550 g_return_val_if_fail (account_name, FALSE);
552 /* Init mail operation. Set total and done to 0, and do not
553 update them, this way the progress objects will know that
554 we have no clue about the number of the objects */
555 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
558 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
560 /* Get the Modest account */
561 modest_account = (TnyStoreAccount *)
562 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store (),
564 TNY_ACCOUNT_TYPE_STORE);
566 if (!modest_account) {
567 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
568 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
573 /* Create the helper object */
574 info = g_slice_new (UpdateAccountInfo);
575 info->mail_op = g_object_ref (self);
576 info->account = modest_account;
577 info->user_data = NULL;
579 thread = g_thread_create (update_account_thread, info, FALSE, NULL);
584 ModestMailOperationStatus
585 modest_mail_operation_get_status (ModestMailOperation *self)
587 ModestMailOperationPrivate *priv;
589 g_return_val_if_fail (self, MODEST_MAIL_OPERATION_STATUS_INVALID);
590 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self),
591 MODEST_MAIL_OPERATION_STATUS_INVALID);
593 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
598 modest_mail_operation_get_error (ModestMailOperation *self)
600 ModestMailOperationPrivate *priv;
602 g_return_val_if_fail (self, NULL);
603 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
605 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
610 modest_mail_operation_cancel (ModestMailOperation *self)
612 ModestMailOperationPrivate *priv;
614 if (!MODEST_IS_MAIL_OPERATION (self)) {
615 g_warning ("%s: invalid parametter", G_GNUC_FUNCTION);
619 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
621 /* TODO: Tinymail does not support cancel operation */
624 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
626 /* Notify the queue */
627 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
633 modest_mail_operation_get_task_done (ModestMailOperation *self)
635 ModestMailOperationPrivate *priv;
637 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), 0);
639 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
644 modest_mail_operation_get_task_total (ModestMailOperation *self)
646 ModestMailOperationPrivate *priv;
648 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), 0);
650 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
655 modest_mail_operation_is_finished (ModestMailOperation *self)
657 ModestMailOperationPrivate *priv;
658 gboolean retval = FALSE;
660 if (!MODEST_IS_MAIL_OPERATION (self)) {
661 g_warning ("%s: invalid parametter", G_GNUC_FUNCTION);
665 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
667 if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS ||
668 priv->status == MODEST_MAIL_OPERATION_STATUS_FAILED ||
669 priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED ||
670 priv->status == MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS) {
679 /* ******************************************************************* */
680 /* ************************** STORE ACTIONS ************************* */
681 /* ******************************************************************* */
685 modest_mail_operation_create_folder (ModestMailOperation *self,
686 TnyFolderStore *parent,
689 ModestTnyFolderRules rules;
690 ModestMailOperationPrivate *priv;
691 TnyFolder *new_folder = NULL;
692 gboolean can_create = FALSE;
694 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL);
695 g_return_val_if_fail (name, NULL);
697 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
700 if (!TNY_IS_FOLDER (parent)) {
701 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
702 MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
703 _("mail_in_ui_folder_create_error"));
705 /* Check folder rules */
706 rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
707 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)
708 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
709 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
710 _("mail_in_ui_folder_create_error"));
716 /* Create the folder */
717 new_folder = tny_folder_store_create_folder (parent, name, &(priv->error));
718 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
721 /* Notify the queue */
722 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
728 modest_mail_operation_remove_folder (ModestMailOperation *self,
730 gboolean remove_to_trash)
733 ModestMailOperationPrivate *priv;
734 ModestTnyFolderRules rules;
736 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
737 g_return_if_fail (TNY_IS_FOLDER (folder));
739 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
741 /* Check folder rules */
742 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
743 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
744 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
745 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
746 _("mail_in_ui_folder_delete_error"));
750 /* Get the account */
751 account = tny_folder_get_account (folder);
753 /* Delete folder or move to trash */
754 if (remove_to_trash) {
755 TnyFolder *trash_folder = NULL;
756 /* TnyFolder *trash_folder, *new_folder; */
757 trash_folder = modest_tny_account_get_special_folder (account,
758 TNY_FOLDER_TYPE_TRASH);
759 /* TODO: error_handling */
760 modest_mail_operation_xfer_folder (self, folder,
761 TNY_FOLDER_STORE (trash_folder), TRUE);
762 /* new_folder = modest_mail_operation_xfer_folder (self, folder, */
763 /* TNY_FOLDER_STORE (trash_folder), TRUE); */
764 /* g_object_unref (G_OBJECT (new_folder)); */
766 TnyFolderStore *parent = tny_folder_get_folder_store (folder);
768 tny_folder_store_remove_folder (parent, folder, &(priv->error));
769 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
772 g_object_unref (G_OBJECT (parent));
774 g_object_unref (G_OBJECT (account));
777 /* Notify the queue */
778 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
782 modest_mail_operation_rename_folder (ModestMailOperation *self,
786 ModestMailOperationPrivate *priv;
787 ModestTnyFolderRules rules;
789 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
790 g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
791 g_return_if_fail (name);
793 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
795 /* Check folder rules */
796 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
797 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
798 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
799 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
800 _("FIXME: unable to rename"));
802 /* Rename. Camel handles folder subscription/unsubscription */
803 tny_folder_set_name (folder, name, &(priv->error));
804 CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
807 /* Notify the queue */
808 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
812 transfer_folder_status_cb (GObject *obj,
816 XFerMsgAsyncHelper *helper = NULL;
817 ModestMailOperation *self;
818 ModestMailOperationPrivate *priv;
820 g_return_if_fail (status != NULL);
821 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_COPY_FOLDER);
823 helper = (XFerMsgAsyncHelper *) user_data;
824 g_return_if_fail (helper != NULL);
826 /* Temporary FIX: useful when tinymail send us status
827 information *after* calling the function callback */
828 if (!MODEST_IS_MAIL_OPERATION (helper->mail_op))
831 self = helper->mail_op;
832 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
834 if ((status->position == 1) && (status->of_total == 100))
837 priv->done = status->position;
838 priv->total = status->of_total;
841 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
846 transfer_folder_cb (TnyFolder *folder, TnyFolderStore *into, const gchar *new_name, gboolean cancelled, GError **err, gpointer user_data)
848 XFerFolderAsyncHelper *helper = NULL;
849 ModestMailOperation *self = NULL;
850 ModestMailOperationPrivate *priv = NULL;
852 helper = (XFerFolderAsyncHelper *) user_data;
853 self = helper->mail_op;
855 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
858 priv->error = g_error_copy (*err);
860 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
861 } else if (cancelled) {
862 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
863 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
864 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
865 _("Error trying to refresh the contents of %s"),
866 tny_folder_get_name (folder));
869 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
873 g_slice_free (XFerFolderAsyncHelper, helper);
874 g_object_unref (folder);
875 g_object_unref (into);
877 /* Notify the queue */
878 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
882 modest_mail_operation_xfer_folder (ModestMailOperation *self,
884 TnyFolderStore *parent,
885 gboolean delete_original)
887 ModestMailOperationPrivate *priv;
888 TnyFolder *new_folder = NULL;
889 ModestTnyFolderRules rules;
891 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
892 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL);
893 g_return_val_if_fail (TNY_IS_FOLDER (folder), NULL);
895 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
897 /* The moveable restriction is applied also to copy operation */
898 rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
899 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE) {
900 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
901 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
902 _("FIXME: unable to rename"));
904 /* Move/Copy folder */
905 new_folder = tny_folder_copy (folder,
907 tny_folder_get_name (folder),
912 /* Notify the queue */
913 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
919 modest_mail_operation_xfer_folder_async (ModestMailOperation *self,
921 TnyFolderStore *parent,
922 gboolean delete_original)
924 XFerFolderAsyncHelper *helper = NULL;
925 ModestMailOperationPrivate *priv = NULL;
926 ModestTnyFolderRules rules;
928 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
929 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
930 g_return_if_fail (TNY_IS_FOLDER (folder));
932 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
934 /* The moveable restriction is applied also to copy operation */
935 rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
936 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE) {
937 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
938 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
939 _("FIXME: unable to rename"));
941 helper = g_slice_new0 (XFerFolderAsyncHelper);
942 helper->mail_op = self;
944 /* Move/Copy folder */
945 tny_folder_copy_async (folder,
947 tny_folder_get_name (folder),
950 transfer_folder_status_cb,
956 /* ******************************************************************* */
957 /* ************************** MSG ACTIONS ************************* */
958 /* ******************************************************************* */
960 void modest_mail_operation_get_msg (ModestMailOperation *self,
962 GetMsgAsynUserCallback user_callback,
965 GetMsgAsyncHelper *helper = NULL;
967 ModestMailOperationPrivate *priv;
969 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
970 g_return_if_fail (TNY_IS_HEADER (header));
972 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
973 folder = tny_header_get_folder (header);
975 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
977 /* Get message from folder */
979 helper = g_slice_new0 (GetMsgAsyncHelper);
980 helper->mail_op = self;
981 helper->user_callback = user_callback;
982 helper->pending_ops = 1;
983 helper->user_data = user_data;
985 tny_folder_get_msg_async (folder, header, get_msg_cb, get_msg_status_cb, helper);
987 g_object_unref (G_OBJECT (folder));
989 /* Set status failed and set an error */
990 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
991 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
992 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
993 _("Error trying to get a message. No folder found for header"));
998 get_msg_cb (TnyFolder *folder,
1004 GetMsgAsyncHelper *helper = NULL;
1005 ModestMailOperation *self = NULL;
1006 ModestMailOperationPrivate *priv = NULL;
1008 helper = (GetMsgAsyncHelper *) user_data;
1009 g_return_if_fail (helper != NULL);
1010 self = helper->mail_op;
1011 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
1012 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1014 helper->pending_ops--;
1016 /* Check errors and cancel */
1018 priv->error = g_error_copy (*error);
1019 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1023 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1024 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1025 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1026 _("Error trying to refresh the contents of %s"),
1027 tny_folder_get_name (folder));
1031 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1033 /* If user defined callback function was defined, call it */
1034 if (helper->user_callback) {
1035 helper->user_callback (priv->source, msg, helper->user_data);
1040 if (helper->pending_ops == 0) {
1041 g_slice_free (GetMsgAsyncHelper, helper);
1043 /* Notify the queue */
1044 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
1049 get_msg_status_cb (GObject *obj,
1053 GetMsgAsyncHelper *helper = NULL;
1054 ModestMailOperation *self;
1055 ModestMailOperationPrivate *priv;
1057 g_return_if_fail (status != NULL);
1058 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
1060 helper = (GetMsgAsyncHelper *) user_data;
1061 g_return_if_fail (helper != NULL);
1063 /* Temporary FIX: useful when tinymail send us status
1064 information *after* calling the function callback */
1065 if (!MODEST_IS_MAIL_OPERATION (helper->mail_op))
1068 self = helper->mail_op;
1069 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1071 if ((status->position == 1) && (status->of_total == 100))
1077 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1081 void modest_mail_operation_process_msg (ModestMailOperation *self,
1082 TnyList *header_list,
1083 GetMsgAsynUserCallback user_callback,
1086 ModestMailOperationPrivate *priv = NULL;
1087 GetMsgAsyncHelper *helper = NULL;
1088 TnyHeader *header = NULL;
1089 TnyFolder *folder = NULL;
1090 TnyIterator *iter = NULL;
1092 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1094 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1095 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1097 iter = tny_list_create_iterator (header_list);
1099 priv->total = tny_list_get_length(header_list);
1101 helper = g_slice_new0 (GetMsgAsyncHelper);
1102 helper->mail_op = self;
1103 helper->user_callback = user_callback;
1104 helper->pending_ops = priv->total;
1105 helper->user_data = user_data;
1107 while (!tny_iterator_is_done (iter)) {
1109 header = TNY_HEADER (tny_iterator_get_current (iter));
1110 folder = tny_header_get_folder (header);
1112 /* Get message from folder */
1114 /* The callback will call it per each header */
1115 tny_folder_get_msg_async (folder, header, get_msg_cb, update_process_msg_status_cb, helper);
1116 g_object_unref (G_OBJECT (folder));
1118 /* Set status failed and set an error */
1119 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1120 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1121 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1122 _("Error trying to get a message. No folder found for header"));
1124 /* Notify the queue */
1125 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
1128 g_slice_free (GetMsgAsyncHelper, helper);
1132 g_object_unref (header);
1133 tny_iterator_next (iter);
1138 update_process_msg_status_cb (GObject *obj,
1142 GetMsgAsyncHelper *helper = NULL;
1143 ModestMailOperation *self;
1144 ModestMailOperationPrivate *priv;
1146 g_return_if_fail (status != NULL);
1147 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
1149 helper = (GetMsgAsyncHelper *) user_data;
1150 g_return_if_fail (helper != NULL);
1152 /* Temporary FIX: useful when tinymail send us status
1153 information *after* calling the function callback */
1154 if (!MODEST_IS_MAIL_OPERATION (helper->mail_op))
1157 self = helper->mail_op;
1158 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1160 if ((status->position == 1) && (status->of_total == 100))
1163 if (status->of_total > 0)
1164 priv->done += status->position/status->of_total;
1166 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1172 modest_mail_operation_remove_msg (ModestMailOperation *self,
1174 gboolean remove_to_trash)
1177 ModestMailOperationPrivate *priv;
1179 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1180 g_return_if_fail (TNY_IS_HEADER (header));
1182 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1183 folder = tny_header_get_folder (header);
1185 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1187 /* Delete or move to trash */
1188 if (remove_to_trash) {
1189 TnyFolder *trash_folder;
1190 TnyStoreAccount *store_account;
1192 store_account = TNY_STORE_ACCOUNT (tny_folder_get_account (folder));
1193 trash_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT(store_account),
1194 TNY_FOLDER_TYPE_TRASH);
1199 headers = tny_simple_list_new ();
1200 tny_list_append (headers, G_OBJECT (header));
1201 g_object_unref (header);
1204 modest_mail_operation_xfer_msgs (self, headers, trash_folder, TRUE);
1205 g_object_unref (headers);
1206 /* g_object_unref (trash_folder); */
1208 ModestMailOperationPrivate *priv;
1210 /* Set status failed and set an error */
1211 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1212 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1213 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1214 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1215 _("Error trying to delete a message. Trash folder not found"));
1218 g_object_unref (G_OBJECT (store_account));
1220 tny_folder_remove_msg (folder, header, &(priv->error));
1222 tny_folder_sync(folder, TRUE, &(priv->error));
1227 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1229 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1232 g_object_unref (G_OBJECT (folder));
1234 /* Notify the queue */
1235 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
1239 transfer_msgs_status_cb (GObject *obj,
1243 XFerMsgAsyncHelper *helper = NULL;
1244 ModestMailOperation *self;
1245 ModestMailOperationPrivate *priv;
1247 g_return_if_fail (status != NULL);
1248 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
1250 helper = (XFerMsgAsyncHelper *) user_data;
1251 g_return_if_fail (helper != NULL);
1253 /* Temporary FIX: useful when tinymail send us status
1254 information *after* calling the function callback */
1255 if (!MODEST_IS_MAIL_OPERATION (helper->mail_op))
1258 self = helper->mail_op;
1259 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1261 if ((status->position == 1) && (status->of_total == 100))
1264 priv->done = status->position;
1265 priv->total = status->of_total;
1267 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1272 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer user_data)
1274 XFerMsgAsyncHelper *helper;
1275 ModestMailOperation *self;
1276 ModestMailOperationPrivate *priv;
1278 helper = (XFerMsgAsyncHelper *) user_data;
1279 self = helper->mail_op;
1281 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1284 priv->error = g_error_copy (*err);
1286 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1287 } else if (cancelled) {
1288 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1289 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1290 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1291 _("Error trying to refresh the contents of %s"),
1292 tny_folder_get_name (folder));
1295 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1299 /* g_object_unref (helper->headers); */
1300 /* g_object_unref (helper->dest_folder); */
1301 /* g_object_unref (helper->mail_op); */
1302 g_slice_free (XFerMsgAsyncHelper, helper);
1303 g_object_unref (folder);
1305 /* Notify the queue */
1306 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
1310 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
1313 gboolean delete_original)
1315 ModestMailOperationPrivate *priv;
1317 TnyFolder *src_folder;
1318 XFerMsgAsyncHelper *helper;
1321 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1322 g_return_if_fail (TNY_IS_LIST (headers));
1323 g_return_if_fail (TNY_IS_FOLDER (folder));
1325 /* Pick references for async calls */
1326 g_object_ref (folder);
1328 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1331 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1333 /* Create the helper */
1334 helper = g_slice_new0 (XFerMsgAsyncHelper);
1335 helper->mail_op = self;
1336 helper->dest_folder = g_object_ref(folder);
1337 helper->headers = g_object_ref(headers);
1339 /* Get source folder */
1340 iter = tny_list_create_iterator (headers);
1341 header = TNY_HEADER (tny_iterator_get_current (iter));
1342 src_folder = tny_header_get_folder (header);
1343 g_object_unref (header);
1344 g_object_unref (iter);
1346 /* Transfer messages */
1347 tny_folder_transfer_msgs_async (src_folder,
1352 transfer_msgs_status_cb,
1358 on_refresh_folder (TnyFolder *folder,
1363 ModestMailOperation *self;
1364 ModestMailOperationPrivate *priv;
1366 self = MODEST_MAIL_OPERATION (user_data);
1367 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1370 priv->error = g_error_copy (*error);
1371 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1376 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1377 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1378 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1379 _("Error trying to refresh the contents of %s"),
1380 tny_folder_get_name (folder));
1384 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1388 g_object_unref (folder);
1390 /* Notify the queue */
1391 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
1395 on_refresh_folder_status_update (GObject *obj,
1399 ModestMailOperation *self;
1400 ModestMailOperationPrivate *priv;
1402 g_return_if_fail (status != NULL);
1403 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
1405 /* Temporary FIX: useful when tinymail send us status
1406 information *after* calling the function callback */
1407 if (!MODEST_IS_MAIL_OPERATION (user_data))
1410 self = MODEST_MAIL_OPERATION (user_data);
1411 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1413 priv->done = status->position;
1414 priv->total = status->of_total;
1416 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1420 modest_mail_operation_refresh_folder (ModestMailOperation *self,
1423 ModestMailOperationPrivate *priv;
1425 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1427 /* Pick a reference */
1428 g_object_ref (folder);
1430 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1432 /* Refresh the folder. TODO: tinymail could issue a status
1433 updates before the callback call then this could happen. We
1434 must review the design */
1435 tny_folder_refresh_async (folder,
1437 on_refresh_folder_status_update,
1442 _modest_mail_operation_notify_end (ModestMailOperation *self)
1444 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);