Fix some compiling errors.
[modest] / src / modest-mail-operation.c
index 363a043..c86338d 100644 (file)
@@ -27,8 +27,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "modest-mail-operation.h"
-/* include other impl specific header files */
 #include <string.h>
 #include <stdarg.h>
 #include <tny-mime-part.h>
@@ -52,6 +50,7 @@
 #include "modest-tny-platform-factory.h"
 #include "modest-marshal.h"
 #include "modest-error.h"
+#include "modest-mail-operation.h"
 
 #define KB 1024
 
@@ -180,7 +179,7 @@ modest_mail_operation_init (ModestMailOperation *obj)
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(obj);
 
-       priv->account  = NULL;
+       priv->account        = NULL;
        priv->status         = MODEST_MAIL_OPERATION_STATUS_INVALID;
        priv->op_type        = MODEST_MAIL_OPERATION_TYPE_UNKNOWN;
        priv->error          = NULL;
@@ -332,8 +331,8 @@ modest_mail_operation_cancel (ModestMailOperation *self)
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
 
-       /* TODO: Tinymail does not support cancel operation  */
-/*     tny_account_cancel (); */
+       /* cancel current operation in account */
+       tny_account_cancel (priv->account);
 
        /* Set new status */
        priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
@@ -459,18 +458,12 @@ modest_mail_operation_send_mail (ModestMailOperation *self,
        priv->account = g_object_ref (transport_account);
 
        send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
-       if (!TNY_IS_SEND_QUEUE(send_queue))
-               g_printerr ("modest: could not find send queue for account\n");
-       else {
-               GError *err = NULL;
-               tny_send_queue_add (send_queue, msg, &err);
-               if (err) {
-                       g_printerr ("modest: error adding msg to send queue: %s\n",
-                                   err->message);
-                       g_error_free (err);
-               } else {
-                       /* g_message ("modest: message added to send queue"); */
-               }
+       if (!TNY_IS_SEND_QUEUE(send_queue)) {
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
+                            "modest: could not find send queue for account\n");
+       } else {
+               tny_send_queue_add (send_queue, msg, &(priv->error));
        }
 
        /* Notify about operation end */
@@ -480,6 +473,7 @@ modest_mail_operation_send_mail (ModestMailOperation *self,
 void
 modest_mail_operation_send_new_mail (ModestMailOperation *self,
                                     TnyTransportAccount *transport_account,
+                                    TnyMsg *draft_msg,
                                     const gchar *from,  const gchar *to,
                                     const gchar *cc,  const gchar *bcc,
                                     const gchar *subject, const gchar *plain_body,
@@ -488,6 +482,7 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self,
                                     TnyHeaderFlags priority_flags)
 {
        TnyMsg *new_msg = NULL;
+       TnyFolder *folder = NULL;
        ModestMailOperationPrivate *priv = NULL;
 
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
@@ -524,6 +519,15 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self,
        /* Call mail operation */
        modest_mail_operation_send_mail (self, transport_account, new_msg);
 
+       folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account), TNY_FOLDER_TYPE_DRAFTS);
+       if (folder) {
+               if (draft_msg != NULL) {
+                       TnyHeader *header = tny_msg_get_header (draft_msg);
+                       tny_folder_remove_msg (folder, header, NULL);
+                       g_object_unref (header);
+               }
+       }
+
        /* Free */
        g_object_unref (G_OBJECT (new_msg));
 }
@@ -531,6 +535,7 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self,
 void
 modest_mail_operation_save_to_drafts (ModestMailOperation *self,
                                      TnyTransportAccount *transport_account,
+                                     TnyMsg *draft_msg,
                                      const gchar *from,  const gchar *to,
                                      const gchar *cc,  const gchar *bcc,
                                      const gchar *subject, const gchar *plain_body,
@@ -541,7 +546,6 @@ modest_mail_operation_save_to_drafts (ModestMailOperation *self,
        TnyMsg *msg = NULL;
        TnyFolder *folder = NULL;
        ModestMailOperationPrivate *priv = NULL;
-       GError *err = NULL;
 
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
        g_return_if_fail (TNY_IS_TRANSPORT_ACCOUNT (transport_account));
@@ -557,32 +561,37 @@ modest_mail_operation_save_to_drafts (ModestMailOperation *self,
                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;
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
+                            "modest: failed to create a new msg\n");
+               goto end;
        }
 
        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;
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
+                            "modest: failed to create a new msg\n");
+               goto end;
        }
 
