* src/modest-ui-actions.[ch]:
[modest] / src / modest-mail-operation.c
index b496141..2d24e88 100644 (file)
@@ -38,6 +38,7 @@
 #include <tny-camel-stream.h>
 #include <tny-simple-list.h>
 #include <tny-send-queue.h>
+#include <tny-status.h>
 #include <camel/camel-stream-mem.h>
 #include <glib/gi18n.h>
 #include <modest-tny-account.h>
@@ -45,6 +46,7 @@
 #include <modest-runtime.h>
 #include "modest-text-utils.h"
 #include "modest-tny-msg.h"
+#include "modest-tny-folder.h"
 #include "modest-tny-platform-factory.h"
 #include "modest-marshal.h"
 #include "modest-error.h"
@@ -70,7 +72,8 @@ typedef struct _ModestMailOperationPrivate ModestMailOperationPrivate;
 struct _ModestMailOperationPrivate {
        guint                      done;
        guint                      total;
-       ModestMailOperationStatus  status;
+       ModestMailOperationStatus  status;      
+       ModestMailOperationId      id;          
        GError                    *error;
 };
 
@@ -78,9 +81,8 @@ struct _ModestMailOperationPrivate {
                                                    MODEST_TYPE_MAIL_OPERATION, \
                                                    ModestMailOperationPrivate))
 
-#define CHECK_EXCEPTION(priv, new_status, op)  if (priv->error) {\
+#define CHECK_EXCEPTION(priv, new_status)  if (priv->error) {\
                                                    priv->status = new_status;\
-                                                   op;\
                                                }
 
 typedef struct _RefreshFolderAsyncHelper
@@ -166,6 +168,7 @@ modest_mail_operation_init (ModestMailOperation *obj)
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
 
        priv->status   = MODEST_MAIL_OPERATION_STATUS_INVALID;
+       priv->id       = MODEST_MAIL_OPERATION_ID_UNKNOWN;
        priv->error    = NULL;
        priv->done     = 0;
        priv->total    = 0;
@@ -187,12 +190,32 @@ modest_mail_operation_finalize (GObject *obj)
 }
 
 ModestMailOperation*
-modest_mail_operation_new (void)
+modest_mail_operation_new (ModestMailOperationId id)
 {
-       return MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
+       ModestMailOperation *obj;
+       ModestMailOperationPrivate *priv;
+
+
+       obj = MODEST_MAIL_OPERATION(g_object_new(MODEST_TYPE_MAIL_OPERATION, NULL));
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
+
+       priv->id = id;
+
+       return obj;
 }
 
 
+
+ModestMailOperationId
+modest_mail_operation_get_id (ModestMailOperation *self)
+{
+       ModestMailOperationPrivate *priv;
+
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
+       
+       return priv->id;
+}
+
 void
 modest_mail_operation_send_mail (ModestMailOperation *self,
                                 TnyTransportAccount *transport_account,
@@ -229,7 +252,8 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self,
                                     const gchar *cc,  const gchar *bcc,
                                     const gchar *subject, const gchar *plain_body,
                                     const gchar *html_body,
-                                    const GList *attachments_list)
+                                    const GList *attachments_list,
+                                    TnyHeaderFlags priority_flags)
 {
        TnyMsg *new_msg;
        ModestMailOperationPrivate *priv = NULL;
@@ -243,7 +267,7 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self,
        /* Check parametters */
        if (to == NULL) {
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
-                            MODEST_MAIL_OPERATION_ERROR_MISSING_PARAMETER,
+                            MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
                             _("Error trying to send a mail. You need to set at least one recipient"));
                return;
        }
@@ -258,6 +282,9 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self,
                return;
        }
 
+       /* TODO: add priority handling. It's received in the priority_flags operator, and
+          it should have effect in the sending operation */
+
        /* Call mail operation */
        modest_mail_operation_send_mail (self, transport_account, new_msg);
 
@@ -265,6 +292,62 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self,
        g_object_unref (G_OBJECT (new_msg));
 }
 
