Fixes NB#105818, show the proper message when sending fails
[modest] / src / modest-tny-send-queue.c
index d4db8d7..5100ca2 100644 (file)
@@ -73,6 +73,9 @@ static void _on_msg_error_happened (TnySendQueue *self,
 static void _on_queue_start        (TnySendQueue *self, 
                                    gpointer user_data);
 
+static void _on_queue_stop         (TnySendQueue *self,
+                                   gpointer data);
+
 static void modest_tny_send_queue_add_async (TnySendQueue *self, 
                                             TnyMsg *msg, 
                                             TnySendQueueAddCallback callback, 
@@ -108,6 +111,8 @@ struct _ModestTnySendQueuePrivate {
 
        /* last was send receive operation?*/
        gboolean requested_send_receive;
+
+       gboolean sending;
 };
 
 #define MODEST_TNY_SEND_QUEUE_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
@@ -399,22 +404,24 @@ modest_tny_send_queue_instance_init (GTypeInstance *instance, gpointer g_class)
        priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (instance);
        priv->queue = g_queue_new();
        priv->current = NULL;
+       priv->outbox = NULL;
+       priv->sentbox = NULL;
+       priv->sending = FALSE;
 }
 
 static void
 modest_tny_send_queue_finalize (GObject *obj)
 {
        ModestTnySendQueuePrivate *priv;
-               
+
        priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (obj);
 
        g_queue_foreach (priv->queue, (GFunc)modest_tny_send_queue_info_free, NULL);
        g_queue_free (priv->queue);
 
+       G_OBJECT_CLASS(parent_class)->finalize (obj);
        g_object_unref (priv->outbox);
        g_object_unref (priv->sentbox);
-
-       G_OBJECT_CLASS(parent_class)->finalize (obj);
 }
 
 typedef struct {
@@ -432,6 +439,7 @@ new_queue_get_headers_async_cb (TnyFolder *folder,
        ModestTnySendQueue *self;
        TnyIterator *iter;
        GetHeadersInfo *info;
+       ModestMailOperation *wakeup_op;
 
        info = (GetHeadersInfo *) user_data;
        self = MODEST_TNY_SEND_QUEUE (info->queue);
@@ -450,7 +458,10 @@ new_queue_get_headers_async_cb (TnyFolder *folder,
        }
 
        /* Reenable suspended items */
-       modest_tny_send_queue_wakeup (self);
+       wakeup_op = modest_mail_operation_new (NULL);
+       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
+                                        wakeup_op);
+       modest_mail_operation_queue_wakeup (wakeup_op, MODEST_TNY_SEND_QUEUE (self));
 
        /* Frees */
        g_object_unref (iter);
@@ -480,7 +491,21 @@ modest_tny_send_queue_new (TnyCamelTransportAccount *account)
        g_return_val_if_fail (TNY_IS_CAMEL_TRANSPORT_ACCOUNT(account), NULL);
        
        self = MODEST_TNY_SEND_QUEUE(g_object_new(MODEST_TYPE_TNY_SEND_QUEUE, NULL));
-       
+
+       /* Set outbox and sentbox */
+       priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
+       priv->outbox  = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
+                                                              TNY_FOLDER_TYPE_OUTBOX);
+       priv->sentbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
+                                                              TNY_FOLDER_TYPE_SENT);
+
+       /* NOTE that this could happen if there was not enough disk
+          space when the account was created */
+       if (!priv->outbox || !priv->sentbox) {
+               g_object_unref (self);
+               return NULL;
+       }
+
        /* Connect signals to control when a msg is being or has been sent */
        g_signal_connect (G_OBJECT(self), "msg-sending",
                          G_CALLBACK(_on_msg_start_sending),
@@ -491,16 +516,15 @@ modest_tny_send_queue_new (TnyCamelTransportAccount *account)
        g_signal_connect (G_OBJECT(self), "error-happened",
                          G_CALLBACK(_on_msg_error_happened),
                          NULL);
+
        g_signal_connect (G_OBJECT (self), "queue-start",
                          G_CALLBACK (_on_queue_start),
                          NULL);
 
-       /* Set outbox and sentbox */
-       priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
-       priv->outbox  = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
-                                                              TNY_FOLDER_TYPE_OUTBOX);
-       priv->sentbox = modest_tny_account_get_special_folder (TNY_ACCOUNT(account),
-                                                              TNY_FOLDER_TYPE_SENT);
+       g_signal_connect (G_OBJECT (self), "queue-stop",
+                         G_CALLBACK (_on_queue_stop),
+                         NULL);
+
        priv->requested_send_receive = FALSE;
 
        headers = tny_simple_list_new ();
@@ -535,7 +559,7 @@ modest_tny_send_queue_sending_in_progress (ModestTnySendQueue* self)
        
        priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
        
-       return priv->current != NULL;
+       return priv->sending;
 }
 
 ModestTnySendQueueStatus
@@ -679,7 +703,7 @@ _on_msg_error_happened (TnySendQueue *self,
                        g_free(msg_uid);
                        return;
                }
-               
+
                info = item->data;
 
                /* Keep in queue so that we remember that the opertion has failed */