-       modest_mail_operation_notify_end (self);
+       if (draft_msg != NULL) {
+               TnyHeader *header = tny_msg_get_header (draft_msg);
+               tny_folder_remove_msg (folder, header, NULL);
+               g_object_unref (header);
+       }
+       
+       tny_folder_add_msg (folder, msg, &(priv->error));
+       if (priv->error)
+               goto end;
 
-       /* Free */
-cleanup:
+end:
        if (msg)
                g_object_unref (G_OBJECT(msg));
        if (folder)
                g_object_unref (G_OBJECT(folder));
+
+       modest_mail_operation_notify_end (self);
 }
 
 typedef struct 
@@ -618,6 +627,9 @@ G_DEFINE_TYPE_WITH_CODE (InternalFolderObserver,
 static void
 foreach_add_item (gpointer header, gpointer user_data)
 {
+       /* printf("DEBUG: %s: header subject=%s\n", 
+        * __FUNCTION__, tny_header_get_subject(TNY_HEADER(header)));
+        */
        tny_list_prepend (TNY_LIST (user_data), 
                          g_object_ref (G_OBJECT (header)));
 }
@@ -626,6 +638,8 @@ foreach_add_item (gpointer header, gpointer user_data)
 static void
 internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *change)
 {
+       InternalFolderObserver *derived = (InternalFolderObserver *)self;
+       
        TnyFolderChangeChanged changed;
 
        changed = tny_folder_change_get_changed (change);
@@ -637,9 +651,13 @@ internal_folder_observer_update (TnyFolderObserver *self, TnyFolderChange *chang
                list = tny_simple_list_new ();
                tny_folder_change_get_added_headers (change, list);
 
+               /* printf ("DEBUG: %s: Calling foreach with a list of size=%d\n", 
+                *      __FUNCTION__, tny_list_get_length(list));
+                */
+                
                /* Add them to the folder observer */
                tny_list_foreach (list, foreach_add_item, 
-                                 ((InternalFolderObserver *)self)->new_headers);
+                                 derived->new_headers);
 
                g_object_unref (G_OBJECT (list));
        }
@@ -783,6 +801,7 @@ update_account_thread (gpointer thr_user_data)
        TnyIterator *iter = NULL;
        TnyFolderStoreQuery *query = NULL;
        ModestMailOperationPrivate *priv;
+       ModestTnySendQueue *send_queue;
 
        info = (UpdateAccountInfo *) thr_user_data;
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
@@ -790,7 +809,7 @@ update_account_thread (gpointer thr_user_data)
        /* Get account and set it into mail_operation */
        priv->account = g_object_ref (info->account);
 
-       /* Get all the folders We can do it synchronously because
+       /* Get all the folders. We can do it synchronously because
           we're already running in a different thread than the UI */
        all_folders = tny_simple_list_new ();
        query = tny_folder_store_query_new ();
@@ -814,7 +833,7 @@ update_account_thread (gpointer thr_user_data)
        g_object_unref (G_OBJECT (iter));
 
        /* Update status and notify. We need to call the notification
-          with a source functopm in order to call it from the main
+          with a source function in order to call it from the main
           loop. We need that in order not to get into trouble with
           Gtk+. We use a timeout in order to provide more status
           information, because the sync tinymail call does not
@@ -830,8 +849,18 @@ update_account_thread (gpointer thr_user_data)
                TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter));
 
                /* Refresh the folder */
+               /* Our observer receives notification of new emails during folder refreshes,
+                * so we can use observer->new_headers.
+                * TODO: This does not seem to be providing accurate numbers.
+                * Possibly the observer is notified asynchronously.
+                */
                observer = g_object_new (internal_folder_observer_get_type (), NULL);
                tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
+               
+               /* This gets the status information (headers) from the server.
+                * We use the blocking version, because we are already in a separate 
+                * thread.
+                */
                tny_folder_refresh (TNY_FOLDER (folder), &(priv->error));
 
                /* If the retrieve type is headers only do nothing more */
