X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fmodest-tny-send-queue.c;h=b3bd3b11f82525114af13e9a233ff2ebf7e8cbd1;hp=ba91145454ad24f80f232f3ba27d6d175e886bf1;hb=HEAD;hpb=99c95d6d66cd2da88f09271b2c6b88af660308a4 diff --git a/src/modest-tny-send-queue.c b/src/modest-tny-send-queue.c index ba91145..b3bd3b1 100644 --- a/src/modest-tny-send-queue.c +++ b/src/modest-tny-send-queue.c @@ -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, @@ -81,6 +84,9 @@ static void modest_tny_send_queue_add_async (TnySendQueue *self, static TnyFolder* modest_tny_send_queue_get_outbox (TnySendQueue *self); static TnyFolder* modest_tny_send_queue_get_sentbox (TnySendQueue *self); +static void modest_tny_send_queue_cancel (TnySendQueue *self, + TnySendQueueCancelAction cancel_action, + GError **err); /* list my signals */ enum { @@ -108,6 +114,10 @@ struct _ModestTnySendQueuePrivate { /* last was send receive operation?*/ gboolean requested_send_receive; + gboolean sending; + gboolean suspend; + + GSList *sighandlers; }; #define MODEST_TNY_SEND_QUEUE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ @@ -337,6 +347,24 @@ modest_tny_send_queue_get_outbox (TnySendQueue *self) return g_object_ref (priv->outbox); } +static void +modest_tny_send_queue_cancel (TnySendQueue *self, + TnySendQueueCancelAction cancel_action, + GError **err) +{ + ModestTnySendQueuePrivate *priv; + + g_return_if_fail (self); + + priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self); + + /* Call the parent */ + TNY_CAMEL_SEND_QUEUE_CLASS(parent_class)->cancel (self, cancel_action, err); + + if (cancel_action == TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND && (err == NULL || *err == NULL)) + priv->suspend = TRUE; +} + GType modest_tny_send_queue_get_type (void) { @@ -377,6 +405,7 @@ modest_tny_send_queue_class_init (ModestTnySendQueueClass *klass) TNY_CAMEL_SEND_QUEUE_CLASS(klass)->add_async = modest_tny_send_queue_add_async; TNY_CAMEL_SEND_QUEUE_CLASS(klass)->get_outbox = modest_tny_send_queue_get_outbox; TNY_CAMEL_SEND_QUEUE_CLASS(klass)->get_sentbox = modest_tny_send_queue_get_sentbox; + TNY_CAMEL_SEND_QUEUE_CLASS(klass)->cancel = modest_tny_send_queue_cancel; klass->status_changed = NULL; signals[STATUS_CHANGED_SIGNAL] = @@ -399,22 +428,29 @@ 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; + priv->suspend = FALSE; + priv->sighandlers = NULL; } static void modest_tny_send_queue_finalize (GObject *obj) { ModestTnySendQueuePrivate *priv; - + priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (obj); + modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers); + priv->sighandlers = NULL; + 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 +468,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 +487,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); @@ -476,9 +516,9 @@ modest_tny_send_queue_new (TnyCamelTransportAccount *account) ModestTnySendQueuePrivate *priv = NULL; TnyList *headers = NULL; GetHeadersInfo *info; - + 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 */ @@ -496,20 +536,27 @@ modest_tny_send_queue_new (TnyCamelTransportAccount *account) } /* 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), - NULL); - g_signal_connect (G_OBJECT(self), "msg-sent", - G_CALLBACK(_on_msg_has_been_sent), - NULL); - 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); - - + priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, + G_OBJECT(self), + "msg-sending", + G_CALLBACK(_on_msg_start_sending), + NULL); + priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, + G_OBJECT(self), "msg-sent", + G_CALLBACK(_on_msg_has_been_sent), + NULL); + priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, + G_OBJECT(self), "error-happened", + G_CALLBACK(_on_msg_error_happened), + NULL); + priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, + G_OBJECT (self), "queue-start", + G_CALLBACK (_on_queue_start), + NULL); + priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, + G_OBJECT (self), "queue-stop", + G_CALLBACK (_on_queue_stop), + NULL); priv->requested_send_receive = FALSE; headers = tny_simple_list_new (); @@ -544,7 +591,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 @@ -632,6 +679,8 @@ _on_msg_has_been_sent (TnySendQueue *self, tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN); + modest_platform_emit_msg_read_changed_signal (msg_id, TRUE); + tny_folder_sync_async (priv->sentbox, FALSE, NULL, NULL, NULL); /* Get status info */ @@ -688,7 +737,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 */ @@ -696,37 +745,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) { - TnyCamelTransportAccount* transport; - TnyTransportAccount *conn_specific; - - transport = tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)); - if (transport) { - gchar *message; - ModestTnyAccountStore *acc_store; - const gchar *acc_name; - - acc_store = modest_runtime_get_account_store(); - acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport)); - conn_specific = (TnyTransportAccount *) - modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name); - if (conn_specific) { - message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), - tny_account_get_hostname (TNY_ACCOUNT (conn_specific))); - g_object_unref (conn_specific); - } else { - message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), - tny_account_get_hostname (TNY_ACCOUNT (transport))); - } - modest_platform_run_alert_dialog (message, FALSE); - g_free (message); - g_object_unref (transport); - } - } 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); @@ -739,6 +761,7 @@ static void _on_queue_start (TnySendQueue *self, gpointer data) { + ModestTnySendQueuePrivate *priv; ModestMailOperation *mail_op; mail_op = modest_mail_operation_new (NULL); @@ -746,9 +769,87 @@ _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 +static void +on_queue_stop_get_headers_async_cb (TnyFolder *folder, + gboolean cancelled, + TnyList *headers, + GError *err, + gpointer user_data) +{ + ModestTnySendQueue *self = (ModestTnySendQueue *) user_data; + TnyIterator *iter; + + if (cancelled || err) + goto end; + + /* Update the info about headers */ + iter = tny_list_create_iterator (headers); + while (!tny_iterator_is_done (iter)) { + TnyHeader *header; + + header = (TnyHeader *) tny_iterator_get_current (iter); + if (header) { + gchar *msg_id = NULL; + GList *item = NULL; + + /* Get message uid */ + msg_id = modest_tny_send_queue_get_msg_id (header); + if (msg_id) + item = modest_tny_send_queue_lookup_info (MODEST_TNY_SEND_QUEUE (self), msg_id); + else + g_warning ("%s: could not get msg-id for header", __FUNCTION__); + + if (item) { + SendInfo *info; + /* Set current status item */ + info = item->data; + if (tny_header_get_flags (header) & TNY_HEADER_FLAG_SUSPENDED) { + info->status = MODEST_TNY_SEND_QUEUE_SUSPENDED; + g_signal_emit (self, signals[STATUS_CHANGED_SIGNAL], 0, + info->msg_id, info->status); + } + } else { + g_warning ("%s: could not find item with id '%s'", __FUNCTION__, msg_id); + } + g_object_unref (header); + } + tny_iterator_next (iter); + } + g_object_unref (iter); + + end: + /* Unrefs */ + g_object_unref (headers); + g_object_unref (self); +} + +static void +_on_queue_stop (TnySendQueue *self, + gpointer data) +{ + ModestTnySendQueuePrivate *priv; + + priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self); + priv->sending = FALSE; + + if (priv->suspend) { + TnyList *headers; + priv->suspend = FALSE; + + /* Update the state of messages in the queue */ + headers = tny_simple_list_new (); + tny_folder_get_headers_async (priv->outbox, headers, TRUE, + on_queue_stop_get_headers_async_cb, + NULL, g_object_ref (self)); + } +} + +static void fill_list_of_caches (gpointer key, gpointer value, gpointer userdata) { GSList **send_queues = (GSList **) userdata; @@ -771,14 +872,14 @@ modest_tny_all_send_queues_get_msg_status (TnyHeader *header) ModestTnySendQueueStatus queue_status = MODEST_TNY_SEND_QUEUE_UNKNOWN; gchar *msg_uid = NULL; ModestTnySendQueue *send_queue = NULL; - + g_return_val_if_fail (TNY_IS_HEADER(header), MODEST_TNY_SEND_QUEUE_UNKNOWN); msg_uid = modest_tny_send_queue_get_msg_id (header); cache_mgr = modest_runtime_get_cache_mgr (); send_queue_cache = modest_cache_mgr_get_cache (cache_mgr, MODEST_CACHE_MGR_CACHE_TYPE_SEND_QUEUE); - + g_hash_table_foreach (send_queue_cache, (GHFunc) fill_list_of_caches, &send_queues); if (send_queues == NULL) { accounts = tny_simple_list_new (); @@ -786,9 +887,9 @@ modest_tny_all_send_queues_get_msg_status (TnyHeader *header) tny_account_store_get_accounts (TNY_ACCOUNT_STORE(accounts_store), accounts, TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS); - + iter = tny_list_create_iterator (accounts); - while (!tny_iterator_is_done (iter)) { + while (!tny_iterator_is_done (iter)) { 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); @@ -807,7 +908,7 @@ modest_tny_all_send_queues_get_msg_status (TnyHeader *header) else { for (node = send_queues; node != NULL; node = g_slist_next (node)) { send_queue = MODEST_TNY_SEND_QUEUE (node->data); - + queue_status = modest_tny_send_queue_get_msg_status (send_queue, msg_uid); if (queue_status != MODEST_TNY_SEND_QUEUE_UNKNOWN) { status = queue_status; @@ -821,6 +922,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, @@ -831,13 +950,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; } @@ -857,12 +982,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 */ @@ -871,29 +1000,34 @@ 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); g_object_unref (headers); - 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