1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <modest-platform.h>
34 #include <modest-defs.h>
35 #include <modest-runtime.h>
36 #include <modest-main-window.h>
37 #include <modest-header-view.h>
38 #include "modest-hildon2-global-settings-dialog.h"
39 #include "modest-widget-memory.h"
40 #include <modest-hildon-includes.h>
41 #include <modest-maemo-utils.h>
42 #include <modest-utils.h>
43 #include <dbus_api/modest-dbus-callbacks.h>
44 #include <modest-osso-autosave-callbacks.h>
46 #include <tny-maemo-conic-device.h>
47 #include <tny-camel-folder.h>
48 #include <tny-simple-list.h>
49 #include <tny-merge-folder.h>
50 #include <tny-error.h>
51 #include <tny-folder.h>
52 #include <tny-account-store-view.h>
53 #include <gtk/gtkicontheme.h>
54 #include <gtk/gtkmenuitem.h>
55 #include <gtk/gtkmain.h>
56 #include <modest-text-utils.h>
57 #include "modest-tny-folder.h"
58 #include "modest-tny-account.h"
60 #include <libgnomevfs/gnome-vfs-mime-utils.h>
61 #include <modest-account-settings-dialog.h>
62 #include <modest-easysetup-wizard-dialog.h>
63 #include "modest-hildon2-sort-dialog.h"
64 #include <hildon/hildon.h>
66 #include "hildon2/modest-hildon2-details-dialog.h"
67 #include "hildon2/modest-hildon2-window-mgr.h"
68 #ifdef MODEST_USE_PROFILE
69 #include <keys_nokia.h>
70 #include <libprofile.h>
73 #include <modest-datetime-formatter.h>
74 #include "modest-header-window.h"
75 #include <modest-folder-window.h>
76 #include <modest-account-mgr.h>
77 #include <modest-account-mgr-helpers.h>
78 #include <modest-ui-constants.h>
79 #include <modest-selector-picker.h>
80 #include <modest-icon-names.h>
81 #include <modest-count-stream.h>
83 #ifdef MODEST_HAVE_MCE
84 #include <mce/dbus-names.h>
85 #endif /*MODEST_HAVE_MCE*/
87 #ifdef MODEST_HAVE_ABOOK
88 #include <libosso-abook/osso-abook.h>
89 #endif /*MODEST_HAVE_ABOOK*/
91 #ifdef MODEST_HAVE_LIBALARM
92 #include <alarmd/libalarm.h> /* For alarm_event_add(), etc. */
93 #endif /*MODEST_HAVE_LIBALARM*/
96 #define HILDON_OSSO_URI_ACTION "uri-action"
97 #define URI_ACTION_COPY "copy:"
98 #define MODEST_NOTIFICATION_CATEGORY "email-message"
99 #define MODEST_NEW_MAIL_LIGHTING_PATTERN "PatternCommunicationEmail"
100 #ifdef MODEST_USE_PROFILE
101 #define PROFILE_MAIL_TONE PROFILEKEY_EMAIL_ALERT_TONE
102 #define PROFILE_MAIL_VOLUME PROFILEKEY_EMAIL_ALERT_VOLUME
104 #define MAIL_TONE "message-new-email"
107 #define COMMON_FOLDER_DIALOG_ENTRY "entry"
108 #define COMMON_FOLDER_DIALOG_ACCOUNT_PICKER "account-picker"
109 #define FOLDER_PICKER_CURRENT_FOLDER "current-folder"
110 #define MODEST_ALARMD_APPID PACKAGE_NAME
113 static void _modest_platform_play_email_tone (void);
117 on_modest_conf_update_interval_changed (ModestConf* self,
119 ModestConfEvent event,
120 ModestConfNotificationId id,
123 g_return_if_fail (key);
125 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
126 const guint update_interval_minutes =
127 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
128 modest_platform_set_update_interval (update_interval_minutes);
135 check_required_files (void)
137 FILE *mcc_file = modest_utils_open_mcc_mapping_file (NULL);
139 g_printerr ("modest: check for mcc file failed\n");
144 if (access(MODEST_PROVIDER_DATA_FILE, R_OK) != 0 &&
145 access(MODEST_FALLBACK_PROVIDER_DATA_FILE, R_OK) != 0) {
146 g_printerr ("modest: cannot find providers data\n");
154 /* the gpointer here is the osso_context. */
156 modest_platform_init (int argc, char *argv[])
158 osso_context_t *osso_context;
160 osso_hw_state_t hw_state = { 0 };
164 if (!check_required_files ()) {
165 g_printerr ("modest: missing required files\n");
169 osso_context = osso_initialize(PACKAGE,PACKAGE_VERSION,
172 g_printerr ("modest: failed to acquire osso context\n");
175 modest_maemo_utils_set_osso_context (osso_context);
177 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
178 g_printerr ("modest: could not get dbus connection\n");
182 /* Add a D-Bus handler to be used when the main osso-rpc
183 * D-Bus handler has not handled something.
184 * We use this for D-Bus methods that need to use more complex types
185 * than osso-rpc supports.
187 if (!dbus_connection_add_filter (con,
188 modest_dbus_req_filter,
192 g_printerr ("modest: Could not add D-Bus filter\n");
196 /* Register our simple D-Bus callbacks, via the osso API: */
197 osso_return_t result = osso_rpc_set_cb_f(osso_context,
201 modest_dbus_req_handler, NULL /* user_data */);
202 if (result != OSSO_OK) {
203 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
207 /* Register hardware event dbus callback: */
208 hw_state.shutdown_ind = TRUE;
209 osso_hw_set_event_cb(osso_context, NULL, NULL, NULL);
211 /* Register osso auto-save callbacks: */
212 result = osso_application_set_autosave_cb (osso_context,
213 modest_on_osso_application_autosave, NULL /* user_data */);
214 if (result != OSSO_OK) {
215 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
220 /* Make sure that the update interval is changed whenever its gconf key
222 /* CAUTION: we're not using here the
223 modest_conf_listen_to_namespace because we know that there
224 are other parts of Modest listening for this namespace, so
225 we'll receive the notifications anyway. We basically do not
226 use it because there is no easy way to do the
227 modest_conf_forget_namespace */
228 ModestConf *conf = modest_runtime_get_conf ();
229 g_signal_connect (G_OBJECT(conf),
231 G_CALLBACK (on_modest_conf_update_interval_changed),
234 /* only force the setting of the default interval, if there are actually
236 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
238 /* Get the initial update interval from gconf: */
239 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
240 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
241 modest_account_mgr_free_account_names (acc_names);
245 #ifdef MODEST_HAVE_ABOOK
246 /* initialize the addressbook */
247 if (!osso_abook_init (&argc, &argv, osso_context)) {
248 g_printerr ("modest: failed to initialized addressbook\n");
251 #endif /*MODEST_HAVE_ABOOK*/
257 modest_platform_uninit (void)
259 osso_context_t *osso_context =
260 modest_maemo_utils_get_osso_context ();
262 osso_deinitialize (osso_context);
271 modest_platform_get_new_device (void)
273 return TNY_DEVICE (tny_maemo_conic_device_new ());
277 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
278 gchar **effective_mime_type)
280 GString *mime_str = NULL;
281 gchar *icon_name = NULL;
282 gchar **icons, **cursor;
284 if (!mime_type || g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0)
285 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
287 mime_str = g_string_new (mime_type);
288 g_string_ascii_down (mime_str);
291 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
293 for (cursor = icons; cursor; ++cursor) {
294 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
295 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
296 icon_name = g_strdup ("qgn_list_messagin");
298 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
299 icon_name = g_strdup (*cursor);
305 if (effective_mime_type)
306 *effective_mime_type = g_string_free (mime_str, FALSE);
308 g_string_free (mime_str, TRUE);
315 checked_hildon_uri_open (const gchar *uri, HildonURIAction *action)
320 g_return_val_if_fail (uri, FALSE);
322 result = hildon_uri_open (uri, action, &err);
324 g_printerr ("modest: hildon_uri_open ('%s', %p) failed: %s",
325 uri, action, err && err->message ? err->message : "unknown error");
335 modest_platform_activate_uri (const gchar *uri)
337 HildonURIAction *action;
338 gboolean result = FALSE;
339 GSList *actions, *iter = NULL;
341 g_return_val_if_fail (uri, FALSE);
345 /* don't try to activate file: uri's -- they might confuse the user,
346 * and/or might have security implications */
347 if (!g_str_has_prefix (uri, "file:")) {
349 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
351 for (iter = actions; iter; iter = g_slist_next (iter)) {
352 action = (HildonURIAction*) iter->data;
353 if (action && strcmp (hildon_uri_action_get_service (action),
354 "com.nokia.modest") == 0) {
355 result = checked_hildon_uri_open (uri, action);
360 /* if we could not open it with email, try something else */
362 result = checked_hildon_uri_open (uri, NULL);
366 ModestWindow *parent =
367 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
368 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
369 _("mcen_ib_unsupported_link"));
370 g_warning ("%s: cannot open uri '%s'", __FUNCTION__,uri);
377 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
381 gchar *uri_path = NULL;
383 uri_path = gnome_vfs_get_uri_from_local_path (path);
384 con = osso_get_dbus_connection (modest_maemo_utils_get_osso_context());
387 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
389 result = hildon_mime_open_file (con, uri_path);
391 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"), FALSE);
399 } ModestPlatformPopupInfo;
402 delete_uri_popup (GtkWidget *menu,
406 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
408 g_free (popup_info->uri);
409 hildon_uri_free_actions (popup_info->actions);
415 activate_uri_popup_item (GtkMenuItem *menu_item,
419 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
420 const gchar* action_name;
422 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
424 g_printerr ("modest: no action name defined\n");
428 /* special handling for the copy menu item -- copy the uri to the clipboard */
429 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
430 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
431 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
432 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
434 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
435 action_name += strlen ("mailto:");
437 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
438 modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
439 return; /* we're done */
442 /* now, the real uri-actions... */
443 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
444 HildonURIAction *action = (HildonURIAction *) node->data;
445 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
446 if (!checked_hildon_uri_open (popup_info->uri, action)) {
447 ModestWindow *parent =
448 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
449 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
450 _("mcen_ib_unsupported_link"));
458 modest_platform_show_uri_popup (const gchar *uri)
460 GSList *actions_list;
465 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
468 GtkWidget *menu = gtk_menu_new ();
469 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
471 /* don't add actions for file: uri's -- they might confuse the user,
472 * and/or might have security implications
473 * we still allow to copy the url though
475 if (!g_str_has_prefix (uri, "file:")) {
478 popup_info->actions = actions_list;
479 popup_info->uri = g_strdup (uri);
481 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
482 GtkWidget *menu_item;
483 const gchar *action_name;
484 const gchar *translation_domain;
485 HildonURIAction *action = (HildonURIAction *) node->data;
486 action_name = hildon_uri_action_get_name (action);
487 translation_domain = hildon_uri_action_get_translation_domain (action);
488 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
489 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
490 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
493 if (hildon_uri_is_default_action (action, NULL)) {
494 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
496 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
498 gtk_widget_show (menu_item);
503 /* and what to do when the link is deleted */
504 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
505 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
508 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
516 modest_platform_get_icon (const gchar *name, guint icon_size)
519 GdkPixbuf* pixbuf = NULL;
520 GtkIconTheme *current_theme = NULL;
522 g_return_val_if_fail (name, NULL);
524 /* strlen == 0 is not really an error; it just
525 * means the icon is not available
527 if (!name || strlen(name) == 0)
530 current_theme = gtk_icon_theme_get_default ();
531 pixbuf = gtk_icon_theme_load_icon (current_theme, name, icon_size,
532 GTK_ICON_LOOKUP_NO_SVG,
535 g_printerr ("modest: error loading theme icon '%s': %s\n",
543 modest_platform_get_app_name (void)
545 return _("mcen_ap_name");
549 entry_insert_text (GtkEditable *editable,
558 chars = gtk_editable_get_chars (editable, 0, -1);
559 chars_length = g_utf8_strlen (chars, -1);
562 /* Show WID-INF036 */
563 if (chars_length >= 20) {
564 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
565 _CS("ckdg_ib_maximum_characters_reached"));
567 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
571 tmp = g_strndup (folder_name_forbidden_chars,
572 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
573 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
574 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
580 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
581 _CS("ckdg_ib_maximum_characters_reached"));
583 /* Write the text in the entry if it's valid */
584 g_signal_handlers_block_by_func (editable,
585 (gpointer) entry_insert_text, data);
586 gtk_editable_insert_text (editable, text, length, position);
587 g_signal_handlers_unblock_by_func (editable,
588 (gpointer) entry_insert_text, data);
591 /* Do not allow further processing */
592 g_signal_stop_emission_by_name (editable, "insert_text");
596 entry_changed (GtkEditable *editable,
600 GtkWidget *ok_button;
603 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
604 ok_button = GTK_WIDGET (buttons->data);
606 chars = gtk_editable_get_chars (editable, 0, -1);
607 g_return_if_fail (chars != NULL);
610 if (g_utf8_strlen (chars,-1) >= 20) {
611 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
612 _CS("ckdg_ib_maximum_characters_reached"));
614 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
617 g_list_free (buttons);
624 on_response (GtkDialog *dialog,
628 GtkWidget *entry, *picker;
629 TnyFolderStore *parent;
630 const gchar *new_name;
633 if (response != GTK_RESPONSE_ACCEPT)
637 entry = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY);
638 picker = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER);
640 parent = TNY_FOLDER_STORE (user_data);
641 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
645 parent = g_object_get_data (G_OBJECT (picker), FOLDER_PICKER_CURRENT_FOLDER);
647 /* Look for another folder with the same name */
648 if (!TNY_IS_MERGE_FOLDER (parent) &&
649 modest_tny_folder_has_subfolder_with_name (parent, new_name, TRUE))
653 if (TNY_IS_ACCOUNT (parent) &&
654 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
655 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
663 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
664 NULL, _CS("ckdg_ib_folder_already_exists"));
665 /* Select the text */
666 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
667 gtk_widget_grab_focus (entry);
668 /* Do not close the dialog */
669 g_signal_stop_emission_by_name (dialog, "response");
673 typedef struct _FolderChooserData {
674 TnyFolderStore *store;
679 folder_chooser_activated (ModestFolderView *folder_view,
680 TnyFolderStore *folder,
681 FolderChooserData *userdata)
683 userdata->store = folder;
684 gtk_dialog_response (GTK_DIALOG (userdata->dialog), GTK_RESPONSE_OK);
687 static TnyFolderStore *
688 folder_chooser_dialog_run (ModestFolderView *original)
690 GtkWidget *folder_view;
691 FolderChooserData userdata = {NULL, NULL};
693 const gchar *visible_id = NULL;
695 userdata.dialog = hildon_dialog_new ();
696 pannable = hildon_pannable_area_new ();
697 folder_view = modest_platform_create_folder_view (NULL);
699 gtk_window_set_title (GTK_WINDOW (userdata.dialog), _FM("ckdg_ti_change_folder"));
701 modest_folder_view_copy_model (MODEST_FOLDER_VIEW (original),
702 MODEST_FOLDER_VIEW (folder_view));
705 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(original));
706 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view),
709 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (userdata.dialog)->vbox), pannable);
710 gtk_container_add (GTK_CONTAINER (pannable), folder_view);
711 gtk_widget_set_size_request (pannable, -1, 320);
713 gtk_widget_show (folder_view);
714 gtk_widget_show (pannable);
715 gtk_widget_show (userdata.dialog);
716 g_signal_connect (G_OBJECT (folder_view), "folder-activated",
717 G_CALLBACK (folder_chooser_activated),
718 (gpointer) &userdata);
720 gtk_dialog_run (GTK_DIALOG (userdata.dialog));
721 gtk_widget_destroy (userdata.dialog);
723 return userdata.store;
727 folder_store_get_display_name (TnyFolderStore *store)
729 if (TNY_IS_ACCOUNT (store)) {
730 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
731 return modest_conf_get_string (modest_runtime_get_conf(),
732 MODEST_CONF_DEVICE_NAME, NULL);
734 return g_strdup (tny_account_get_name (TNY_ACCOUNT (store)));
737 TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
739 fname = g_strdup (tny_folder_get_name (TNY_FOLDER (store)));
740 type = tny_folder_get_folder_type (TNY_FOLDER (store));
741 if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)) ||
742 modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
743 type = modest_tny_folder_get_local_or_mmc_folder_type (TNY_FOLDER (store));
744 if (type != TNY_FOLDER_TYPE_UNKNOWN) {
746 fname = g_strdup (modest_local_folder_info_get_type_display_name (type));
749 /* Sometimes an special folder is reported by the server as
750 NORMAL, like some versions of Dovecot */
751 if (type == TNY_FOLDER_TYPE_NORMAL ||
752 type == TNY_FOLDER_TYPE_UNKNOWN) {
753 type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
757 if (type == TNY_FOLDER_TYPE_INBOX) {
759 fname = g_strdup (_("mcen_me_folder_inbox"));
766 get_image_for_folder_store (TnyFolderStore *store,
770 const gchar *icon_name = NULL;
771 GtkWidget *image = NULL;
773 if (TNY_IS_ACCOUNT (store)) {
774 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
775 icon_name = MODEST_FOLDER_ICON_LOCAL_FOLDERS;
776 else if (modest_tny_account_is_memory_card_account (TNY_ACCOUNT (store)))
777 icon_name = MODEST_FOLDER_ICON_MMC;
779 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
781 TnyFolderType type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
782 if (modest_tny_folder_is_remote_folder (TNY_FOLDER (store))) {
784 case TNY_FOLDER_TYPE_INBOX:
785 icon_name = MODEST_FOLDER_ICON_INBOX;
788 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
790 } else if (modest_tny_folder_is_local_folder (TNY_FOLDER (store))) {
792 case TNY_FOLDER_TYPE_OUTBOX:
793 icon_name = MODEST_FOLDER_ICON_OUTBOX;
795 case TNY_FOLDER_TYPE_DRAFTS:
796 icon_name = MODEST_FOLDER_ICON_DRAFTS;
798 case TNY_FOLDER_TYPE_SENT:
799 icon_name = MODEST_FOLDER_ICON_SENT;
802 icon_name = MODEST_FOLDER_ICON_NORMAL;
804 } else if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
805 icon_name = MODEST_FOLDER_ICON_MMC_FOLDER;
810 pixbuf = modest_platform_get_icon (icon_name, size);
813 image = gtk_image_new_from_pixbuf (pixbuf);
814 g_object_unref (pixbuf);
821 folder_picker_set_store (GtkButton *button, TnyFolderStore *store)
826 g_object_set_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER, NULL);
830 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
831 g_object_ref (store),
832 (GDestroyNotify) g_object_unref);
833 name = folder_store_get_display_name (store);
834 hildon_button_set_value (HILDON_BUTTON (button), name);
838 image = get_image_for_folder_store (store, MODEST_ICON_SIZE_SMALL);
840 hildon_button_set_image (HILDON_BUTTON (button), image);
844 /* Always returns DUPs so you must free the returned value */
846 get_next_folder_name (const gchar *suggested_name,
847 TnyFolderStore *suggested_folder)
849 const gchar *default_name = _FM("ckdg_va_new_folder_name_stub");
851 gchar *real_suggested_name;
853 if (suggested_name !=NULL) {
854 return g_strdup (suggested_name);
857 for(i = 0; i < 100; ++ i) {
858 gboolean exists = FALSE;
861 real_suggested_name = g_strdup (default_name);
863 real_suggested_name = g_strdup_printf ("%s(%d)",
864 _FM("ckdg_va_new_folder_name_stub"),
866 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
873 g_free (real_suggested_name);
876 /* Didn't find a free number */
878 real_suggested_name = g_strdup (default_name);
880 return real_suggested_name;
884 ModestFolderView *folder_view;
886 } FolderPickerHelper;
889 folder_picker_clicked (GtkButton *button,
890 FolderPickerHelper *helper)
892 TnyFolderStore *store;
894 store = folder_chooser_dialog_run (helper->folder_view);
896 const gchar *current_name;
897 gboolean exists = FALSE;
899 folder_picker_set_store (GTK_BUTTON (button), store);
901 /* Update the name of the folder */
902 current_name = gtk_entry_get_text (helper->entry);
904 if (TNY_IS_FOLDER_STORE (store))
905 exists = modest_tny_folder_has_subfolder_with_name (store,
909 gchar *new_name = get_next_folder_name (NULL, store);
910 gtk_entry_set_text (helper->entry, new_name);
917 folder_picker_new (TnyFolderStore *suggested, FolderPickerHelper *helper)
921 button = hildon_button_new (MODEST_EDITABLE_SIZE,
922 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
924 hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 1.0);
927 folder_picker_set_store (GTK_BUTTON (button), suggested);
929 g_signal_connect (G_OBJECT (button), "clicked",
930 G_CALLBACK (folder_picker_clicked),
938 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
939 TnyFolderStore *suggested_parent,
940 const gchar *dialog_title,
941 const gchar *label_text,
942 const gchar *suggested_name,
944 gboolean show_parent,
946 TnyFolderStore **parent)
948 GtkWidget *accept_btn = NULL;
949 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
950 GtkWidget *account_picker = NULL;
951 GList *buttons = NULL;
953 GtkSizeGroup *sizegroup;
954 ModestFolderView *folder_view;
955 ModestWindow *folder_window;
956 ModestHildon2WindowMgr *window_mgr;
957 FolderPickerHelper *helper = NULL;
958 GtkWidget *top_vbox, *top_align;
960 window_mgr = (ModestHildon2WindowMgr *) modest_runtime_get_window_mgr ();
961 folder_window = modest_hildon2_window_mgr_get_folder_window (window_mgr);
962 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
964 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
966 top_vbox = gtk_vbox_new (FALSE, 0);
967 top_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
968 gtk_alignment_set_padding (GTK_ALIGNMENT (top_align), 0, 0, MODEST_MARGIN_DOUBLE, 0);
970 /* Ask the user for the folder name */
971 dialog = gtk_dialog_new_with_buttons (dialog_title,
973 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
974 _FM("ckdg_bd_new_folder_dialog_ok"),
978 /* Add accept button (with unsensitive handler) */
979 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
980 accept_btn = GTK_WIDGET (buttons->data);
982 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
985 label_entry = gtk_label_new (label_text);
986 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
987 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
989 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
990 gtk_size_group_add_widget (sizegroup, label_entry);
993 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
995 gtk_entry_set_text (GTK_ENTRY (entry), _FM("ckdg_va_new_folder_name_stub"));
996 gtk_entry_set_width_chars (GTK_ENTRY (entry),
997 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
998 g_utf8_strlen (_FM("ckdg_va_new_folder_name_stub"), -1)));
999 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
1004 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
1006 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
1007 gtk_size_group_add_widget (sizegroup, label_location);
1009 helper = g_slice_new0 (FolderPickerHelper);
1010 helper->folder_view = folder_view;
1011 helper->entry = (GtkEntry *) entry;
1013 account_picker = folder_picker_new (suggested_parent, helper);
1016 g_object_unref (sizegroup);
1018 /* Connect to the response method to avoid closing the dialog
1019 when an invalid name is selected*/
1020 g_signal_connect (dialog,
1022 G_CALLBACK (on_response),
1026 /* Track entry changes */
1027 g_signal_connect (entry,
1029 G_CALLBACK (entry_insert_text),
1031 g_signal_connect (entry,
1033 G_CALLBACK (entry_changed),
1038 /* Some locales like pt_BR need this to get the full window
1040 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
1042 /* Create the hbox */
1044 hbox = gtk_hbox_new (FALSE, 12);
1045 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
1046 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
1048 /* Add hbox to dialog */
1049 gtk_box_pack_start (GTK_BOX (top_vbox),
1050 hbox, FALSE, FALSE, 0);
1051 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
1055 hbox = gtk_hbox_new (FALSE, 12);
1056 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
1057 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
1059 /* Add hbox to dialog */
1060 gtk_box_pack_start (GTK_BOX (top_vbox),
1061 hbox, FALSE, FALSE, 0);
1062 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
1064 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1065 GTK_WINDOW (dialog), parent_window);
1067 gtk_container_add (GTK_CONTAINER (top_align), top_vbox);
1068 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), top_align, TRUE, TRUE, 0);
1070 gtk_widget_show_all (GTK_WIDGET(dialog));
1072 result = gtk_dialog_run (GTK_DIALOG(dialog));
1073 if (result == GTK_RESPONSE_ACCEPT) {
1075 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1077 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
1079 g_object_ref (*parent);
1083 gtk_widget_destroy (dialog);
1086 g_slice_free (FolderPickerHelper, helper);
1088 while (gtk_events_pending ())
1089 gtk_main_iteration ();
1095 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
1096 TnyFolderStore *suggested_folder,
1097 gchar *suggested_name,
1098 gchar **folder_name,
1099 TnyFolderStore **parent_folder)
1101 gchar *real_suggested_name = NULL;
1103 ModestTnyAccountStore *acc_store;
1104 TnyAccount *account;
1105 gboolean do_free = FALSE;
1107 real_suggested_name = get_next_folder_name ((const gchar *) suggested_name,
1110 /* In hildon 2.2 we always suggest the archive folder as parent */
1111 acc_store = modest_runtime_get_account_store ();
1112 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
1114 suggested_folder = (TnyFolderStore *)
1115 modest_tny_account_get_special_folder (account,
1116 TNY_FOLDER_TYPE_ARCHIVE);
1117 g_object_unref (account);
1121 /* If there is not archive folder then fallback to local folders account */
1122 if (!suggested_folder) {
1124 suggested_folder = (TnyFolderStore *)
1125 modest_tny_account_store_get_local_folders_account (acc_store);
1128 result = modest_platform_run_folder_common_dialog (parent_window,
1130 _HL("ckdg_ti_new_folder"),
1131 _FM("ckdg_fi_new_folder_name"),
1132 real_suggested_name,
1139 g_object_unref (suggested_folder);
1141 g_free(real_suggested_name);
1147 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1148 TnyFolderStore *parent_folder,
1149 const gchar *suggested_name,
1150 gchar **folder_name)
1152 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1154 return modest_platform_run_folder_common_dialog (parent_window,
1156 _HL("ckdg_ti_rename_folder"),
1157 _HL("ckdg_fi_rename_name"),
1168 on_destroy_dialog (GtkWidget *dialog)
1170 /* This could happen when the dialogs get programatically
1171 hidden or destroyed (for example when closing the
1172 application while a dialog is being shown) */
1173 if (!GTK_IS_WIDGET (dialog))
1176 gtk_widget_destroy (dialog);
1178 if (gtk_events_pending ())
1179 gtk_main_iteration ();
1183 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1184 const gchar *message)
1189 dialog = hildon_note_new_confirmation (parent_window, message);
1190 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1191 GTK_WINDOW (dialog), parent_window);
1193 response = gtk_dialog_run (GTK_DIALOG (dialog));
1195 on_destroy_dialog (dialog);
1201 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1202 const gchar *message,
1203 const gchar *button_accept,
1204 const gchar *button_cancel)
1209 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1210 button_accept, GTK_RESPONSE_ACCEPT,
1211 button_cancel, GTK_RESPONSE_CANCEL,
1214 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1215 GTK_WINDOW (dialog), parent_window);
1217 response = gtk_dialog_run (GTK_DIALOG (dialog));
1219 on_destroy_dialog (dialog);
1225 modest_platform_run_information_dialog (GtkWindow *parent_window,
1226 const gchar *message,
1231 note = hildon_note_new_information (parent_window, message);
1233 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1234 GTK_WINDOW (note), parent_window);
1237 gtk_dialog_run (GTK_DIALOG (note));
1239 on_destroy_dialog (note);
1241 g_signal_connect_swapped (note,
1243 G_CALLBACK (on_destroy_dialog),
1246 gtk_widget_show_all (note);
1250 typedef struct _ConnectAndWaitData {
1252 GMainLoop *wait_loop;
1253 gboolean has_callback;
1255 } ConnectAndWaitData;
1259 quit_wait_loop (TnyAccount *account,
1260 ConnectAndWaitData *data)
1262 /* Set the has_callback to TRUE (means that the callback was
1263 executed and wake up every code waiting for cond to be
1265 g_mutex_lock (data->mutex);
1266 data->has_callback = TRUE;
1267 if (data->wait_loop)
1268 g_main_loop_quit (data->wait_loop);
1269 g_mutex_unlock (data->mutex);
1273 on_connection_status_changed (TnyAccount *account,
1274 TnyConnectionStatus status,
1277 TnyConnectionStatus conn_status;
1278 ConnectAndWaitData *data;
1280 /* Ignore if reconnecting or disconnected */
1281 conn_status = tny_account_get_connection_status (account);
1282 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1283 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1286 /* Remove the handler */
1287 data = (ConnectAndWaitData *) user_data;
1288 g_signal_handler_disconnect (account, data->handler);
1290 /* Quit from wait loop */
1291 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1295 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1300 /* Quit from wait loop */
1301 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1305 modest_platform_connect_and_wait (GtkWindow *parent_window,
1306 TnyAccount *account)
1308 ConnectAndWaitData *data = NULL;
1309 gboolean device_online;
1311 TnyConnectionStatus conn_status;
1312 gboolean user_requested;
1314 device = modest_runtime_get_device();
1315 device_online = tny_device_is_online (device);
1317 /* Whether the connection is user requested or automatically
1318 requested, for example via D-Bus */
1319 user_requested = (parent_window) ? TRUE : FALSE;
1321 /* If there is no account check only the device status */
1326 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1327 NULL, user_requested);
1330 /* Return if the account is already connected */
1331 conn_status = tny_account_get_connection_status (account);
1332 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1335 /* Create the helper */
1336 data = g_slice_new0 (ConnectAndWaitData);
1337 data->mutex = g_mutex_new ();
1338 data->has_callback = FALSE;
1340 /* Connect the device */
1341 if (!device_online) {
1342 /* Track account connection status changes */
1343 data->handler = g_signal_connect (account, "connection-status-changed",
1344 G_CALLBACK (on_connection_status_changed),
1346 /* Try to connect the device */
1347 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1348 NULL, user_requested);
1350 /* If the device connection failed then exit */
1351 if (!device_online && data->handler)
1354 /* Force a reconnection of the account */
1355 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1356 on_tny_camel_account_set_online_cb, data);
1359 /* Wait until the callback is executed */
1360 g_mutex_lock (data->mutex);
1361 if (!data->has_callback) {
1362 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1363 gdk_threads_leave ();
1364 g_mutex_unlock (data->mutex);
1365 g_main_loop_run (data->wait_loop);
1366 g_mutex_lock (data->mutex);
1367 gdk_threads_enter ();
1369 g_mutex_unlock (data->mutex);
1372 if (g_signal_handler_is_connected (account, data->handler))
1373 g_signal_handler_disconnect (account, data->handler);
1374 g_mutex_free (data->mutex);
1375 g_main_loop_unref (data->wait_loop);
1376 g_slice_free (ConnectAndWaitData, data);
1378 conn_status = tny_account_get_connection_status (account);
1379 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1383 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1385 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1386 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1387 /* This must be a maildir account, which does not require a connection: */
1392 return modest_platform_connect_and_wait (parent_window, account);
1396 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1399 return TRUE; /* Maybe it is something local. */
1401 gboolean result = TRUE;
1402 if (TNY_IS_FOLDER (folder_store)) {
1403 /* Get the folder's parent account: */
1404 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1405 if (account != NULL) {
1406 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1407 g_object_unref (account);
1409 } else if (TNY_IS_ACCOUNT (folder_store)) {
1410 /* Use the folder store as an account: */
1411 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1418 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1422 dialog = modest_hildon2_sort_dialog_new (parent_window);
1429 modest_platform_set_update_interval (guint minutes)
1431 #ifdef MODEST_HAVE_LIBALARM
1433 ModestConf *conf = modest_runtime_get_conf ();
1437 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1439 /* Delete any existing alarm,
1440 * because we will replace it: */
1442 if (alarmd_event_del(alarm_cookie) != 0)
1443 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1445 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1448 /* 0 means no updates: */
1453 /* Register alarm: */
1455 /* Set the interval in alarm_event_t structure: */
1456 alarm_event_t *event = alarm_event_create ();
1457 alarm_event_add_actions (event, 1);
1458 alarm_action_t *action = alarm_event_get_action (event, 0);
1459 alarm_event_set_alarm_appid (event, MODEST_ALARMD_APPID);
1460 event->alarm_time = minutes * 60; /* seconds */
1462 /* Set recurrence every few minutes: */
1463 event->recur_secs = minutes*60;
1464 event->recur_count = -1; /* Means infinite */
1466 /* Specify what should happen when the alarm happens:
1467 * It should call this D-Bus method: */
1469 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1470 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1471 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1472 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1473 action->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1475 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1476 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1477 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1478 * This is why we want to use the Alarm API instead of just g_timeout_add().
1479 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1480 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1482 event->flags = ALARM_EVENT_CONNECTED;
1484 alarm_cookie = alarmd_event_add (event);
1487 alarm_event_delete (event);
1489 /* Store the alarm ID in GConf, so we can remove it later:
1490 * This is apparently valid between application instances. */
1491 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1493 if (!alarm_cookie) {
1495 g_debug ("Error setting alarm event. \n");
1499 #endif /* MODEST_HAVE_LIBALARM */
1504 modest_platform_push_email_notification(void)
1506 gboolean screen_on, app_in_foreground;
1508 /* Get the window status */
1509 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1511 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1513 /* If the screen is on and the app is in the
1514 foreground we don't show anything */
1515 if (!(screen_on && app_in_foreground)) {
1517 _modest_platform_play_email_tone ();
1519 /* Activate LED. This must be deactivated by
1520 modest_platform_remove_new_mail_notifications */
1521 #ifdef MODEST_HAVE_MCE
1522 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1526 MCE_ACTIVATE_LED_PATTERN,
1528 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1535 modest_platform_on_new_headers_received (TnyList *header_list,
1536 gboolean show_visual)
1538 g_return_if_fail (TNY_IS_LIST (header_list));
1540 if (tny_list_get_length (header_list) < 1)
1543 /* If the window is in the foreground don't do anything */
1544 if (hildon_program_get_is_topmost (hildon_program_get_instance ()))
1547 #ifdef MODEST_HAVE_HILDON_NOTIFY
1548 /* For any other case issue a notification */
1549 HildonNotification *notification;
1551 GSList *notifications_list = NULL;
1553 /* Get previous notifications ids */
1554 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1555 MODEST_CONF_NOTIFICATION_IDS,
1556 MODEST_CONF_VALUE_INT, NULL);
1558 iter = tny_list_create_iterator (header_list);
1559 while (!tny_iterator_is_done (iter)) {
1560 gchar *url = NULL, *display_address = NULL;
1561 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1562 TnyFolder *folder = tny_header_get_folder (header);
1563 gboolean first_notification = TRUE;
1567 display_address = tny_header_dup_from (header);
1568 /* string is changed in-place */
1569 modest_text_utils_get_display_address (display_address);
1571 str = tny_header_dup_subject (header);
1572 notification = hildon_notification_new (display_address,
1574 "qgn_list_messagin",
1575 MODEST_NOTIFICATION_CATEGORY);
1577 /* Create the message URL */
1578 str = tny_header_dup_uid (header);
1579 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1583 hildon_notification_add_dbus_action(notification,
1586 MODEST_DBUS_SERVICE,
1589 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1593 /* Play sound if the user wants. Show the LED
1594 pattern. Show and play just one */
1595 if (G_UNLIKELY (first_notification)) {
1596 TnyAccount *account;
1598 first_notification = FALSE;
1600 /* Set the led pattern */
1601 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1603 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1605 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1607 /* Set the account of the headers */
1608 account = tny_folder_get_account (folder);
1610 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1612 tny_account_get_id (account));
1613 g_object_unref (account);
1617 /* Notify. We need to do this in an idle because this function
1618 could be called from a thread */
1619 if (!notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL)) {
1620 g_warning ("Failed to send notification");
1623 /* Save id in the list */
1624 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1625 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1626 /* We don't listen for the "closed" signal, because we
1627 don't care about if the notification was removed or
1628 not to store the list in gconf */
1630 /* Free & carry on */
1631 g_free (display_address);
1633 g_object_unref (folder);
1634 g_object_unref (header);
1635 tny_iterator_next (iter);
1637 g_object_unref (iter);
1640 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1641 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1643 g_slist_free (notifications_list);
1645 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1649 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1652 #ifdef MODEST_HAVE_MCE
1653 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1657 MCE_DEACTIVATE_LED_PATTERN,
1659 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1665 #ifdef MODEST_HAVE_HILDON_NOTIFY
1666 GSList *notif_list = NULL;
1668 /* Get previous notifications ids */
1669 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1670 MODEST_CONF_NOTIFICATION_IDS,
1671 MODEST_CONF_VALUE_INT, NULL);
1673 while (notif_list) {
1675 NotifyNotification *notif;
1677 /* Nasty HACK to remove the notifications, set the id
1678 of the existing ones and then close them */
1679 notif_id = GPOINTER_TO_INT(notif_list->data);
1680 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1681 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1683 /* Close the notification, note that some ids could be
1684 already invalid, but we don't care because it does
1686 notify_notification_close(notif, NULL);
1687 g_object_unref(notif);
1689 /* Delete the link, it's like going to the next */
1690 notif_list = g_slist_delete_link (notif_list, notif_list);
1694 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1695 notif_list, MODEST_CONF_VALUE_INT, NULL);
1697 g_slist_free (notif_list);
1699 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1705 modest_platform_get_global_settings_dialog ()
1707 return modest_hildon2_global_settings_dialog_new ();
1711 modest_platform_show_help (GtkWindow *parent_window,
1712 const gchar *help_id)
1718 modest_platform_show_search_messages (GtkWindow *parent_window)
1720 osso_return_t result = OSSO_ERROR;
1722 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1723 "osso_global_search",
1724 "search_email", NULL, DBUS_TYPE_INVALID);
1726 if (result != OSSO_OK) {
1727 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1732 modest_platform_show_addressbook (GtkWindow *parent_window)
1734 osso_return_t result = OSSO_ERROR;
1736 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1738 "top_application", NULL, DBUS_TYPE_INVALID);
1740 if (result != OSSO_OK) {
1741 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1746 modest_platform_create_folder_view_full (TnyFolderStoreQuery *query, gboolean do_refresh)
1748 GtkWidget *widget = modest_folder_view_new_full (query, do_refresh);
1750 /* Show one account by default */
1751 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1752 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1754 /* Restore settings */
1755 modest_widget_memory_restore (modest_runtime_get_conf(),
1757 MODEST_CONF_FOLDER_VIEW_KEY);
1763 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1765 return modest_platform_create_folder_view_full (query, TRUE);
1769 banner_finish (gpointer data, GObject *object)
1771 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1772 modest_window_mgr_unregister_banner (mgr);
1773 g_object_unref (mgr);
1777 modest_platform_information_banner (GtkWidget *parent,
1778 const gchar *icon_name,
1781 GtkWidget *banner, *banner_parent = NULL;
1782 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1784 if (modest_window_mgr_get_num_windows (mgr) == 0)
1787 if (parent && GTK_IS_WINDOW (parent)) {
1788 /* If the window is the active one then show the
1789 banner on top of this window */
1790 if (gtk_window_is_active (GTK_WINDOW (parent)))
1791 banner_parent = parent;
1792 /* If the window is not the topmost but it's visible
1793 (it's minimized for example) then show the banner
1795 else if (GTK_WIDGET_VISIBLE (parent))
1796 banner_parent = NULL;
1797 /* If the window is hidden (like the main window when
1798 running in the background) then do not show
1805 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1807 modest_window_mgr_register_banner (mgr);
1809 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1813 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1814 const gchar *icon_name,
1820 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1823 banner = hildon_banner_show_information (parent, icon_name, text);
1824 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1828 modest_platform_animation_banner (GtkWidget *parent,
1829 const gchar *animation_name,
1832 GtkWidget *inf_note = NULL;
1834 g_return_val_if_fail (text != NULL, NULL);
1836 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1839 /* If the parent is not visible then do not show */
1840 if (parent && !GTK_WIDGET_VISIBLE (parent))
1843 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1851 TnyAccount *account;
1854 } CheckAccountIdleData;
1856 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1859 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1861 gboolean stop_trying = FALSE;
1862 g_return_val_if_fail (data && data->account, FALSE);
1864 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1865 tny_account_get_connection_status (data->account));
1867 if (data && data->account &&
1868 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1869 * after which the account is likely to be usable, or never likely to be usable soon: */
1870 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1872 data->is_online = TRUE;
1876 /* Give up if we have tried too many times: */
1877 if (data->count_tries >= NUMBER_OF_TRIES) {
1880 /* Wait for another timeout: */
1881 ++(data->count_tries);
1886 /* Allow the function that requested this idle callback to continue: */
1888 g_main_loop_quit (data->loop);
1891 g_object_unref (data->account);
1893 return FALSE; /* Don't call this again. */
1895 return TRUE; /* Call this timeout callback again. */
1899 /* Return TRUE immediately if the account is already online,
1900 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1901 * soon as the account is online, or FALSE if the account does
1902 * not become online in the NUMBER_OF_TRIES seconds.
1903 * This is useful when the D-Bus method was run immediately after
1904 * the application was started (when using D-Bus activation),
1905 * because the account usually takes a short time to go online.
1906 * The return value is maybe not very useful.
1909 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1913 g_return_val_if_fail (account, FALSE);
1915 if (!tny_device_is_online (modest_runtime_get_device())) {
1916 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1920 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1921 * so we avoid wait unnecessarily: */
1922 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1925 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1926 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1927 * we want to avoid. */
1928 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1931 /* This blocks on the result: */
1932 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1933 data->is_online = FALSE;
1934 data->account = account;
1935 g_object_ref (data->account);
1936 data->count_tries = 0;
1938 GMainContext *context = NULL; /* g_main_context_new (); */
1939 data->loop = g_main_loop_new (context, FALSE /* not running */);
1941 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1943 /* This main loop will run until the idle handler has stopped it: */
1944 g_main_loop_run (data->loop);
1946 g_main_loop_unref (data->loop);
1947 /* g_main_context_unref (context); */
1949 is_online = data->is_online;
1950 g_slice_free (CheckAccountIdleData, data);
1958 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1960 /* GTK_RESPONSE_HELP means we need to show the certificate */
1961 if (response_id == GTK_RESPONSE_APPLY) {
1965 /* Do not close the dialog */
1966 g_signal_stop_emission_by_name (dialog, "response");
1968 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1969 note = hildon_note_new_information (NULL, msg);
1970 gtk_dialog_run (GTK_DIALOG(note));
1971 gtk_widget_destroy (note);
1977 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1978 const gchar *certificate)
1983 HildonWindowStack *stack;
1985 stack = hildon_window_stack_get_default ();
1986 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1989 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1994 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1997 /* We use GTK_RESPONSE_APPLY because we want the button in the
1998 middle of OK and CANCEL the same as the browser does for
1999 example. With GTK_RESPONSE_HELP the view button is aligned
2000 to the left while the other two to the right */
2001 note = hildon_note_new_confirmation_add_buttons (
2004 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
2005 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
2006 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
2009 g_signal_connect (G_OBJECT(note), "response",
2010 G_CALLBACK(on_cert_dialog_response),
2011 (gpointer) certificate);
2013 response = gtk_dialog_run(GTK_DIALOG(note));
2015 on_destroy_dialog (note);
2018 return response == GTK_RESPONSE_OK;
2022 modest_platform_run_alert_dialog (const gchar* prompt,
2023 gboolean is_question)
2025 ModestWindow *top_win;
2026 HildonWindowStack *stack;
2028 stack = hildon_window_stack_get_default ();
2029 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
2032 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
2037 gboolean retval = TRUE;
2039 /* The Tinymail documentation says that we should show Yes and No buttons,
2040 * when it is a question.
2041 * Obviously, we need tinymail to use more specific error codes instead,
2042 * so we know what buttons to show. */
2043 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
2045 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2046 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
2048 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
2049 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
2051 on_destroy_dialog (dialog);
2053 /* Just show the error text and use the default response: */
2054 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
2062 GtkWindow *parent_window;
2063 ModestConnectedPerformer callback;
2064 TnyAccount *account;
2071 on_went_online_info_free (OnWentOnlineInfo *info)
2073 /* And if we cleanup, we DO cleanup :-) */
2076 g_object_unref (info->device);
2079 if (info->parent_window)
2080 g_object_unref (info->parent_window);
2082 g_object_unref (info->account);
2084 g_slice_free (OnWentOnlineInfo, info);
2086 /* We're done ... */
2092 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
2094 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2096 /* Now it's really time to callback to the caller. If going online didn't succeed,
2097 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
2098 * canceled will be set. Etcetera etcetera. */
2100 if (info->callback) {
2101 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2104 /* This is our last call, we must cleanup here if we didn't yet do that */
2105 on_went_online_info_free (info);
2112 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2114 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2115 info->iap = g_strdup (iap_id);
2117 if (canceled || err || !info->account) {
2119 /* If there's a problem or if there's no account (then that's it for us, we callback
2120 * the caller's callback now. He'll have to handle err or canceled, of course.
2121 * We are not really online, as the account is not really online here ... */
2123 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2124 * this info. We don't cleanup err, Tinymail does that! */
2126 if (info->callback) {
2128 /* info->account can be NULL here, this means that the user did not
2129 * provide a nice account instance. We'll assume that the user knows
2130 * what he's doing and is happy with just the device going online.
2132 * We can't do magic, we don't know what account the user wants to
2133 * see going online. So just the device goes online, end of story */
2135 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2138 } else if (info->account) {
2140 /* If there's no problem and if we have an account, we'll put the account
2141 * online too. When done, the callback of bringing the account online
2142 * will callback the caller's callback. This is the most normal case. */
2144 info->device = TNY_DEVICE (g_object_ref (device));
2146 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2147 on_account_went_online, info);
2149 /* The on_account_went_online cb frees up the info, go look if you
2150 * don't believe me! (so we return here) */
2155 /* We cleanup if we are not bringing the account online too */
2156 on_went_online_info_free (info);
2162 modest_platform_connect_and_perform (GtkWindow *parent_window,
2164 TnyAccount *account,
2165 ModestConnectedPerformer callback,
2168 gboolean device_online;
2170 TnyConnectionStatus conn_status;
2171 OnWentOnlineInfo *info;
2173 device = modest_runtime_get_device();
2174 device_online = tny_device_is_online (device);
2176 /* If there is no account check only the device status */
2179 if (device_online) {
2181 /* We promise to instantly perform the callback, so ... */
2183 callback (FALSE, NULL, parent_window, account, user_data);
2188 info = g_slice_new0 (OnWentOnlineInfo);
2191 info->device = NULL;
2192 info->account = NULL;
2195 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2197 info->parent_window = NULL;
2198 info->user_data = user_data;
2199 info->callback = callback;
2201 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2202 force, on_conic_device_went_online,
2205 /* We'll cleanup in on_conic_device_went_online */
2208 /* The other code has no more reason to run. This is all that we can do for the
2209 * caller (he should have given us a nice and clean account instance!). We
2210 * can't do magic, we don't know what account he intends to bring online. So
2211 * we'll just bring the device online (and await his false bug report). */
2217 /* Return if the account is already connected */
2219 conn_status = tny_account_get_connection_status (account);
2220 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2222 /* We promise to instantly perform the callback, so ... */
2224 callback (FALSE, NULL, parent_window, account, user_data);
2230 /* Else, we are in a state that requires that we go online before we
2231 * call the caller's callback. */
2233 info = g_slice_new0 (OnWentOnlineInfo);
2235 info->device = NULL;
2237 info->account = TNY_ACCOUNT (g_object_ref (account));
2240 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2242 info->parent_window = NULL;
2244 /* So we'll put the callback away for later ... */
2246 info->user_data = user_data;
2247 info->callback = callback;
2249 if (!device_online) {
2251 /* If also the device is offline, then we connect both the device
2252 * and the account */
2254 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2255 force, on_conic_device_went_online,
2260 /* If the device is online, we'll just connect the account */
2262 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2263 on_account_went_online, info);
2266 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2267 * in both situations, go look if you don't believe me! */
2273 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2275 TnyFolderStore *folder_store,
2276 ModestConnectedPerformer callback,
2279 TnyAccount *account = NULL;
2281 if (!folder_store ||
2282 (TNY_IS_MERGE_FOLDER (folder_store) &&
2283 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2285 /* We promise to instantly perform the callback, so ... */
2287 GError *error = NULL;
2288 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2289 "Unable to move or not found folder");
2290 callback (FALSE, error, parent_window, NULL, user_data);
2291 g_error_free (error);
2295 } else if (TNY_IS_FOLDER (folder_store)) {
2296 /* Get the folder's parent account: */
2297 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2298 } else if (TNY_IS_ACCOUNT (folder_store)) {
2299 /* Use the folder store as an account: */
2300 account = TNY_ACCOUNT (g_object_ref (folder_store));
2303 if (account && (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE)) {
2304 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2305 /* No need to connect a local account */
2307 callback (FALSE, NULL, parent_window, account, user_data);
2312 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2316 g_object_unref (account);
2320 src_account_connect_performer (gboolean canceled,
2322 GtkWindow *parent_window,
2323 TnyAccount *src_account,
2326 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2328 if (canceled || err) {
2329 /* If there was any error call the user callback */
2330 info->callback (canceled, err, parent_window, src_account, info->data);
2332 /* Connect the destination account */
2333 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2334 TNY_FOLDER_STORE (info->dst_account),
2335 info->callback, info->data);
2338 /* Free the info object */
2339 g_object_unref (info->dst_account);
2340 g_slice_free (DoubleConnectionInfo, info);
2345 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2347 TnyFolderStore *folder_store,
2348 DoubleConnectionInfo *connect_info)
2350 modest_platform_connect_if_remote_and_perform(parent_window,
2353 src_account_connect_performer,
2358 modest_platform_get_account_settings_wizard (void)
2360 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2362 return GTK_WIDGET (dialog);
2366 modest_platform_get_current_connection (void)
2368 TnyDevice *device = NULL;
2369 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2371 device = modest_runtime_get_device ();
2373 if (!tny_device_is_online (device))
2374 return MODEST_CONNECTED_VIA_ANY;
2376 #ifdef MODEST_HAVE_CONIC
2378 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2380 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2381 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2382 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2384 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2385 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2386 !strcmp (bearer_type, "WIMAX")) {
2387 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2389 retval = MODEST_CONNECTED_VIA_ANY;
2392 g_object_unref (iap);
2395 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2396 #endif /* MODEST_HAVE_CONIC */
2403 modest_platform_check_memory_low (ModestWindow *win,
2408 /* are we in low memory state? */
2409 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2411 if (win && lowmem && visuals)
2412 modest_platform_run_information_dialog (
2414 _KR("memr_ib_operation_disabled"),
2418 g_debug ("%s: low memory reached. disallowing some operations",
2425 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2431 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2434 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2435 GTK_WINDOW (dialog),
2437 gtk_widget_show_all (dialog);
2439 g_signal_connect_swapped (dialog, "response",
2440 G_CALLBACK (gtk_widget_destroy),
2444 typedef struct _HeaderDetailsGetSizeInfo {
2448 } HeaderDetailsGetSizeInfo;
2451 header_details_dialog_destroy (gpointer userdata,
2454 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) userdata;
2456 info->dialog = NULL;
2460 idle_get_mime_part_size_cb (gpointer userdata)
2462 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) userdata;
2463 gdk_threads_enter ();
2465 if (info->dialog && GTK_WIDGET_VISIBLE (info->dialog)) {
2466 modest_details_dialog_set_message_size (MODEST_DETAILS_DIALOG (info->dialog),
2471 g_object_weak_unref (G_OBJECT (info->dialog), header_details_dialog_destroy, info);
2472 info->dialog = NULL;
2474 g_object_unref (info->part);
2475 g_slice_free (HeaderDetailsGetSizeInfo, info);
2477 gdk_threads_leave ();
2483 get_mime_part_size_thread (gpointer thr_user_data)
2485 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) thr_user_data;
2487 TnyStream *count_stream;
2489 count_stream = modest_count_stream_new ();
2490 result = tny_mime_part_decode_to_stream (info->part, count_stream, NULL);
2491 info->total = modest_count_stream_get_count(MODEST_COUNT_STREAM (count_stream));
2492 if (info->total == 0) {
2493 modest_count_stream_reset_count(MODEST_COUNT_STREAM (count_stream));
2494 result = tny_mime_part_write_to_stream (info->part, count_stream, NULL);
2495 info->total = modest_count_stream_get_count(MODEST_COUNT_STREAM (count_stream));
2498 /* if there was an error, don't set the size (this is pretty uncommon) */
2500 g_warning ("%s: error while writing mime part to stream\n", __FUNCTION__);
2502 g_idle_add (idle_get_mime_part_size_cb, info);
2508 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2510 gboolean async_get_size,
2516 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header, !async_get_size);
2518 if (async_get_size && msg && TNY_IS_MSG (msg)) {
2519 HeaderDetailsGetSizeInfo *info;
2520 info = g_slice_new (HeaderDetailsGetSizeInfo);
2521 info->dialog = dialog;
2523 info->part = TNY_MIME_PART (g_object_ref (msg));
2525 g_object_weak_ref (G_OBJECT (dialog), header_details_dialog_destroy, info);
2526 g_thread_create (get_mime_part_size_thread, info, FALSE, NULL);
2530 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2531 GTK_WINDOW (dialog),
2533 gtk_widget_show_all (dialog);
2535 g_signal_connect_swapped (dialog, "response",
2536 G_CALLBACK (gtk_widget_destroy),
2541 modest_platform_get_osso_context (void)
2543 return modest_maemo_utils_get_osso_context ();
2547 _modest_platform_play_email_tone (void)
2550 gint mail_volume_int;
2552 ca_context *ca_con = NULL;
2553 ca_proplist *pl = NULL;
2555 #ifdef MODEST_USE_PROFILE
2556 gchar *active_profile;
2559 active_profile = profile_get_profile ();
2560 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2561 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2562 mail_volume_int = profile_parse_int (mail_volume);
2563 g_free (mail_volume);
2564 g_free (active_profile);
2566 mail_tone = MAIL_TONE;
2567 mail_volume_int = 100;
2570 if (mail_tone && !strstr (mail_tone, "/")) {
2573 tmp = g_strconcat ("/usr/share/sounds", mail_tone, NULL);
2578 if (mail_volume_int > 0) {
2580 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2581 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2585 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2586 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2587 ca_context_destroy(ca_con);
2591 ca_proplist_create(&pl);
2592 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2593 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2595 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2596 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2598 ca_proplist_destroy(pl);
2599 ca_context_destroy(ca_con);
2605 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
2606 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
2607 #define MOVE_TO_DIALOG_ACTION_BUTTON "action-button"
2608 #define MOVE_TO_DIALOG_SHOWING_FOLDERS "showing-folders"
2609 #define MOVE_TO_DIALOG_PANNABLE "pannable"
2610 #define MOVE_TO_FOLDER_SEPARATOR "/"
2613 move_to_dialog_set_selected_folder_store (GtkWidget *dialog,
2614 TnyFolderStore *folder_store)
2616 GtkWidget *action_button;
2617 GtkWidget *image = NULL;
2618 TnyAccount *account;
2619 gchar *account_name = NULL, *short_name = NULL;
2621 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2623 /* Get account name */
2624 if (TNY_IS_FOLDER (folder_store))
2625 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2627 account = g_object_ref (folder_store);
2629 if (modest_tny_account_is_virtual_local_folders (account))
2630 account_name = modest_conf_get_string (modest_runtime_get_conf(),
2631 MODEST_CONF_DEVICE_NAME, NULL);
2634 account_name = g_strdup (tny_account_get_name (account));
2636 g_object_unref (account);
2638 /* Set title of button: account or folder name */
2639 if (TNY_IS_FOLDER (folder_store))
2640 short_name = folder_store_get_display_name (folder_store);
2642 short_name = g_strdup (account_name);
2644 hildon_button_set_title (HILDON_BUTTON (action_button), short_name);
2646 /* Set value of button, folder full name */
2647 if (TNY_IS_CAMEL_FOLDER (folder_store)) {
2648 const gchar *camel_full_name;
2649 gchar *last_slash, *full_name;
2651 camel_full_name = tny_camel_folder_get_full_name (TNY_CAMEL_FOLDER (folder_store));
2652 last_slash = g_strrstr (camel_full_name, "/");
2654 gchar *prefix = g_strndup (camel_full_name, last_slash - camel_full_name + 1);
2655 full_name = g_strconcat (account_name, MOVE_TO_FOLDER_SEPARATOR, prefix, short_name, NULL);
2658 full_name = g_strconcat (account_name, MOVE_TO_FOLDER_SEPARATOR,
2662 hildon_button_set_value (HILDON_BUTTON (action_button), full_name);
2665 g_free (account_name);
2666 g_free (short_name);
2668 /* Set image for the button */
2669 image = get_image_for_folder_store (folder_store, MODEST_ICON_SIZE_BIG);
2671 hildon_button_set_image (HILDON_BUTTON (action_button), image);
2675 move_to_dialog_show_accounts (GtkWidget *dialog)
2677 GtkWidget *back_button;
2678 GtkWidget *folder_view;
2679 GtkWidget *pannable;
2680 GtkWidget *action_button;
2682 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2683 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2684 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2685 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2687 gtk_widget_set_sensitive (back_button, FALSE);
2688 gtk_widget_set_sensitive (action_button, FALSE);
2690 /* Need to set this here, otherwise callbacks called because
2691 of filtering won't perform correctly */
2692 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (FALSE));
2694 /* Reset action button */
2695 hildon_button_set_title (HILDON_BUTTON (action_button), NULL);
2696 hildon_button_set_value (HILDON_BUTTON (action_button), NULL);
2697 hildon_button_set_image (HILDON_BUTTON (action_button), NULL);
2699 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view), NULL);
2700 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2701 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
2702 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
2703 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2704 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
2705 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2706 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
2707 MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
2708 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2709 MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2710 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2714 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
2716 GtkWidget *back_button;
2717 GtkWidget *folder_view;
2718 TnyAccount *account;
2719 const gchar *account_id;
2720 GtkWidget *pannable;
2721 GtkWidget *action_button;
2724 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2726 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2728 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2730 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2732 gtk_widget_set_sensitive (back_button, TRUE);
2733 gtk_widget_set_sensitive (action_button, TRUE);
2735 /* Need to set this here, otherwise callbacks called because
2736 of filtering won't perform correctly */
2737 g_object_set_data (G_OBJECT (dialog),
2738 MOVE_TO_DIALOG_SHOWING_FOLDERS,
2739 GINT_TO_POINTER (TRUE));
2741 account = TNY_ACCOUNT (folder_store);
2742 if (modest_tny_account_is_virtual_local_folders (account)) {
2743 account_id = tny_account_get_id (account);
2744 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2745 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2746 } else if (modest_tny_account_is_memory_card_account (account)) {
2747 account_id = tny_account_get_id (account);
2748 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2749 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2751 account_id = tny_account_get_id (account);
2752 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2753 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2754 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2755 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2758 move_to_dialog_set_selected_folder_store (dialog, folder_store);
2759 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
2762 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
2763 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
2764 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
2765 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2766 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2770 on_move_to_dialog_back_clicked (GtkButton *button,
2773 GtkWidget *dialog = (GtkWidget *) userdata;
2775 /* Back to show accounts */
2776 move_to_dialog_show_accounts (dialog);
2780 on_move_to_dialog_row_activated (GtkTreeView *tree_view,
2782 GtkTreeViewColumn *column,
2785 TnyFolderStore *selected = NULL;
2787 GtkWidget *folder_view;
2788 gboolean showing_folders;
2790 dialog = (GtkWidget *) user_data;
2791 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog),
2792 MOVE_TO_DIALOG_SHOWING_FOLDERS));
2794 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog),
2795 MOVE_TO_DIALOG_FOLDER_VIEW));
2797 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2801 if (!showing_folders) {
2802 gboolean valid = TRUE;
2804 if (TNY_IS_ACCOUNT (selected) &&
2805 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (selected))) {
2806 ModestProtocolType protocol_type;
2808 protocol_type = modest_tny_account_get_protocol_type (TNY_ACCOUNT (selected));
2809 valid = !modest_protocol_registry_protocol_type_has_tag
2810 (modest_runtime_get_protocol_registry (),
2812 MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
2815 move_to_dialog_show_folders (dialog, selected);
2817 move_to_dialog_set_selected_folder_store (dialog, selected);
2822 on_move_to_dialog_selection_changed (GtkTreeSelection *selection,
2825 gboolean showing_folders;
2828 dialog = (GtkWidget *) user_data;
2829 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2830 if (showing_folders) {
2831 TnyFolderStore *selected;
2832 GtkWidget *folder_view;
2834 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2835 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2838 move_to_dialog_set_selected_folder_store (dialog, selected);
2839 g_object_unref (selected);
2845 on_move_to_dialog_action_clicked (GtkButton *selection,
2849 gboolean showing_folders;
2851 dialog = (GtkWidget *) user_data;
2852 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2853 if (showing_folders) {
2854 TnyFolderStore *selected;
2855 GtkWidget *folder_view;
2857 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2858 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2861 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
2862 g_object_unref (selected);
2868 move_to_dialog_activity_changed (ModestFolderView *folder_view, gboolean activity, GtkDialog *dialog)
2870 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (dialog), activity?1:0);
2874 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2875 GtkWidget **folder_view)
2877 GtkWidget *dialog, *folder_view_container;
2879 GtkWidget *buttons_hbox;
2880 GtkWidget *back_button;
2881 GdkPixbuf *back_pixbuf;
2882 GtkWidget *top_vbox;
2883 GtkWidget *action_button;
2884 GtkTreeSelection *selection;
2886 /* Create dialog. We cannot use a touch selector because we
2887 need to use here the folder view widget directly */
2888 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2889 GTK_WINDOW (parent_window),
2890 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2891 GTK_DIALOG_DESTROY_WITH_PARENT,
2892 _HL("wdgt_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2895 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
2896 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_NONE);
2897 top_vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
2899 /* Create folder view */
2900 *folder_view = modest_platform_create_folder_view_full (NULL, FALSE);
2901 g_signal_connect (G_OBJECT (*folder_view), "activity-changed", G_CALLBACK (move_to_dialog_activity_changed),
2904 modest_folder_view_set_cell_style (MODEST_FOLDER_VIEW (*folder_view),
2905 MODEST_FOLDER_VIEW_CELL_STYLE_COMPACT);
2906 modest_folder_view_show_message_count (MODEST_FOLDER_VIEW (*folder_view),
2908 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2909 (TnyAccountStore *) modest_runtime_get_account_store ());
2911 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
2912 back_button = gtk_button_new ();
2913 back_pixbuf = modest_platform_get_icon (_FM("filemanager_folder_up"), MODEST_ICON_SIZE_BIG);
2915 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
2916 g_object_unref (back_pixbuf);
2919 action_button = hildon_button_new (HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT,
2920 HILDON_BUTTON_ARRANGEMENT_VERTICAL);
2921 gtk_button_set_alignment (GTK_BUTTON (action_button), 0.0, 0.5);
2923 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
2924 gtk_box_pack_start (GTK_BOX (buttons_hbox), action_button, TRUE, TRUE, 0);
2925 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
2926 gtk_widget_set_sensitive (GTK_WIDGET (action_button), FALSE);
2927 gtk_box_pack_start (GTK_BOX (top_vbox), buttons_hbox, FALSE, FALSE, 0);
2929 /* Create pannable and add it to the dialog */
2930 folder_view_container = hildon_pannable_area_new ();
2931 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2932 gtk_box_pack_start (GTK_BOX (top_vbox), folder_view_container, TRUE, TRUE, 0);
2934 gtk_container_add (GTK_CONTAINER (align), top_vbox);
2935 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), align, TRUE, TRUE, 0);
2937 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2939 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2940 gtk_widget_show (folder_view_container);
2941 gtk_widget_show (align);
2942 gtk_widget_show (top_vbox);
2943 gtk_widget_show (*folder_view);
2944 gtk_widget_show_all (back_button);
2945 gtk_widget_show (action_button);
2946 gtk_widget_show (buttons_hbox);
2947 gtk_widget_show (dialog);
2949 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
2950 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
2951 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON, action_button);
2952 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE, folder_view_container);
2954 /* Simulate the behaviour of a HildonPickerDialog by emitting
2955 a response when a folder is selected */
2956 g_signal_connect (*folder_view, "row-activated",
2957 G_CALLBACK (on_move_to_dialog_row_activated),
2960 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (*folder_view));
2961 g_signal_connect (selection, "changed",
2962 G_CALLBACK (on_move_to_dialog_selection_changed),
2965 g_signal_connect (action_button, "clicked",
2966 G_CALLBACK (on_move_to_dialog_action_clicked),
2969 g_signal_connect (back_button, "clicked",
2970 G_CALLBACK (on_move_to_dialog_back_clicked),
2973 move_to_dialog_show_accounts (dialog);
2979 modest_platform_get_list_to_move (ModestWindow *window)
2981 TnyList *list = NULL;
2983 if (MODEST_IS_HEADER_WINDOW (window)) {
2984 ModestHeaderView *header_view;
2986 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2987 list = modest_header_view_get_selected_headers (header_view);
2988 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2989 ModestFolderView *folder_view;
2990 TnyFolderStore *selected_folder;
2992 list = TNY_LIST (tny_simple_list_new ());
2993 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2994 selected_folder = modest_folder_view_get_selected (folder_view);
2995 if (selected_folder) {
2996 tny_list_prepend (list, G_OBJECT (selected_folder));
2997 g_object_unref (selected_folder);
3000 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3003 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
3005 list = TNY_LIST (tny_simple_list_new ());
3006 tny_list_prepend (list, G_OBJECT (header));
3007 g_object_unref (header);
3010 g_return_val_if_reached (NULL);