@@ -842,6 +871,11 @@ update_account_thread (gpointer thr_user_data)
                        iter = tny_list_create_iterator (observer->new_headers);
                        while (!tny_iterator_is_done (iter)) {
                                TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
+                               /* printf ("  DEBUG1.2 %s: checking size: account=%s, subject=%s\n", 
+                                *      __FUNCTION__, tny_account_get_id (priv->account), 
+                                * tny_header_get_subject (header));
+                                */
+                                
                                /* Apply per-message size limits */
                                if (tny_header_get_message_size (header) < info->max_size)
                                        g_ptr_array_add (new_headers, g_object_ref (header));
@@ -851,8 +885,10 @@ update_account_thread (gpointer thr_user_data)
                        }
                        g_object_unref (iter);
                }
+               
                tny_folder_remove_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
                g_object_unref (observer);
+               observer = NULL;
 
                if (priv->error)
                        priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
@@ -870,11 +906,26 @@ update_account_thread (gpointer thr_user_data)
                g_ptr_array_sort (new_headers, (GCompareFunc) compare_headers_by_date);
 
                /* Apply message count limit */
-               /* TODO if the number of messages exceeds the maximum, ask the
-                  user to download them all */
+               /* If the number of messages exceeds the maximum, ask the
+                * user to download them all,
+                * as per the UI spec "Retrieval Limits" section in 4.4: 
+                */
+               printf ("DEBUG: %s: account=%s, len=%d, retrieve_limit = %d\n", __FUNCTION__, 
+                       tny_account_get_id (priv->account), new_headers->len, info->retrieve_limit);
+               if (new_headers->len > info->retrieve_limit) {
+                       /* TODO: Ask the user, instead of just failing, showing mail_nc_msg_count_limit_exceeded, 
+                        * with 'Get all' and 'Newest only' buttons. */
+                       g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_RETRIEVAL_NUMBER_LIMIT,
+                            "The number of messages to retrieve exceeds the chosen limit for account %s\n", 
+                            tny_account_get_name (TNY_ACCOUNT (info->transport_account)));
+                       priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+                       goto out;
+               }
+               
                priv->done = 0;
                priv->total = MIN (new_headers->len, info->retrieve_limit);
-               while ((msg_num < priv->total)) {
+               while (msg_num < priv->total) {
 
                        TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers, msg_num));
                        TnyFolder *folder = tny_header_get_folder (header);
@@ -908,14 +959,18 @@ update_account_thread (gpointer thr_user_data)
                g_object_unref (priv->account);
        priv->account = g_object_ref (info->transport_account);
        
-       ModestTnySendQueue *send_queue = modest_runtime_get_send_queue
-               (info->transport_account);
-
-       timeout = g_timeout_add (250, idle_notify_progress, info->mail_op);
-       modest_tny_send_queue_try_to_send (send_queue);
-       g_source_remove (timeout);
-
-       g_object_unref (G_OBJECT(send_queue));
+       send_queue = modest_runtime_get_send_queue (info->transport_account);
+       if (send_queue) {
+               timeout = g_timeout_add (250, idle_notify_progress, info->mail_op);
+               modest_tny_send_queue_try_to_send (send_queue);
+               g_source_remove (timeout);
+       } else {
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
+                            "cannot create a send queue for %s\n", 
+                            tny_account_get_name (TNY_ACCOUNT (info->transport_account)));
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+       }
        
        /* Check if the operation was a success */
        if (!priv->error) {
@@ -960,6 +1015,13 @@ modest_mail_operation_update_account (ModestMailOperation *self,
        g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE);
        g_return_val_if_fail (account_name, FALSE);
 
+       /* Make sure that we have a connection, and request one 
+        * if necessary:
+        * TODO: Is there some way to trigger this for every attempt to 
+        * use the network? */
+       if (!modest_platform_connect_and_wait(NULL))
+               return FALSE;
+       
        /* Init mail operation. Set total and done to 0, and do not
           update them, this way the progress objects will know that
           we have no clue about the number of the objects */
@@ -1021,6 +1083,8 @@ modest_mail_operation_update_account (ModestMailOperation *self,
                                                           MODEST_ACCOUNT_LIMIT_RETRIEVE, FALSE);
        if (info->retrieve_limit == 0)
                info->retrieve_limit = G_MAXINT;
+               
+       /* printf ("DEBUG: %s: info->retrieve_limit = %d\n", __FUNCTION__, info->retrieve_limit); */
 
        thread = g_thread_create (update_account_thread, info, FALSE, NULL);
 
@@ -1037,44 +1101,33 @@ 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);
 
