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, gboolean cancelled, TnyFolder *new_folder, 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);
876 g_object_unref (new_folder);
878 /* Notify the queue */
879 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
883 modest_mail_operation_xfer_folder (ModestMailOperation *self,
885 TnyFolderStore *parent,
886 gboolean delete_original)
888 ModestMailOperationPrivate *priv;
889 TnyFolder *new_folder = NULL;
890 ModestTnyFolderRules rules;
892 g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
893 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL);
894 g_return_val_if_fail (TNY_IS_FOLDER (folder), NULL);
896 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
898 /* The moveable restriction is applied also to copy operation */
899 rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
900 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE) {
901 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
902 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
903 _("FIXME: unable to rename"));
905 /* Move/Copy folder */
906 new_folder = tny_folder_copy (folder,
908 tny_folder_get_name (folder),
913 /* Notify the queue */
914 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
920 modest_mail_operation_xfer_folder_async (ModestMailOperation *self,
922 TnyFolderStore *parent,
923 gboolean delete_original)
925 XFerFolderAsyncHelper *helper = NULL;
926 ModestMailOperationPrivate *priv = NULL;
927 ModestTnyFolderRules rules;
929 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
930 g_return_if_fail (TNY_IS_FOLDER_STORE (parent));
931 g_return_if_fail (TNY_IS_FOLDER (folder));
933 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
935 /* The moveable restriction is applied also to copy operation */
936 rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
937 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE) {
938 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
939 MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
940 _("FIXME: unable to rename"));
942 helper = g_slice_new0 (XFerFolderAsyncHelper);
943 helper->mail_op = self;
945 /* Move/Copy folder */
946 tny_folder_copy_async (folder,
948 tny_folder_get_name (folder),
951 transfer_folder_status_cb,
957 /* ******************************************************************* */
958 /* ************************** MSG ACTIONS ************************* */
959 /* ******************************************************************* */
961 void modest_mail_operation_get_msg (ModestMailOperation *self,
963 GetMsgAsynUserCallback user_callback,
966 GetMsgAsyncHelper *helper = NULL;
968 ModestMailOperationPrivate *priv;
970 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
971 g_return_if_fail (TNY_IS_HEADER (header));
973 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
974 folder = tny_header_get_folder (header);
976 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
978 /* Get message from folder */
980 helper = g_slice_new0 (GetMsgAsyncHelper);
981 helper->mail_op = self;
982 helper->user_callback = user_callback;
983 helper->pending_ops = 1;
984 helper->user_data = user_data;
986 tny_folder_get_msg_async (folder, header, get_msg_cb, get_msg_status_cb, helper);
988 g_object_unref (G_OBJECT (folder));
990 /* Set status failed and set an error */
991 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
992 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
993 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
994 _("Error trying to get a message. No folder found for header"));
999 get_msg_cb (TnyFolder *folder,
1005 GetMsgAsyncHelper *helper = NULL;
1006 ModestMailOperation *self = NULL;
1007 ModestMailOperationPrivate *priv = NULL;
1009 helper = (GetMsgAsyncHelper *) user_data;
1010 g_return_if_fail (helper != NULL);
1011 self = helper->mail_op;
1012 g_return_if_fail (MODEST_IS_MAIL_OPERATION(self));
1013 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1015 helper->pending_ops--;
1017 /* Check errors and cancel */
1019 priv->error = g_error_copy (*error);
1020 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1024 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1025 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1026 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1027 _("Error trying to refresh the contents of %s"),
1028 tny_folder_get_name (folder));
1032 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1034 /* If user defined callback function was defined, call it */
1035 if (helper->user_callback) {
1036 helper->user_callback (priv->source, msg, helper->user_data);
1041 if (helper->pending_ops == 0) {
1042 g_slice_free (GetMsgAsyncHelper, helper);
1044 /* Notify the queue */
1045 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
1050 get_msg_status_cb (GObject *obj,
1054 GetMsgAsyncHelper *helper = NULL;
1055 ModestMailOperation *self;
1056 ModestMailOperationPrivate *priv;
1058 g_return_if_fail (status != NULL);
1059 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
1061 helper = (GetMsgAsyncHelper *) user_data;
1062 g_return_if_fail (helper != NULL);
1064 /* Temporary FIX: useful when tinymail send us status
1065 information *after* calling the function callback */
1066 if (!MODEST_IS_MAIL_OPERATION (helper->mail_op))
1069 self = helper->mail_op;
1070 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1072 if ((status->position == 1) && (status->of_total == 100))
1078 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1082 void modest_mail_operation_process_msg (ModestMailOperation *self,
1083 TnyList *header_list,
1084 GetMsgAsynUserCallback user_callback,
1087 ModestMailOperationPrivate *priv = NULL;
1088 GetMsgAsyncHelper *helper = NULL;
1089 TnyHeader *header = NULL;
1090 TnyFolder *folder = NULL;
1091 TnyIterator *iter = NULL;
1093 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1095 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1096 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1098 iter = tny_list_create_iterator (header_list);
1100 priv->total = tny_list_get_length(header_list);
1102 helper = g_slice_new0 (GetMsgAsyncHelper);
1103 helper->mail_op = self;
1104 helper->user_callback = user_callback;
1105 helper->pending_ops = priv->total;
1106 helper->user_data = user_data;
1108 while (!tny_iterator_is_done (iter)) {
1110 header = TNY_HEADER (tny_iterator_get_current (iter));
1111 folder = tny_header_get_folder (header);
1113 /* Get message from folder */
1115 /* The callback will call it per each header */
1116 tny_folder_get_msg_async (folder, header, get_msg_cb, update_process_msg_status_cb, helper);
1117 g_object_unref (G_OBJECT (folder));
1119 /* Set status failed and set an error */
1120 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1121 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1122 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1123 _("Error trying to get a message. No folder found for header"));
1125 /* Notify the queue */
1126 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
1129 g_slice_free (GetMsgAsyncHelper, helper);
1133 g_object_unref (header);
1134 tny_iterator_next (iter);
1139 update_process_msg_status_cb (GObject *obj,
1143 GetMsgAsyncHelper *helper = NULL;
1144 ModestMailOperation *self;
1145 ModestMailOperationPrivate *priv;
1147 g_return_if_fail (status != NULL);
1148 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
1150 helper = (GetMsgAsyncHelper *) user_data;
1151 g_return_if_fail (helper != NULL);
1153 /* Temporary FIX: useful when tinymail send us status
1154 information *after* calling the function callback */
1155 if (!MODEST_IS_MAIL_OPERATION (helper->mail_op))
1158 self = helper->mail_op;
1159 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1161 if ((status->position == 1) && (status->of_total == 100))
1164 if (status->of_total > 0)
1165 priv->done += status->position/status->of_total;
1167 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1173 modest_mail_operation_remove_msg (ModestMailOperation *self,
1175 gboolean remove_to_trash)
1178 ModestMailOperationPrivate *priv;
1180 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1181 g_return_if_fail (TNY_IS_HEADER (header));
1183 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1184 folder = tny_header_get_folder (header);
1186 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1188 /* Delete or move to trash */
1189 if (remove_to_trash) {
1190 TnyFolder *trash_folder;
1191 TnyStoreAccount *store_account;
1193 store_account = TNY_STORE_ACCOUNT (tny_folder_get_account (folder));
1194 trash_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT(store_account),
1195 TNY_FOLDER_TYPE_TRASH);
1200 headers = tny_simple_list_new ();
1201 tny_list_append (headers, G_OBJECT (header));
1202 g_object_unref (header);
1205 modest_mail_operation_xfer_msgs (self, headers, trash_folder, TRUE);
1206 g_object_unref (headers);
1207 /* g_object_unref (trash_folder); */
1209 ModestMailOperationPrivate *priv;
1211 /* Set status failed and set an error */
1212 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1213 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1214 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1215 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1216 _("Error trying to delete a message. Trash folder not found"));
1219 g_object_unref (G_OBJECT (store_account));
1221 tny_folder_remove_msg (folder, header, &(priv->error));
1223 tny_folder_sync(folder, TRUE, &(priv->error));
1228 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1230 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1233 g_object_unref (G_OBJECT (folder));
1235 /* Notify the queue */
1236 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
1240 transfer_msgs_status_cb (GObject *obj,
1244 XFerMsgAsyncHelper *helper = NULL;
1245 ModestMailOperation *self;
1246 ModestMailOperationPrivate *priv;
1248 g_return_if_fail (status != NULL);
1249 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_XFER_MSGS);
1251 helper = (XFerMsgAsyncHelper *) user_data;
1252 g_return_if_fail (helper != NULL);
1254 /* Temporary FIX: useful when tinymail send us status
1255 information *after* calling the function callback */
1256 if (!MODEST_IS_MAIL_OPERATION (helper->mail_op))
1259 self = helper->mail_op;
1260 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1262 if ((status->position == 1) && (status->of_total == 100))
1265 priv->done = status->position;
1266 priv->total = status->of_total;
1268 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1273 transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer user_data)
1275 XFerMsgAsyncHelper *helper;
1276 ModestMailOperation *self;
1277 ModestMailOperationPrivate *priv;
1279 helper = (XFerMsgAsyncHelper *) user_data;
1280 self = helper->mail_op;
1282 priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
1285 priv->error = g_error_copy (*err);
1287 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1288 } else if (cancelled) {
1289 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1290 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1291 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1292 _("Error trying to refresh the contents of %s"),
1293 tny_folder_get_name (folder));
1296 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1300 /* g_object_unref (helper->headers); */
1301 /* g_object_unref (helper->dest_folder); */
1302 /* g_object_unref (helper->mail_op); */
1303 g_slice_free (XFerMsgAsyncHelper, helper);
1304 g_object_unref (folder);
1306 /* Notify the queue */
1307 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
1311 modest_mail_operation_xfer_msgs (ModestMailOperation *self,
1314 gboolean delete_original)
1316 ModestMailOperationPrivate *priv;
1318 TnyFolder *src_folder;
1319 XFerMsgAsyncHelper *helper;
1322 g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
1323 g_return_if_fail (TNY_IS_LIST (headers));
1324 g_return_if_fail (TNY_IS_FOLDER (folder));
1326 /* Pick references for async calls */
1327 g_object_ref (folder);
1329 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1332 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1334 /* Create the helper */
1335 helper = g_slice_new0 (XFerMsgAsyncHelper);
1336 helper->mail_op = self;
1337 helper->dest_folder = g_object_ref(folder);
1338 helper->headers = g_object_ref(headers);
1340 /* Get source folder */
1341 iter = tny_list_create_iterator (headers);
1342 header = TNY_HEADER (tny_iterator_get_current (iter));
1343 src_folder = tny_header_get_folder (header);
1344 g_object_unref (header);
1345 g_object_unref (iter);
1347 /* Transfer messages */
1348 tny_folder_transfer_msgs_async (src_folder,
1353 transfer_msgs_status_cb,
1359 on_refresh_folder (TnyFolder *folder,
1364 ModestMailOperation *self;
1365 ModestMailOperationPrivate *priv;
1367 self = MODEST_MAIL_OPERATION (user_data);
1368 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1371 priv->error = g_error_copy (*error);
1372 priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
1377 priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
1378 g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
1379 MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1380 _("Error trying to refresh the contents of %s"),
1381 tny_folder_get_name (folder));
1385 priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
1389 g_object_unref (folder);
1391 /* Notify the queue */
1392 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
1396 on_refresh_folder_status_update (GObject *obj,
1400 ModestMailOperation *self;
1401 ModestMailOperationPrivate *priv;
1403 g_return_if_fail (status != NULL);
1404 g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
1406 /* Temporary FIX: useful when tinymail send us status
1407 information *after* calling the function callback */
1408 if (!MODEST_IS_MAIL_OPERATION (user_data))
1411 self = MODEST_MAIL_OPERATION (user_data);
1412 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1414 priv->done = status->position;
1415 priv->total = status->of_total;
1417 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
1421 modest_mail_operation_refresh_folder (ModestMailOperation *self,
1424 ModestMailOperationPrivate *priv;
1426 priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
1428 /* Pick a reference */
1429 g_object_ref (folder);
1431 priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
1433 /* Refresh the folder. TODO: tinymail could issue a status
1434 updates before the callback call then this could happen. We
1435 must review the design */
1436 tny_folder_refresh_async (folder,
1438 on_refresh_folder_status_update,
1443 _modest_mail_operation_notify_end (ModestMailOperation *self)
1445 g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);