From d56bab09ae68f6708d2dcec6150433c5e905f0c3 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Fri, 7 Sep 2007 16:11:32 +0000 Subject: [PATCH] * Changed the update_account_thread it now refreshes the INBOX and pokes the other folders * Changed the signature of the signal that notifies about new messages * Added the proper dbus call when new messages arrive to the notification * replaced the old new_msg method of modest-platform by new_header_arrived * Fixes NB#59971 adds message notifications, NB#63779 adds LED pattern to the notifications pmo-trunk-r3246 --- src/gnome/modest-platform.c | 2 +- src/maemo/modest-platform.c | 35 ++++-- src/modest-mail-operation.c | 252 +++++++++++++++++++++---------------------- src/modest-mail-operation.h | 4 +- src/modest-platform.h | 2 +- src/modest-ui-actions.c | 17 ++- 6 files changed, 167 insertions(+), 145 deletions(-) diff --git a/src/gnome/modest-platform.c b/src/gnome/modest-platform.c index afe8f66..6d2d200 100644 --- a/src/gnome/modest-platform.c +++ b/src/gnome/modest-platform.c @@ -217,7 +217,7 @@ modest_platform_get_global_settings_dialog () } void -modest_platform_on_new_msg (void) +modest_platform_on_new_header_received (TnyHeader *header) { /* TODO: implement this */ g_print ("--------------- NEW MESSAGE ARRIVED ---------------\n"); diff --git a/src/maemo/modest-platform.c b/src/maemo/modest-platform.c index 03afc35..ae94a93 100644 --- a/src/maemo/modest-platform.c +++ b/src/maemo/modest-platform.c @@ -1013,7 +1013,8 @@ set_account_to_online (TnyAccount *account) #endif } -gboolean modest_platform_connect_and_wait (GtkWindow *parent_window, TnyAccount *account) +gboolean +modest_platform_connect_and_wait (GtkWindow *parent_window, TnyAccount *account) { if (connect_request_in_progress) return FALSE; @@ -1071,7 +1072,8 @@ gboolean modest_platform_connect_and_wait (GtkWindow *parent_window, TnyAccount return result; } -gboolean modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account) +gboolean +modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account) { if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) { if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) && @@ -1084,7 +1086,8 @@ gboolean modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_ return modest_platform_connect_and_wait (parent_window, account); } -gboolean modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store) +gboolean +modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store) { if (!folder_store) return TRUE; /* Maybe it is something local. */ @@ -1105,7 +1108,8 @@ gboolean modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *par return result; } -gboolean modest_platform_is_network_folderstore (TnyFolderStore *folder_store) +gboolean +modest_platform_is_network_folderstore (TnyFolderStore *folder_store) { TnyAccount *account = NULL; gboolean result = TRUE; @@ -1160,7 +1164,8 @@ modest_platform_run_sort_dialog (GtkWindow *parent_window, } -gboolean modest_platform_set_update_interval (guint minutes) +gboolean +modest_platform_set_update_interval (guint minutes) { ModestConf *conf = modest_runtime_get_conf (); if (!conf) @@ -1251,25 +1256,35 @@ modest_platform_get_global_settings_dialog () } void -modest_platform_on_new_msg (void) +modest_platform_on_new_header_received (TnyHeader *header) { #ifdef MODEST_HAVE_HILDON_NOTIFY HildonNotification *not; - + gchar *url = NULL; + TnyFolder *folder = NULL; + /* Create a new notification. TODO: per-mail data needed */ - not = hildon_notification_new ("TODO: (new email) Summary", - "TODO: (new email) Description", + not = hildon_notification_new (tny_header_get_from (header), + tny_header_get_subject (header), "qgn_list_messagin_mail_unread", NULL); + folder = tny_header_get_folder (header); + url = g_strdup_printf ("%s/%s", + tny_folder_get_url_string (folder), + tny_header_get_uid (header)); + g_object_unref (folder); + hildon_notification_add_dbus_action(not, "default", "Cancel", MODEST_DBUS_SERVICE, MODEST_DBUS_OBJECT, MODEST_DBUS_IFACE, - MODEST_DBUS_METHOD_OPEN_DEFAULT_INBOX, + MODEST_DBUS_METHOD_OPEN_MESSAGE, + G_TYPE_STRING, url, -1); + g_free (url); /* Play sound SR-SND-18 */ hildon_notification_set_sound diff --git a/src/modest-mail-operation.c b/src/modest-mail-operation.c index a21782e..492e3e4 100644 --- a/src/modest-mail-operation.c +++ b/src/modest-mail-operation.c @@ -941,7 +941,7 @@ typedef struct gchar *account_name; UpdateAccountCallback callback; gpointer user_data; - gint new_headers; + TnyList *new_headers; } UpdateAccountInfo; typedef struct @@ -1190,56 +1190,33 @@ idle_update_account_cb (gpointer data) /* Frees */ g_object_unref (idle_info->mail_op); + if (idle_info->new_headers) + g_object_unref (idle_info->new_headers); g_free (idle_info); return FALSE; } - -static gpointer -update_account_thread (gpointer thr_user_data) +static TnyList * +get_all_folders_from_account (TnyStoreAccount *account, + GError **error) { - static gboolean first_time = TRUE; - UpdateAccountInfo *info = NULL; TnyList *all_folders = NULL; - GPtrArray *new_headers = NULL; TnyIterator *iter = NULL; TnyFolderStoreQuery *query = NULL; - ModestMailOperationPrivate *priv = NULL; - ModestTnySendQueue *send_queue = NULL; - gint num_new_headers = 0; - - info = (UpdateAccountInfo *) thr_user_data; - priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op); - /* Get account and set it into mail_operation */ - priv->account = g_object_ref (info->account); - - /* - * Previousl, we did this for POP3, to do a logout-login upon send/receive, - * because many POP-servers (like Gmail) do not - * show any updates unless we do that. - * But that didn't work with gmail anyway, - * and tinymail now takes care of this itself by disconnecting - * automatically after using the connection. - */ - /* - if (!first_time && TNY_IS_CAMEL_POP_STORE_ACCOUNT (priv->account)) - tny_camel_pop_store_account_reconnect (TNY_CAMEL_POP_STORE_ACCOUNT(priv->account)); - */ - - /* 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 (); tny_folder_store_query_add_item (query, NULL, TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED); - tny_folder_store_get_folders (TNY_FOLDER_STORE (info->account), + tny_folder_store_get_folders (TNY_FOLDER_STORE (account), all_folders, query, - &(priv->error)); - if (priv->error) { - priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; - goto out; + error); + + if (*error) { + if (all_folders) + g_object_unref (all_folders); + return NULL; } iter = tny_list_create_iterator (all_folders); @@ -1253,140 +1230,158 @@ update_account_thread (gpointer thr_user_data) } g_object_unref (G_OBJECT (iter)); + return all_folders; +} + + +static gpointer +update_account_thread (gpointer thr_user_data) +{ + static gboolean first_time = TRUE; + UpdateAccountInfo *info = NULL; + TnyList *all_folders = NULL, *new_headers = NULL; + GPtrArray *new_headers_array = NULL; + TnyIterator *iter = NULL; + ModestMailOperationPrivate *priv = NULL; + ModestTnySendQueue *send_queue = NULL; + gint i = 0, timeout = 0; + + info = (UpdateAccountInfo *) thr_user_data; + priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op); + + /* 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 + we're already running in a different thread than the UI */ + all_folders = get_all_folders_from_account (info->account, &(priv->error)); + if (!all_folders) { + priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; + goto out; + } + /* Update status and notify. We need to call the notification 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 provide it for the moment */ - gint timeout = g_timeout_add (100, idle_notify_progress, info->mail_op); + timeout = g_timeout_add (100, idle_notify_progress, info->mail_op); - /* Refresh folders */ - num_new_headers = 0; - new_headers = g_ptr_array_new (); + new_headers_array = g_ptr_array_new (); iter = tny_list_create_iterator (all_folders); while (!tny_iterator_is_done (iter) && !priv->error && priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) { - InternalFolderObserver *observer; - TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter)); + TnyFolderType folder_type; + TnyFolder *folder = NULL; - /* Refresh the folder */ - /* Our observer receives notification of new emails during folder refreshes, - * so we can use observer->new_headers. - */ - 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. - */ + folder = TNY_FOLDER (tny_iterator_get_current (iter)); + folder_type = tny_folder_get_folder_type (folder); - if (!g_ascii_strcasecmp (info->retrieve_type, MODEST_ACCOUNT_RETRIEVE_VALUE_MESSAGES) || - !g_ascii_strcasecmp (info->retrieve_type, MODEST_ACCOUNT_RETRIEVE_VALUE_MESSAGES_AND_ATTACHMENTS)) { - TnyIterator *iter; + /* Refresh it only if it's the INBOX */ + if (folder_type == TNY_FOLDER_TYPE_INBOX) { + InternalFolderObserver *observer = NULL; + TnyIterator *new_headers_iter = NULL; - /* If the retrieve type is full messages, refresh and get the messages */ + /* Refresh the folder. Our observer receives + * the new emails during folder refreshes, so + * we can use observer->new_headers + */ + observer = g_object_new (internal_folder_observer_get_type (), NULL); + tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer)); + tny_folder_refresh (TNY_FOLDER (folder), &(priv->error)); - iter = tny_list_create_iterator (observer->new_headers); - while (!tny_iterator_is_done (iter)) { - TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter)); - + new_headers_iter = tny_list_create_iterator (observer->new_headers); + while (!tny_iterator_is_done (new_headers_iter)) { + TnyHeader *header = NULL; + + header = TNY_HEADER (tny_iterator_get_current (new_headers_iter)); /* 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)); - + g_ptr_array_add (new_headers_array, g_object_ref (header)); + g_object_unref (header); - tny_iterator_next (iter); + tny_iterator_next (new_headers_iter); } - g_object_unref (iter); + g_object_unref (new_headers_iter); + + tny_folder_remove_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer)); + g_object_unref (observer); } else { - /* We do not need to do it the first time + /* We no not need to do it the first time, because it's automatically done by the tree model */ - if (G_UNLIKELY (!first_time)) - tny_folder_poke_status (TNY_FOLDER (folder)); + if (G_LIKELY (!first_time)) + tny_folder_poke_status (folder); } - - tny_folder_remove_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer)); - g_object_unref (observer); - observer = NULL; - - if (folder) - g_object_unref (G_OBJECT (folder)); - - if (priv->error) - priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; + g_object_unref (folder); tny_iterator_next (iter); } - g_object_unref (G_OBJECT (iter)); g_source_remove (timeout); if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED && priv->status != MODEST_MAIL_OPERATION_STATUS_FAILED && - new_headers->len > 0) { + new_headers_array->len > 0) { gint msg_num = 0; /* Order by date */ - g_ptr_array_sort (new_headers, (GCompareFunc) compare_headers_by_date); - - /* Apply message count limit */ - /* 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: - */ - 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; + g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date); + + /* TODO: Ask the user, instead of just failing, + * showing mail_nc_msg_count_limit_exceeded, with 'Get + * all' and 'Newest only' buttons. */ + if (new_headers_array->len > info->retrieve_limit) { + /* TODO */ } - - priv->done = 0; - priv->total = MIN (new_headers->len, info->retrieve_limit); - while (msg_num < priv->total) { - - TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers, msg_num)); - TnyFolder *folder = tny_header_get_folder (header); - TnyMsg *msg = tny_folder_get_msg (folder, header, NULL); - ModestMailOperationState *state; - ModestPair* pair; - - priv->done++; - /* We can not just use the mail operation because the - values of done and total could change before the - idle is called */ - state = modest_mail_operation_clone_state (info->mail_op); - pair = modest_pair_new (g_object_ref (info->mail_op), state, FALSE); - g_idle_add_full (G_PRIORITY_HIGH_IDLE, idle_notify_progress_once, - pair, (GDestroyNotify) modest_pair_free); - - g_object_unref (msg); - g_object_unref (folder); - msg_num++; + /* Should be get only the headers or the message as well? */ + if (g_ascii_strcasecmp (info->retrieve_type, + MODEST_ACCOUNT_RETRIEVE_VALUE_HEADERS_ONLY) != 0) { + priv->done = 0; + priv->total = MIN (new_headers_array->len, info->retrieve_limit); + while (msg_num < priv->total) { + + TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num)); + TnyFolder *folder = tny_header_get_folder (header); + TnyMsg *msg = tny_folder_get_msg (folder, header, NULL); + ModestMailOperationState *state; + ModestPair* pair; + + priv->done++; + /* We can not just use the mail operation because the + values of done and total could change before the + idle is called */ + state = modest_mail_operation_clone_state (info->mail_op); + pair = modest_pair_new (g_object_ref (info->mail_op), state, FALSE); + g_idle_add_full (G_PRIORITY_HIGH_IDLE, idle_notify_progress_once, + pair, (GDestroyNotify) modest_pair_free); + + g_object_unref (msg); + g_object_unref (folder); + + msg_num++; + } } } - /* Get the number of new headers and free them */ - num_new_headers = new_headers->len; - g_ptr_array_foreach (new_headers, (GFunc) g_object_unref, NULL); - g_ptr_array_free (new_headers, FALSE); - if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED) goto out; + /* Copy the headers to a list and free the array */ + new_headers = tny_simple_list_new (); + for (i=0; i < new_headers_array->len; i++) { + TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i)); + tny_list_append (new_headers, G_OBJECT (header)); + } + g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL); + g_ptr_array_free (new_headers_array, FALSE); + + /* Perform send (if operation was not cancelled) */ priv->done = 0; priv->total = 0; @@ -1424,7 +1419,7 @@ update_account_thread (gpointer thr_user_data) /* This thread is not in the main lock */ idle_info = g_malloc0 (sizeof (UpdateAccountInfo)); idle_info->mail_op = g_object_ref (info->mail_op); - idle_info->new_headers = num_new_headers; + idle_info->new_headers = (new_headers) ? g_object_ref (new_headers) : NULL; idle_info->callback = info->callback; idle_info->user_data = info->user_data; g_idle_add (idle_update_account_cb, idle_info); @@ -1436,7 +1431,8 @@ update_account_thread (gpointer thr_user_data) g_idle_add (idle_notify_queue, g_object_ref (info->mail_op)); /* Frees */ - g_object_unref (query); + if (new_headers) + g_object_unref (new_headers); g_object_unref (all_folders); g_object_unref (info->account); g_object_unref (info->transport_account); diff --git a/src/modest-mail-operation.h b/src/modest-mail-operation.h index 8fc8caf..6b6ebcd 100644 --- a/src/modest-mail-operation.h +++ b/src/modest-mail-operation.h @@ -147,7 +147,7 @@ typedef void (*RefreshAsyncUserCallback) (ModestMailOperation *mail_op, * UpdateAccountCallback: * * @obj: a #GObject generic object which has created current mail operation. - * @new_messages: the amount of new messages received + * @new_headers: the list of new headers received * @user_data: generic data passed to user defined function. * * This is the callback of the update_account operation. It informs @@ -155,7 +155,7 @@ typedef void (*RefreshAsyncUserCallback) (ModestMailOperation *mail_op, * downloaded */ typedef void (*UpdateAccountCallback) (ModestMailOperation *self, - gint new_messages, + TnyList *new_headers, gpointer user_data); /* This struct represents the internal state of a mail operation in a diff --git a/src/modest-platform.h b/src/modest-platform.h index 020a2c1..e897c87 100644 --- a/src/modest-platform.h +++ b/src/modest-platform.h @@ -275,7 +275,7 @@ gboolean modest_platform_set_update_interval (guint minutes); **/ GtkWidget* modest_platform_get_global_settings_dialog (void); -void modest_platform_on_new_msg (void); +void modest_platform_on_new_header_received (TnyHeader *header); /** diff --git a/src/modest-ui-actions.c b/src/modest-ui-actions.c index bcef523..c39ea95 100644 --- a/src/modest-ui-actions.c +++ b/src/modest-ui-actions.c @@ -1520,7 +1520,7 @@ modest_ui_actions_on_sort (GtkAction *action, static void new_messages_arrived (ModestMailOperation *self, - gint new_messages, + TnyList *new_headers, gpointer user_data) { ModestMainWindow *win = NULL; @@ -1546,8 +1546,19 @@ new_messages_arrived (ModestMailOperation *self, } /* Notify new messages have been downloaded */ - if (new_messages > 0) - modest_platform_on_new_msg (); + if (tny_list_get_length (new_headers) > 0) { + TnyIterator *iter = tny_list_create_iterator (new_headers); + do { + TnyHeader *header = NULL; + + header = TNY_HEADER (tny_iterator_get_current (iter)); + modest_platform_on_new_header_received (header); + g_object_unref (header); + + tny_iterator_next (iter); + } while (!tny_iterator_is_done (iter)); + g_object_unref (iter); + } } /* -- 1.7.9.5