-       /* Get account and set it into mail_operation */
-       priv->account = tny_folder_get_account (TNY_FOLDER(parent));
-
        /* Check parent */
-       if (!TNY_IS_FOLDER (parent)) {
-               /* Set status failed and set an error */
-               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
-               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
-                            MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
-                            _("mail_in_ui_folder_create_error"));
-       } else {
+       if (TNY_IS_FOLDER (parent)) {
                /* Check folder rules */
-               rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
+               ModestTnyFolderRules rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
                if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
                        /* Set status failed and set an error */
                        priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                        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) {
+       if (!priv->error) {
                /* Create the folder */
                new_folder = tny_folder_store_create_folder (parent, name, &(priv->error));
                CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED);
+               if (!priv->error)
+                       priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
        }
 
        /* Notify about operation end */
@@ -1331,7 +1384,7 @@ void modest_mail_operation_get_msg (ModestMailOperation *self,
        /* Get message from folder */
        if (folder) {
                /* Get account and set it into mail_operation */
-               priv->account = tny_folder_get_account (TNY_FOLDER(folder));            
+               priv->account = tny_folder_get_account (TNY_FOLDER(folder));
 
                helper = g_slice_new0 (GetMsgAsyncHelper);
                helper->mail_op = self;
@@ -1556,6 +1609,10 @@ get_msgs_full_thread (gpointer thr_user_data)
                tny_iterator_next (iter);
        }
 
+       /* Set operation status */
+       if (priv->status == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
+               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
+
        /* Notify about operation end */
        g_idle_add (notify_update_account_queue, info->mail_op);
 
@@ -1579,7 +1636,6 @@ modest_mail_operation_get_msgs_full (ModestMailOperation *self,
        GetFullMsgsInfo *info = NULL;
        gboolean size_ok = TRUE;
        gint max_size;
-       GError *error = NULL;
        TnyIterator *iter = NULL;
        
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
@@ -1591,21 +1647,26 @@ modest_mail_operation_get_msgs_full (ModestMailOperation *self,
        priv->total = tny_list_get_length(header_list);
 
        /* Get account and set it into mail_operation */
-       if (tny_list_get_length (header_list) > 1) {
-               iter = tny_list_create_iterator (header_list);          
+       if (tny_list_get_length (header_list) >= 1) {
+               iter = tny_list_create_iterator (header_list);
                header = TNY_HEADER (tny_iterator_get_current (iter));
                folder = tny_header_get_folder (header);                
                priv->account = tny_folder_get_account (TNY_FOLDER(folder));
                g_object_unref (header);
                g_object_unref (folder);
+
+               if (tny_list_get_length (header_list) == 1) {
+                       g_object_unref (iter);
+                       iter = NULL;
+               }
        }
 
        /* Get msg size limit */
        max_size  = modest_conf_get_int (modest_runtime_get_conf (), 
                                         MODEST_CONF_MSG_SIZE_LIMIT, 
-                                        &error);
-       if (error) {
-               g_clear_error (&error);
+                                        &(priv->error));
+       if (priv->error) {
+               g_clear_error (&(priv->error));
                max_size = G_MAXINT;
        } else {
                max_size = max_size * KB;
@@ -1639,7 +1700,7 @@ modest_mail_operation_get_msgs_full (ModestMailOperation *self,
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                /* FIXME: the error msg is different for pop */
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
-                            MODEST_MAIL_OPERATION_ERROR_SIZE_LIMIT,
+                            MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT,
                             _("emev_ni_ui_imap_msg_size_exceed_error"));
                /* Remove from queue and free resources */
                modest_mail_operation_notify_end (self);
@@ -1963,7 +2024,4 @@ modest_mail_operation_notify_end (ModestMailOperation *self)
        state = modest_mail_operation_clone_state (self);
        g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
        g_slice_free (ModestMailOperationState, state);
-
-       /* Notify the queue */
-       modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
 }