+void
+modest_mail_operation_save_to_drafts (ModestMailOperation *self,
+                                     TnyTransportAccount *transport_account,
+                                     const gchar *from,  const gchar *to,
+                                     const gchar *cc,  const gchar *bcc,
+                                     const gchar *subject, const gchar *plain_body,
+                                     const gchar *html_body,
+                                     const GList *attachments_list,
+                                     TnyHeaderFlags priority_flags)
+{
+       TnyMsg *msg = NULL;
+       TnyFolder *folder = NULL;
+       ModestMailOperationPrivate *priv = NULL;
+       GError *err = NULL;
+
+       /* GList *node = NULL; */
+
+       g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
+       g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
+
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
+
+       if (html_body == NULL) {
+               msg = modest_tny_msg_new (to, from, cc, bcc, subject, plain_body, (GSList *) attachments_list); /* FIXME: attachments */
+       } else {
+               msg = modest_tny_msg_new_html_plain (to, from, cc, bcc, subject, html_body, plain_body, (GSList *) attachments_list);
+       }
+       if (!msg) {
+               g_printerr ("modest: failed to create a new msg\n");
+               goto cleanup;
+       }
+
+       folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account), TNY_FOLDER_TYPE_DRAFTS);
+       if (!folder) {
+               g_printerr ("modest: failed to find Drafts folder\n");
+               goto cleanup;
+       }
+       
+       tny_folder_add_msg (folder, msg, &err);
+       if (err) {
+               g_printerr ("modest: error adding msg to Drafts folder: %s",
+                           err->message);
+               g_error_free (err);
+               goto cleanup;
+       }
+
+       modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
+
+       /* Free */
+cleanup:
+       if (msg)
+               g_object_unref (G_OBJECT(msg));
+       if (folder)
+               g_object_unref (G_OBJECT(folder));
+}
+
 static void
 recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all_folders)
 {
@@ -478,17 +561,37 @@ modest_mail_operation_create_folder (ModestMailOperation *self,
                                     TnyFolderStore *parent,
                                     const gchar *name)
 {
+       ModestTnyFolderRules rules;
        ModestMailOperationPrivate *priv;
        TnyFolder *new_folder = NULL;
+       gboolean can_create = FALSE;
 
        g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL);
        g_return_val_if_fail (name, NULL);
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
 
-       /* Create the folder */
-       new_folder = tny_folder_store_create_folder (parent, name, &(priv->error));
-       CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED, return NULL);
+       /* Check parent */
+       if (!TNY_IS_FOLDER (parent)) {
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
+                            _("mail_in_ui_folder_create_error"));
+       } else {
+               /* Check folder rules */
+               rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
+               if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)
+                       g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                                    MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
+                                    _("mail_in_ui_folder_create_error"));
+               else
+                       can_create = TRUE;              
+       }
+
+       if (can_create) {
+               /* Create the folder */
+               new_folder = tny_folder_store_create_folder (parent, name, &(priv->error));
+               CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
+       }
 
        /* Notify the queue */
        modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
@@ -501,15 +604,24 @@ modest_mail_operation_remove_folder (ModestMailOperation *self,
                                     TnyFolder           *folder,
                                     gboolean             remove_to_trash)
 {
-       TnyFolderStore *parent;
        TnyAccount *account;
        ModestMailOperationPrivate *priv;
+       ModestTnyFolderRules rules;
 
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
        g_return_if_fail (TNY_IS_FOLDER (folder));
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
 
+       /* Check folder rules */
+       rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
+       if (rules & MODEST_FOLDER_RULES_FOLDER_NON_DELETABLE) {
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
+                            _("mail_in_ui_folder_delete_error"));
+               goto end;
+       }
+
        /* Get the account */
        account = tny_folder_get_account (folder);
 
@@ -523,16 +635,17 @@ modest_mail_operation_remove_folder (ModestMailOperation *self,
                                                                TNY_FOLDER_STORE (trash_folder), TRUE);
                g_object_unref (G_OBJECT (new_folder));
        } else {
-               parent = tny_folder_get_folder_store (folder);
+               TnyFolderStore *parent = tny_folder_get_folder_store (folder);
 
                tny_folder_store_remove_folder (parent, folder, &(priv->error));
-               CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED, );
+               CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
 
                if (parent)
                        g_object_unref (G_OBJECT (parent));
        }
        g_object_unref (G_OBJECT (account));
 
+ end:
        /* Notify the queue */
        modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
 }
@@ -543,6 +656,7 @@ modest_mail_operation_rename_folder (ModestMailOperation *self,
                                     const gchar *name)
 {
        ModestMailOperationPrivate *priv;
+       ModestTnyFolderRules rules;
 
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
        g_return_if_fail (TNY_IS_FOLDER_STORE (folder));
@@ -550,15 +664,18 @@ modest_mail_operation_rename_folder (ModestMailOperation *self,
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
 
-       /* FIXME: better error handling */
-       if (strrchr (name, '/') != NULL)
-               goto out;
-
-       /* Rename. Camel handles folder subscription/unsubscription */
-       tny_folder_set_name (folder, name, &(priv->error));
-       CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED, goto out);
+       /* Check folder rules */
+       rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
+       if (rules & MODEST_FOLDER_RULES_FOLDER_NON_RENAMEABLE) {
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
+                            _("FIXME: unable to rename"));
+       } else {
+               /* Rename. Camel handles folder subscription/unsubscription */
+               tny_folder_set_name (folder, name, &(priv->error));
+               CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
+       }
 
- out:
        /* Notify the queue */
        modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
  }
@@ -570,7 +687,8 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self,
                                   gboolean delete_original)
 {
        ModestMailOperationPrivate *priv;
-       TnyFolder *new_folder;
+       TnyFolder *new_folder = NULL;
+       ModestTnyFolderRules rules;
 
        g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), NULL);
        g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL);