@@ -687,12 +711,10 @@ _on_msg_error_happened (TnySendQueue *self,
                if (err->code == TNY_SYSTEM_ERROR_CANCEL) {
                        info->status = MODEST_TNY_SEND_QUEUE_SUSPENDED;
                } else {
-                       if (err->code == TNY_SERVICE_ERROR_CONNECT)
-                               modest_platform_run_alert_dialog (_("emev_ib_ui_smtp_server_invalid"), FALSE);
                        info->status = MODEST_TNY_SEND_QUEUE_FAILED;
                }
                priv->current = NULL;
-               
+
                /* Notify status has changed */
                g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
 
@@ -705,6 +727,7 @@ static void
 _on_queue_start (TnySendQueue *self,
                 gpointer data)
 {
+       ModestTnySendQueuePrivate *priv;
        ModestMailOperation *mail_op;
 
        mail_op = modest_mail_operation_new (NULL);
@@ -712,6 +735,19 @@ _on_queue_start (TnySendQueue *self,
                                         mail_op);
        modest_mail_operation_run_queue (mail_op, MODEST_TNY_SEND_QUEUE (self));
        g_object_unref (mail_op);
+
+       priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
+       priv->sending = TRUE;
+}
+
+static void 
+_on_queue_stop (TnySendQueue *self,
+               gpointer data)
+{
+       ModestTnySendQueuePrivate *priv;
+
+       priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
+       priv->sending = FALSE;
 }
 
 static void 
@@ -758,11 +794,12 @@ modest_tny_all_send_queues_get_msg_status (TnyHeader *header)
                        account = TNY_TRANSPORT_ACCOUNT(tny_iterator_get_current (iter));
                        send_queue = modest_runtime_get_send_queue(TNY_TRANSPORT_ACCOUNT(account), TRUE);
                        g_object_unref(account);
-
-                       queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid);
-                       if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
-                               status = queue_status;
-                               break;
+                       if (TNY_IS_SEND_QUEUE (send_queue)) {
+                               queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid);
+                               if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) {
+                                       status = queue_status;
+                                       break;
+                               }
                        }
                        tny_iterator_next (iter);
                }
@@ -786,6 +823,24 @@ modest_tny_all_send_queues_get_msg_status (TnyHeader *header)
        return status;
 }
 
+typedef struct _WakeupHelper {
+       ModestTnySendQueue *self;
+       ModestTnySendQueueWakeupFunc callback;
+       gpointer userdata;
+} WakeupHelper;
+
+static void
+wakeup_sync_cb (TnyFolder *self, gboolean cancelled, GError *err, gpointer userdata)
+{
+       WakeupHelper *helper = (WakeupHelper *) userdata;
+
+       if (helper->callback) {
+               helper->callback (helper->self, cancelled, err, helper->userdata);
+       }
+       g_object_unref (helper->self);
+       g_slice_free (WakeupHelper, helper);
+}
+
 static void
 wakeup_get_headers_async_cb (TnyFolder *folder, 
                             gboolean cancelled, 
@@ -796,13 +851,19 @@ wakeup_get_headers_async_cb (TnyFolder *folder,
        ModestTnySendQueue *self;
        ModestTnySendQueuePrivate *priv;
        TnyIterator *iter;
+       WakeupHelper *helper = (WakeupHelper *) user_data;
 
-       self = MODEST_TNY_SEND_QUEUE (user_data);
+       self = MODEST_TNY_SEND_QUEUE (helper->self);
        priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
 
        if (cancelled || err) {
                g_debug ("Failed to wake up the headers of the send queue");
                g_object_unref (self);
+               if (helper->callback) {
+                       helper->callback (helper->self, cancelled, err, helper->userdata);
+               }
+               g_object_unref (helper->self);
+               g_slice_free (WakeupHelper, helper);
                return;
        }
 
@@ -822,12 +883,16 @@ wakeup_get_headers_async_cb (TnyFolder *folder,
                        /* Notify view */
                        msg_id = modest_tny_send_queue_get_msg_id (header);                     
                        item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id);
-                       info = (SendInfo *) item->data;
+                       if (!item) {
+                               info = g_slice_new (SendInfo);
+                               info->msg_id = msg_id;
+                               g_queue_push_tail (priv->queue, info);
+                       } else {
+                               info = (SendInfo *) item->data;
+                               g_free (msg_id);
+                       }
                        info->status = MODEST_TNY_SEND_QUEUE_WAITING;
-                       g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);
-                       
-                       /* Frees */
-                       g_free (msg_id);
+                       g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, info->msg_id, info->status);            
                }
 
                /* Frees */
@@ -836,7 +901,7 @@ wakeup_get_headers_async_cb (TnyFolder *folder,
        }
 
        /* Make changes persistent on disk */
-       tny_folder_sync_async (priv->outbox, FALSE, NULL, NULL, NULL);
+       tny_folder_sync_async (priv->outbox, FALSE, wakeup_sync_cb, NULL, helper);
 
        /* Frees */
        g_object_unref (iter);
@@ -844,21 +909,27 @@ wakeup_get_headers_async_cb (TnyFolder *folder,
        g_object_unref (self);
 }
 
-
 void   
-modest_tny_send_queue_wakeup (ModestTnySendQueue *self)
+modest_tny_send_queue_wakeup (ModestTnySendQueue *self, 
+                             ModestTnySendQueueWakeupFunc callback,
+                             gpointer userdata)
 {
        ModestTnySendQueuePrivate *priv;
        TnyList *headers;
+       WakeupHelper *helper;
 
        g_return_if_fail (MODEST_IS_TNY_SEND_QUEUE (self));
-
        priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
 
+       helper = g_slice_new (WakeupHelper);
+       helper->self = g_object_ref (self);
+       helper->callback = callback;
+       helper->userdata = userdata;
+
        headers = tny_simple_list_new ();
        tny_folder_get_headers_async (priv->outbox, headers, TRUE, 
                                      wakeup_get_headers_async_cb, 
-                                     NULL, g_object_ref (self));
+                                     NULL, helper);
 }
 
 gboolean