From 9a50aa1fcb88365c321552e395232846dfe06ea0 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Mon, 15 Oct 2007 11:48:03 +0000 Subject: [PATCH] * Fixed modest_text_utils_get_display_address, now the original string is not modified and the function returns new memory * Added notification removal support * Added notification grouping support * Replaced the old modest_platform_on_new_header_received by modest_platform_on_new_headers_received * Fixed ModestConf's set_list method pmo-trunk-r3505 --- src/gnome/modest-platform.c | 3 +- src/maemo/modest-platform.c | 188 ++++++++++++++++++++++--------- src/modest-conf.c | 26 +---- src/modest-defs.h | 3 + src/modest-main.c | 10 +- src/modest-platform.h | 17 ++- src/modest-text-utils.c | 37 +++--- src/modest-text-utils.h | 10 +- src/modest-ui-actions.c | 15 +-- src/widgets/modest-header-view-render.c | 21 ++-- 10 files changed, 202 insertions(+), 128 deletions(-) diff --git a/src/gnome/modest-platform.c b/src/gnome/modest-platform.c index fd191dc..2f62ecc 100644 --- a/src/gnome/modest-platform.c +++ b/src/gnome/modest-platform.c @@ -216,8 +216,9 @@ modest_platform_get_global_settings_dialog () return modest_gnome_global_settings_dialog_new (); } + void -modest_platform_on_new_header_received (TnyHeader *header) +modest_platform_on_new_headers_received (TnyList *header_list) { /* TODO: implement this */ g_print ("--------------- NEW MESSAGE ARRIVED ---------------\n"); diff --git a/src/maemo/modest-platform.c b/src/maemo/modest-platform.c index 5f32af6..a07ce84 100644 --- a/src/maemo/modest-platform.c +++ b/src/maemo/modest-platform.c @@ -59,6 +59,11 @@ #define HILDON_OSSO_URI_ACTION "uri-action" #define URI_ACTION_COPY "copy:" +/* The maximun number of notifications that could be shown in the + desktop. It's specified by the specs and limited by the screen + size */ +#define MAX_NOTIFICATIONS 6 + static osso_context_t *osso_context = NULL; static void @@ -1215,71 +1220,146 @@ modest_platform_set_update_interval (guint minutes) return TRUE; } -GtkWidget * -modest_platform_get_global_settings_dialog () -{ - return modest_maemo_global_settings_dialog_new (); -} - void -modest_platform_on_new_header_received (TnyHeader *header) +modest_platform_on_new_headers_received (TnyList *header_list) { #ifdef MODEST_HAVE_HILDON_NOTIFY HildonNotification *notification; - gchar *url = NULL; - TnyFolder *folder = NULL; - const gchar *subject; - - subject = tny_header_get_subject (header); - if (!subject || strlen(subject) == 0) - subject = _("mail_va_no_subject"); + TnyIterator *iter; + GSList *notifications_list = NULL; + + /* Get previous notifications ids */ + notifications_list = modest_conf_get_list (modest_runtime_get_conf (), + MODEST_CONF_NOTIFICATION_IDS, + MODEST_CONF_VALUE_INT, NULL); + + iter = tny_list_create_iterator (header_list); + while (!tny_iterator_is_done (iter)) { + gchar *url = NULL, *display_address = NULL, *display_date = NULL, *summary = NULL; + TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter)); + TnyFolder *folder = tny_header_get_folder (header); + gboolean first_notification = TRUE; + gint notif_id; - notification = hildon_notification_new (tny_header_get_from (header), - subject, - "qgn_list_messagin", - 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(notification, - "default", - "Cancel", - MODEST_DBUS_SERVICE, - MODEST_DBUS_OBJECT, - MODEST_DBUS_IFACE, - MODEST_DBUS_METHOD_OPEN_MESSAGE, - G_TYPE_STRING, url, - -1); - g_free (url); + display_date = modest_text_utils_get_display_date (tny_header_get_date_received (header)); + display_address = modest_text_utils_get_display_address (tny_header_get_from (header)); + summary = g_strdup_printf ("%s - %s", display_date, display_address); + notification = hildon_notification_new (summary, + tny_header_get_subject (header), + "qgn_list_messagin", + "email.arrive"); + + /* Create the message URL */ + url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder), + tny_header_get_uid (header)); + + hildon_notification_add_dbus_action(notification, + "default", + "Cancel", + MODEST_DBUS_SERVICE, + MODEST_DBUS_OBJECT, + MODEST_DBUS_IFACE, + MODEST_DBUS_METHOD_OPEN_MESSAGE, + G_TYPE_STRING, url, + -1); + + /* Play sound if the user wants. Show the LED + pattern. Show and play just one */ + if (G_UNLIKELY (first_notification)) { + first_notification = FALSE; + if (modest_conf_get_bool (modest_runtime_get_conf (), + MODEST_CONF_PLAY_SOUND_MSG_ARRIVE, + NULL)) { + notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification), + "sound-file", "/usr/share/sounds/ui-new_email.wav"); + } + + /* Set the led pattern */ + notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification), + "dialog-type", 4); + notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification), + "led-pattern", + "PatternCommunicationEmail"); + } + + /* Notify. We need to do this in an idle because this function + could be called from a thread */ + notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL); + + /* Save id in the list */ + g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL); + notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id)); + /* We don't listen for the "closed" signal, because we + don't care about if the notification was removed or + not to store the list in gconf */ - /* Play sound if the user wants */ - if (modest_conf_get_bool (modest_runtime_get_conf (), - MODEST_CONF_PLAY_SOUND_MSG_ARRIVE, - NULL)) { - hildon_notification_set_sound (HILDON_NOTIFICATION(notification), - "/usr/share/sounds/ui-new_email.wav"); + /* Free & carry on */ + g_free (display_date); + g_free (display_address); + g_free (summary); + g_free (url); + g_object_unref (folder); + g_object_unref (header); + tny_iterator_next (iter); } + g_object_unref (iter); + + /* Save the ids */ + modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS, + notifications_list, MODEST_CONF_VALUE_INT, NULL); + + g_slist_free (notifications_list); - /* Set the led pattern */ - notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION(notification), - "dialog-type", 4); - notify_notification_set_hint_string(NOTIFY_NOTIFICATION(notification), - "led-pattern", - "PatternCommunicationEmail"); - - /* Notify. We need to do this in an idle because this function - could be called from a thread */ - if (!notify_notification_show (NOTIFY_NOTIFICATION(notification), NULL)) - g_error ("Failed to send notification"); - - g_object_unref (notification); #endif /*MODEST_HAVE_HILDON_NOTIFY*/ } +void +modest_platform_remove_new_mail_notifications (void) +{ +#ifdef MODEST_HAVE_HILDON_NOTIFY + GSList *notif_list = NULL; + + /* Get previous notifications ids */ + notif_list = modest_conf_get_list (modest_runtime_get_conf (), + MODEST_CONF_NOTIFICATION_IDS, + MODEST_CONF_VALUE_INT, NULL); + + while (notif_list) { + gint notif_id; + NotifyNotification *notif; + + /* Nasty HACK to remove the notifications, set the id + of the existing ones and then close them */ + notif_id = GPOINTER_TO_INT(notif_list->data); + notif = notify_notification_new("dummy", NULL, NULL, NULL); + g_object_set(G_OBJECT(notif), "id", notif_id, NULL); + + /* Close the notification, note that some ids could be + already invalid, but we don't care because it does + not fail */ + notify_notification_close(notif, NULL); + g_object_unref(notif); + + /* Delete the link, it's like going to the next */ + notif_list = g_slist_delete_link (notif_list, notif_list); + } + + /* Save the ids */ + modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS, + notif_list, MODEST_CONF_VALUE_INT, NULL); + + g_slist_free (notif_list); + +#endif /* MODEST_HAVE_HILDON_NOTIFY */ +} + + + +GtkWidget * +modest_platform_get_global_settings_dialog () +{ + return modest_maemo_global_settings_dialog_new (); +} void modest_platform_show_help (GtkWindow *parent_window, diff --git a/src/modest-conf.c b/src/modest-conf.c index 90946b9..e8fc818 100644 --- a/src/modest-conf.c +++ b/src/modest-conf.c @@ -309,7 +309,6 @@ modest_conf_set_list (ModestConf* self, const gchar* key, { ModestConfPrivate *priv; GConfValueType gconf_type; - gboolean result; g_return_val_if_fail (self, FALSE); g_return_val_if_fail (key, FALSE); @@ -317,31 +316,8 @@ modest_conf_set_list (ModestConf* self, const gchar* key, priv = MODEST_CONF_GET_PRIVATE(self); gconf_type = modest_conf_type_to_gconf_type (list_type, err); - if (*err) - return FALSE; - result = gconf_client_set_list (priv->gconf_client, key, gconf_type, val, err); - if(*err) { - g_warning("gconf_client_set_list() failed with key=%s. error=%s", key, - (*err)->message); - result = FALSE; - } - - /* TODO: Remove this, when we fix the problem: */ - /* This shows that sometimes set_list fails, while saying that it succeeded: */ - if (result) { - const gint debug_list_length_start = g_slist_length(val); - GSList* debug_list = gconf_client_get_list(priv->gconf_client, key, gconf_type, err); - const gint debug_list_length_after = g_slist_length(debug_list); - - if(debug_list_length_start != debug_list_length_after) - g_warning("modest_conf_set_list(): The list length after setting is " - "not the same as the specified list. key=%s. " - "We think that we fixed this, so tell us if you see this.", key); - g_slist_free(debug_list); - } - - return result; + return gconf_client_set_list (priv->gconf_client, key, gconf_type, val, err); } diff --git a/src/modest-defs.h b/src/modest-defs.h index 740d849..e584fd5 100644 --- a/src/modest-defs.h +++ b/src/modest-defs.h @@ -182,4 +182,7 @@ #define MODEST_CONF_REPLY_TYPE MODEST_CONF_NAMESPACE "/reply_type" /* int */ #define MODEST_CONF_FORWARD_TYPE MODEST_CONF_NAMESPACE "/forward_type" /* int */ +/* Notification ids */ +#define MODEST_CONF_NOTIFICATION_IDS MODEST_CONF_NAMESPACE "/notification_ids" /* list of ints */ + #endif /*__MODEST_DEFS_H__*/ diff --git a/src/modest-main.c b/src/modest-main.c index 9bb9588..4ca4f15 100644 --- a/src/modest-main.c +++ b/src/modest-main.c @@ -32,6 +32,7 @@ #include #include #include +#include "modest-platform.h" #include #include #include @@ -84,14 +85,21 @@ main (int argc, char *argv[]) * The UI will be shown later (or just after starting if no otehr D-Bus method was used), * when we receive the "top_application" D-Bus method. */ - if (show_ui_without_top_application_method) + if (show_ui_without_top_application_method) { gtk_widget_show_all (GTK_WIDGET(win)); + + /* Remove new mail notifications if exist */ + modest_platform_remove_new_mail_notifications (); + } gtk_main (); cleanup: gdk_threads_leave (); + /* Remove new mail notifications if exist */ +/* modest_platform_remove_new_mail_notifications (); */ + if (!modest_init_uninit ()) { g_printerr ("modest: modest_init_uninit failed\n"); retval = 1; diff --git a/src/modest-platform.h b/src/modest-platform.h index e1f35ba..e9715b5 100644 --- a/src/modest-platform.h +++ b/src/modest-platform.h @@ -275,8 +275,14 @@ gboolean modest_platform_set_update_interval (guint minutes); **/ GtkWidget* modest_platform_get_global_settings_dialog (void); -void modest_platform_on_new_header_received (TnyHeader *header); - +/** + * modest_platform_on_new_headers_received: + * @header_list: the list of new received headers + * + * Performs the required actions when new headers are + * received. Tipically it's useful for showing new email notifications + **/ +void modest_platform_on_new_headers_received (TnyList *header_list); /** * modest_platform_show_help: @@ -367,6 +373,13 @@ gboolean modest_platform_run_certificate_conformation_dialog (const gchar* serve gboolean modest_platform_run_alert_dialog (const gchar* prompt, gboolean is_question); +/** + * modest_platform_remove_new_mail_notifications: + * + * Removes all the active new mail notifications + **/ +void modest_platform_remove_new_mail_notifications (void); + G_END_DECLS #endif /* __MODEST_PLATFORM_UTILS_H__ */ diff --git a/src/modest-text-utils.c b/src/modest-text-utils.c index 8a83e60..9bf3de2 100644 --- a/src/modest-text-utils.c +++ b/src/modest-text-utils.c @@ -953,36 +953,35 @@ hyperlinkify_plain_text (GString *txt) } - gchar* -modest_text_utils_get_display_address (gchar *address) +modest_text_utils_get_display_address (const gchar *address) { - gchar *cursor; + gchar *display; + gchar **tokens; + gint i = 0; if (!address) return NULL; - + g_return_val_if_fail (g_utf8_validate (address, -1, NULL), NULL); - g_strchug (address); /* remove leading whitespace */ + tokens = g_strsplit_set ((const gchar*) address, "<>()", 3); - /* from display name */ - cursor = g_strstr_len (address, strlen(address), "<"); - if (cursor == address) /* there's nothing else? leave it */ - return address; - if (cursor) - cursor[0]='\0'; + /* Note that if any of the delimiters is the first character + then g_strsplit_set will return "" as the first string */ + while (tokens[i] != NULL) { + if (strlen ((char *) (tokens[i])) != 0) + break; + i++; + } - /* remove (bla bla) from display name */ - cursor = g_strstr_len (address, strlen(address), "("); - if (cursor == address) /* there's nothing else? leave it */ - return address; - if (cursor) - cursor[0]='\0'; + display = g_strdup (tokens [i]); + g_strchug (display); - g_strchomp (address); /* remove trailing whitespace */ + /* Free the other tokens */ + g_strfreev (tokens); - return address; + return display; } gchar * diff --git a/src/modest-text-utils.h b/src/modest-text-utils.h index f39dfc2..c51499b 100644 --- a/src/modest-text-utils.h +++ b/src/modest-text-utils.h @@ -41,6 +41,7 @@ #define _FM(str) dgettext("hildon-fm",str) #define _CS(str) dgettext("hildon-common-strings",str) #define _HL(str) dgettext("hildon-libs",str) +#define _MD(str) dgettext("maemo-af-desktop",str) /* Forbidden char arrays */ extern const gchar account_title_forbidden_chars[]; @@ -203,13 +204,10 @@ size_t modest_text_utils_strftime(char *s, size_t max, const char *fmt, time_t * ie. removes "<...>" and "(...)" parts * the change is in-place; removes leading/trailing whitespace * - * Returns: the new address of the string; this new string - * is _NOT_ newly allocated, so should not be freed. (remember - * the old address of the parameter if that one needs to be freed) - * - * NULL in case of error or if address == NULL + * Returns: a new allocated string with the display address. NULL in + * case of error or if address == NULL */ -gchar* modest_text_utils_get_display_address (gchar *address); +gchar* modest_text_utils_get_display_address (const gchar *address); /** * modest_text_utils_get_email_address: diff --git a/src/modest-ui-actions.c b/src/modest-ui-actions.c index 13e4ee9..e4798cf 100644 --- a/src/modest-ui-actions.c +++ b/src/modest-ui-actions.c @@ -1629,19 +1629,8 @@ new_messages_arrived (ModestMailOperation *self, } /* Notify new messages have been downloaded */ - if ((new_headers != NULL) && (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); - } + if ((new_headers != NULL) && (tny_list_get_length (new_headers) > 0)) + modest_platform_on_new_headers_received (new_headers); } /* diff --git a/src/widgets/modest-header-view-render.c b/src/widgets/modest-header-view-render.c index 019ab32..2f8b599 100644 --- a/src/widgets/modest-header-view-render.c +++ b/src/widgets/modest-header-view-render.c @@ -257,11 +257,14 @@ _modest_header_view_date_cell_data (GtkTreeViewColumn *column, GtkCellRenderer } void -_modest_header_view_sender_receiver_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer, - GtkTreeModel *tree_model, GtkTreeIter *iter, gboolean is_sender) +_modest_header_view_sender_receiver_cell_data (GtkTreeViewColumn *column, + GtkCellRenderer *renderer, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + gboolean is_sender) { TnyHeaderFlags flags; - gchar *address; + gchar *address, *display_address; gint sender_receiver_col; if (is_sender) @@ -274,10 +277,12 @@ _modest_header_view_sender_receiver_cell_data (GtkTreeViewColumn *column, GtkC TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags, -1); + display_address = modest_text_utils_get_display_address (address); g_object_set (G_OBJECT(renderer), "text", - modest_text_utils_get_display_address (address), + display_address, NULL); + g_free (display_address); g_free (address); set_common_flags (renderer, flags); } @@ -300,7 +305,7 @@ _modest_header_view_compact_header_cell_data (GtkTreeViewColumn *column, GtkCe TnyHeaderFlags flags = 0; TnyHeaderFlags prior_flags = 0; - gchar *address = NULL; + gchar *address = NULL, *display_address; gchar *subject = NULL; gchar *header = NULL; time_t date = 0; @@ -371,10 +376,12 @@ _modest_header_view_compact_header_cell_data (GtkTreeViewColumn *column, GtkCe /* FIXME: we hardcode the color to #666666; instead we should use SecondaryTextColour from the * theme (gtkrc file) */ + display_address = modest_text_utils_get_display_address (address); header = g_markup_printf_escaped ("%s", - modest_text_utils_get_display_address (address)); + display_address); + g_free (display_address); g_free (address); - address = NULL; + address = display_address = NULL; g_object_set (G_OBJECT (recipient_cell), "markup", header, NULL); -- 1.7.9.5