@@ -578,11 +696,20 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self,
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
 
-       new_folder = tny_folder_copy (folder,
-                                     parent,
-                                     tny_folder_get_name (folder),
-                                     delete_original, 
-                                     &(priv->error));
+       /* The moveable restriction is applied also to copy operation */
+       rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
+       if (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE) {
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
+                            _("FIXME: unable to rename"));
+       } else {
+               /* Move/Copy folder */
+               new_folder = tny_folder_copy (folder,
+                                             parent,
+                                             tny_folder_get_name (folder),
+                                             delete_original, 
+                                             &(priv->error));
+       }
 
        /* Notify the queue */
        modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
@@ -620,7 +747,16 @@ modest_mail_operation_remove_msg (ModestMailOperation *self,
                trash_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT(store_account),
                                                                      TNY_FOLDER_TYPE_TRASH);
                if (trash_folder) {
-                       modest_mail_operation_xfer_msg (self, header, trash_folder, TRUE);
+                       TnyList *headers;
+
+                       /* Create list */
+                       headers = tny_simple_list_new ();
+                       tny_list_append (headers, G_OBJECT (header));
+                       g_object_unref (header);
+
+                       /* Move to trash */
+                       modest_mail_operation_xfer_msgs (self, headers, trash_folder, TRUE);
+                       g_object_unref (headers);
 /*                     g_object_unref (trash_folder); */
                } else {
                        ModestMailOperationPrivate *priv;
@@ -684,26 +820,24 @@ transfer_msgs_cb (TnyFolder *folder, GError **err, gpointer user_data)
 }
 
 void
-modest_mail_operation_xfer_msg (ModestMailOperation *self,
-                               TnyHeader *header, 
-                               TnyFolder *folder, 
-                               gboolean delete_original)
+modest_mail_operation_xfer_msgs (ModestMailOperation *self,
+                                TnyList *headers, 
+                                TnyFolder *folder, 
+                                gboolean delete_original)
 {
        ModestMailOperationPrivate *priv;
+       TnyIterator *iter;
        TnyFolder *src_folder;
-       TnyList *headers;
        XFerMsgAsyncHelper *helper;
+       TnyHeader *header;
 
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
-       g_return_if_fail (TNY_IS_HEADER (header));
+       g_return_if_fail (TNY_IS_LIST (headers));
        g_return_if_fail (TNY_IS_FOLDER (folder));
 
        /* Pick references for async calls */
        g_object_ref (folder);
 
-       headers = tny_simple_list_new ();
-       tny_list_prepend (headers, G_OBJECT (header));
-
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
        priv->total = 1;
        priv->done = 0;
@@ -715,7 +849,14 @@ modest_mail_operation_xfer_msg (ModestMailOperation *self,
        helper->dest_folder = folder;
        helper->headers = headers;
 
+       /* Get source folder */
+       iter = tny_list_create_iterator (headers);
+       header = TNY_HEADER (tny_iterator_get_current (iter));
        src_folder = tny_header_get_folder (header);
+       g_object_unref (header);
+       g_object_unref (iter);
+
+       /* Transfer messages */
        tny_folder_transfer_msgs_async (src_folder, 
                                        headers, 
                                        folder, 
@@ -761,24 +902,28 @@ on_refresh_folder (TnyFolder   *folder,
        modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
 }
 
-/* static void */
-/* on_refresh_folder_status_update (TnyFolder *folder, const gchar *msg, */
-/*                              gint num, gint total,  gpointer user_data) */
-/* { */
-/*     ModestMailOperation *self; */
-/*     ModestMailOperationPrivate *priv; */
+static void
+on_refresh_folder_status_update (GObject *obj,
+                                TnyStatus *status,  
+                                gpointer user_data)
+{
+       ModestMailOperation *self;
+       ModestMailOperationPrivate *priv;
 
-/*     self = MODEST_MAIL_OPERATION (user_data); */
-/*     priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self); */
+       g_return_if_fail (status != NULL);
+       g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
 
-/*     priv->done = num; */
-/*     priv->total = total; */
+       self = MODEST_MAIL_OPERATION (user_data);
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
 
-/*     if (num == 1 && total == 100) */
-/*             return; */
+       priv->done = status->position;
+       priv->total = status->of_total;
 
-/*     g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL); */
-/* } */
+       if (priv->done == 1 && priv->total == 100)
+               return;
+
+       g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
+}
 
 void 
 modest_mail_operation_refresh_folder  (ModestMailOperation *self,
@@ -798,8 +943,8 @@ modest_mail_operation_refresh_folder  (ModestMailOperation *self,
           must review the design */
        tny_folder_refresh_async (folder,
                                  on_refresh_folder,
-/*                               on_refresh_folder_status_update, */
-                                 NULL,
+                                 on_refresh_folder_status_update,
+/*                               NULL, */
                                  self);
 }