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>
32 #include <modest-platform.h>
33 #include <modest-runtime.h>
34 #include <modest-main-window.h>
35 #include <modest-header-view.h>
36 #include "modest-hildon2-global-settings-dialog.h"
37 #include "modest-widget-memory.h"
38 #include <modest-hildon-includes.h>
39 #include <modest-maemo-utils.h>
40 #include <dbus_api/modest-dbus-callbacks.h>
41 #include <modest-osso-autosave-callbacks.h>
43 #include <tny-maemo-conic-device.h>
44 #include <tny-simple-list.h>
45 #include <tny-folder.h>
46 #include <gtk/gtkicontheme.h>
47 #include <gtk/gtkmenuitem.h>
48 #include <gtk/gtkmain.h>
49 #include <modest-text-utils.h>
50 #include "modest-tny-folder.h"
51 #include "modest-tny-account.h"
53 #include <libgnomevfs/gnome-vfs-mime-utils.h>
54 #include <modest-account-settings-dialog.h>
55 #include <modest-easysetup-wizard-dialog.h>
56 #include "modest-hildon2-sort-dialog.h"
57 #include <hildon/hildon-sound.h>
59 #include "hildon2/modest-hildon2-details-dialog.h"
60 #include "hildon2/modest-hildon2-window-mgr.h"
61 #include <keys_nokia.h>
62 #include <libprofile.h>
64 #include <modest-datetime-formatter.h>
65 #include "modest-header-window.h"
66 #include <modest-folder-window.h>
67 #include <modest-account-mgr.h>
68 #include <modest-account-mgr-helpers.h>
69 #include <modest-ui-constants.h>
70 #include <modest-selector-picker.h>
71 #include <modest-icon-names.h>
73 #ifdef MODEST_HAVE_MCE
74 #include <mce/dbus-names.h>
75 #endif /*MODEST_HAVE_MCE*/
77 #ifdef MODEST_HAVE_ABOOK
78 #include <libosso-abook/osso-abook.h>
79 #endif /*MODEST_HAVE_ABOOK*/
81 #ifdef MODEST_HAVE_LIBALARM
82 #include <alarmd/libalarm.h> /* For alarm_event_add(), etc. */
83 #endif /*MODEST_HAVE_LIBALARM*/
86 #define HILDON_OSSO_URI_ACTION "uri-action"
87 #define URI_ACTION_COPY "copy:"
88 #define MODEST_NEW_MAIL_LIGHTING_PATTERN "PatternCommunicationEmail"
89 #define PROFILE_MAIL_TONE PROFILEKEY_EMAIL_ALERT_TONE
90 #define PROFILE_MAIL_VOLUME PROFILEKEY_EMAIL_ALERT_VOLUME
92 #define COMMON_FOLDER_DIALOG_ENTRY "entry"
93 #define COMMON_FOLDER_DIALOG_ACCOUNT_PICKER "account-picker"
94 #define FOLDER_PICKER_CURRENT_FOLDER "current-folder"
97 static void _modest_platform_play_email_tone (void);
101 on_modest_conf_update_interval_changed (ModestConf* self,
103 ModestConfEvent event,
104 ModestConfNotificationId id,
107 g_return_if_fail (key);
109 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
110 const guint update_interval_minutes =
111 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
112 modest_platform_set_update_interval (update_interval_minutes);
119 check_required_files (void)
121 FILE *mcc_file = modest_maemo_open_mcc_mapping_file ();
123 g_printerr ("modest: check for mcc file failed\n");
128 if (access(MODEST_PROVIDER_DATA_FILE, R_OK) != 0 &&
129 access(MODEST_MAEMO_PROVIDER_DATA_FILE, R_OK) != 0) {
130 g_printerr ("modest: cannot find providers data\n");
138 /* the gpointer here is the osso_context. */
140 modest_platform_init (int argc, char *argv[])
142 osso_context_t *osso_context;
144 osso_hw_state_t hw_state = { 0 };
148 if (!check_required_files ()) {
149 g_printerr ("modest: missing required files\n");
153 osso_context = osso_initialize(PACKAGE,PACKAGE_VERSION,
156 g_printerr ("modest: failed to acquire osso context\n");
159 modest_maemo_utils_set_osso_context (osso_context);
161 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
162 g_printerr ("modest: could not get dbus connection\n");
166 /* Add a D-Bus handler to be used when the main osso-rpc
167 * D-Bus handler has not handled something.
168 * We use this for D-Bus methods that need to use more complex types
169 * than osso-rpc supports.
171 if (!dbus_connection_add_filter (con,
172 modest_dbus_req_filter,
176 g_printerr ("modest: Could not add D-Bus filter\n");
180 /* Register our simple D-Bus callbacks, via the osso API: */
181 osso_return_t result = osso_rpc_set_cb_f(osso_context,
185 modest_dbus_req_handler, NULL /* user_data */);
186 if (result != OSSO_OK) {
187 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
191 /* Register hardware event dbus callback: */
192 hw_state.shutdown_ind = TRUE;
193 osso_hw_set_event_cb(osso_context, NULL, NULL, NULL);
195 /* Register osso auto-save callbacks: */
196 result = osso_application_set_autosave_cb (osso_context,
197 modest_on_osso_application_autosave, NULL /* user_data */);
198 if (result != OSSO_OK) {
199 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
204 /* Make sure that the update interval is changed whenever its gconf key
206 /* CAUTION: we're not using here the
207 modest_conf_listen_to_namespace because we know that there
208 are other parts of Modest listening for this namespace, so
209 we'll receive the notifications anyway. We basically do not
210 use it because there is no easy way to do the
211 modest_conf_forget_namespace */
212 ModestConf *conf = modest_runtime_get_conf ();
213 g_signal_connect (G_OBJECT(conf),
215 G_CALLBACK (on_modest_conf_update_interval_changed),
218 /* only force the setting of the default interval, if there are actually
220 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
222 /* Get the initial update interval from gconf: */
223 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
224 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
225 modest_account_mgr_free_account_names (acc_names);
229 #ifdef MODEST_HAVE_ABOOK
230 /* initialize the addressbook */
231 if (!osso_abook_init (&argc, &argv, osso_context)) {
232 g_printerr ("modest: failed to initialized addressbook\n");
235 #endif /*MODEST_HAVE_ABOOK*/
241 modest_platform_uninit (void)
243 osso_context_t *osso_context =
244 modest_maemo_utils_get_osso_context ();
246 osso_deinitialize (osso_context);
255 modest_platform_get_new_device (void)
257 return TNY_DEVICE (tny_maemo_conic_device_new ());
261 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
262 gchar **effective_mime_type)
264 GString *mime_str = NULL;
265 gchar *icon_name = NULL;
266 gchar **icons, **cursor;
268 if (!mime_type || g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0)
269 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
271 mime_str = g_string_new (mime_type);
272 g_string_ascii_down (mime_str);
275 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
277 for (cursor = icons; cursor; ++cursor) {
278 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
279 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
280 icon_name = g_strdup ("qgn_list_messagin");
282 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
283 icon_name = g_strdup (*cursor);
289 if (effective_mime_type)
290 *effective_mime_type = g_string_free (mime_str, FALSE);
292 g_string_free (mime_str, TRUE);
299 checked_hildon_uri_open (const gchar *uri, HildonURIAction *action)
304 g_return_val_if_fail (uri, FALSE);
306 result = hildon_uri_open (uri, action, &err);
308 g_printerr ("modest: hildon_uri_open ('%s', %p) failed: %s",
309 uri, action, err && err->message ? err->message : "unknown error");
319 modest_platform_activate_uri (const gchar *uri)
321 HildonURIAction *action;
322 gboolean result = FALSE;
323 GSList *actions, *iter = NULL;
325 g_return_val_if_fail (uri, FALSE);
329 /* don't try to activate file: uri's -- they might confuse the user,
330 * and/or might have security implications */
331 if (!g_str_has_prefix (uri, "file:")) {
333 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
335 for (iter = actions; iter; iter = g_slist_next (iter)) {
336 action = (HildonURIAction*) iter->data;
337 if (action && strcmp (hildon_uri_action_get_service (action),
338 "com.nokia.modest") == 0) {
339 result = checked_hildon_uri_open (uri, action);
344 /* if we could not open it with email, try something else */
346 result = checked_hildon_uri_open (uri, NULL);
350 ModestWindow *parent =
351 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
352 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
353 _("mcen_ib_unsupported_link"));
354 g_warning ("%s: cannot open uri '%s'", __FUNCTION__,uri);
361 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
365 gchar *uri_path = NULL;
367 uri_path = gnome_vfs_get_uri_from_local_path (path);
368 con = osso_get_dbus_connection (modest_maemo_utils_get_osso_context());
371 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
373 result = hildon_mime_open_file (con, uri_path);
375 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"), FALSE);
383 } ModestPlatformPopupInfo;
386 delete_uri_popup (GtkWidget *menu,
390 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
392 g_free (popup_info->uri);
393 hildon_uri_free_actions (popup_info->actions);
399 activate_uri_popup_item (GtkMenuItem *menu_item,
403 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
404 const gchar* action_name;
406 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
408 g_printerr ("modest: no action name defined\n");
412 /* special handling for the copy menu item -- copy the uri to the clipboard */
413 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
414 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
415 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
416 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
418 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
419 action_name += strlen ("mailto:");
421 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
422 modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
423 return; /* we're done */
426 /* now, the real uri-actions... */
427 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
428 HildonURIAction *action = (HildonURIAction *) node->data;
429 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
430 if (!checked_hildon_uri_open (popup_info->uri, action)) {
431 ModestWindow *parent =
432 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
433 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
434 _("mcen_ib_unsupported_link"));
442 modest_platform_show_uri_popup (const gchar *uri)
444 GSList *actions_list;
449 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
452 GtkWidget *menu = gtk_menu_new ();
453 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
455 /* don't add actions for file: uri's -- they might confuse the user,
456 * and/or might have security implications
457 * we still allow to copy the url though
459 if (!g_str_has_prefix (uri, "file:")) {
462 popup_info->actions = actions_list;
463 popup_info->uri = g_strdup (uri);
465 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
466 GtkWidget *menu_item;
467 const gchar *action_name;
468 const gchar *translation_domain;
469 HildonURIAction *action = (HildonURIAction *) node->data;
470 action_name = hildon_uri_action_get_name (action);
471 translation_domain = hildon_uri_action_get_translation_domain (action);
472 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
473 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
474 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
477 if (hildon_uri_is_default_action (action, NULL)) {
478 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
480 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
482 gtk_widget_show (menu_item);
486 /* always add the copy item */
487 GtkWidget* menu_item = gtk_menu_item_new_with_label (dgettext("osso-uri",
488 "uri_link_copy_link_location"));
489 g_object_set_data_full (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION,
490 g_strconcat (URI_ACTION_COPY, uri, NULL),
492 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),NULL);
493 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
494 gtk_widget_show (menu_item);
497 /* and what to do when the link is deleted */
498 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
499 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
502 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
510 modest_platform_get_icon (const gchar *name, guint icon_size)
513 GdkPixbuf* pixbuf = NULL;
514 GtkIconTheme *current_theme = NULL;
516 g_return_val_if_fail (name, NULL);
518 /* strlen == 0 is not really an error; it just
519 * means the icon is not available
521 if (!name || strlen(name) == 0)
524 current_theme = gtk_icon_theme_get_default ();
525 pixbuf = gtk_icon_theme_load_icon (current_theme, name, icon_size,
526 GTK_ICON_LOOKUP_NO_SVG,
529 g_printerr ("modest: error loading theme icon '%s': %s\n",
537 modest_platform_get_app_name (void)
539 return _("mcen_ap_name");
543 entry_insert_text (GtkEditable *editable,
552 chars = gtk_editable_get_chars (editable, 0, -1);
553 chars_length = g_utf8_strlen (chars, -1);
556 /* Show WID-INF036 */
557 if (chars_length >= 20) {
558 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
559 _CS("ckdg_ib_maximum_characters_reached"));
561 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
565 tmp = g_strndup (folder_name_forbidden_chars,
566 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
567 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
568 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
573 /* Write the text in the entry if it's valid */
574 g_signal_handlers_block_by_func (editable,
575 (gpointer) entry_insert_text, data);
576 gtk_editable_insert_text (editable, text, length, position);
577 g_signal_handlers_unblock_by_func (editable,
578 (gpointer) entry_insert_text, data);
581 /* Do not allow further processing */
582 g_signal_stop_emission_by_name (editable, "insert_text");
586 entry_changed (GtkEditable *editable,
590 GtkWidget *ok_button;
593 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
594 ok_button = GTK_WIDGET (buttons->data);
596 chars = gtk_editable_get_chars (editable, 0, -1);
597 g_return_if_fail (chars != NULL);
600 if (g_utf8_strlen (chars,-1) >= 20)
601 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
602 _CS("ckdg_ib_maximum_characters_reached"));
604 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
607 g_list_free (buttons);
614 on_response (GtkDialog *dialog,
618 GtkWidget *entry, *picker;
619 TnyFolderStore *parent;
620 const gchar *new_name;
623 if (response != GTK_RESPONSE_ACCEPT)
627 entry = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY);
628 picker = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER);
630 parent = TNY_FOLDER_STORE (user_data);
631 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
634 if (picker != NULL) {
636 parent = g_object_get_data (G_OBJECT (picker), FOLDER_PICKER_CURRENT_FOLDER);
639 /* Look for another folder with the same name */
640 if (modest_tny_folder_has_subfolder_with_name (parent,
647 if (TNY_IS_ACCOUNT (parent) &&
648 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
649 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
658 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
659 NULL, _CS("ckdg_ib_folder_already_exists"));
660 /* Select the text */
661 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
662 gtk_widget_grab_focus (entry);
663 /* Do not close the dialog */
664 g_signal_stop_emission_by_name (dialog, "response");
669 typedef struct _FolderChooserData {
670 TnyFolderStore *store;
675 folder_chooser_activated (ModestFolderView *folder_view,
676 TnyFolderStore *folder,
677 FolderChooserData *userdata)
679 userdata->store = folder;
680 gtk_dialog_response (GTK_DIALOG (userdata->dialog), GTK_RESPONSE_OK);
683 static TnyFolderStore *
684 folder_chooser_dialog_run (ModestFolderView *original)
686 GtkWidget *folder_view;
687 FolderChooserData userdata = {NULL, NULL};
689 const gchar *visible_id = NULL;
691 userdata.dialog = hildon_dialog_new ();
692 pannable = hildon_pannable_area_new ();
693 folder_view = modest_platform_create_folder_view (NULL);
694 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
695 MODEST_FOLDER_VIEW_FILTER_CAN_HAVE_FOLDERS);
697 modest_folder_view_copy_model (MODEST_FOLDER_VIEW (original), MODEST_FOLDER_VIEW (folder_view));
700 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(original));
701 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view),
704 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (userdata.dialog)->vbox), pannable);
705 gtk_container_add (GTK_CONTAINER (pannable), folder_view);
706 gtk_widget_show (folder_view);
707 gtk_widget_show (pannable);
708 gtk_widget_show_all (userdata.dialog);
709 gtk_widget_set_size_request (pannable, -1, 320);
710 g_signal_connect (G_OBJECT (folder_view), "folder-activated",
711 G_CALLBACK (folder_chooser_activated),
712 (gpointer) &userdata);
714 gtk_dialog_run (GTK_DIALOG (userdata.dialog));
715 gtk_widget_destroy (userdata.dialog);
717 return userdata.store;
721 folder_store_get_display_name (TnyFolderStore *store)
723 if (TNY_IS_ACCOUNT (store)) {
724 return g_strdup (tny_account_get_name (TNY_ACCOUNT (store)));
727 TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
729 fname = g_strdup (tny_folder_get_name (TNY_FOLDER (store)));
730 type = tny_folder_get_folder_type (TNY_FOLDER (store));
731 if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)) ||
732 modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
733 type = modest_tny_folder_get_local_or_mmc_folder_type (TNY_FOLDER (store));
734 if (type != TNY_FOLDER_TYPE_UNKNOWN) {
736 fname = g_strdup (modest_local_folder_info_get_type_display_name (type));
739 /* Sometimes an special folder is reported by the server as
740 NORMAL, like some versions of Dovecot */
741 if (type == TNY_FOLDER_TYPE_NORMAL ||
742 type == TNY_FOLDER_TYPE_UNKNOWN) {
743 type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
747 if (type == TNY_FOLDER_TYPE_INBOX) {
749 fname = g_strdup (_("mcen_me_folder_inbox"));
756 folder_picker_set_store (GtkButton *button, TnyFolderStore *store)
761 g_object_set_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER, NULL);
763 g_object_ref (store);
764 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
765 store, (GDestroyNotify) g_object_unref);
766 name = folder_store_get_display_name (store);
767 hildon_button_set_value (HILDON_BUTTON (button), name);
773 folder_picker_clicked (GtkButton *button,
774 ModestFolderView *folder_view)
776 TnyFolderStore *store;
778 store = folder_chooser_dialog_run (folder_view);
780 folder_picker_set_store (GTK_BUTTON (button), store);
785 folder_picker_new (ModestFolderView *folder_view, TnyFolderStore *suggested)
790 button = hildon_button_new (MODEST_EDITABLE_SIZE,
791 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
792 pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_NORMAL,
793 MODEST_ICON_SIZE_SMALL);
795 hildon_button_set_image (HILDON_BUTTON (button),
796 gtk_image_new_from_pixbuf (pixbuf));
797 hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 1.0);
800 folder_picker_set_store (GTK_BUTTON (button), suggested);
803 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (folder_picker_clicked), folder_view);
810 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
811 TnyFolderStore *suggested_parent,
812 const gchar *dialog_title,
813 const gchar *label_text,
814 const gchar *suggested_name,
816 gboolean show_parent,
818 TnyFolderStore **parent)
820 GtkWidget *accept_btn = NULL;
821 GtkWidget *dialog, *entry, *label_entry, *label_location, *hbox;
822 GtkWidget *account_picker;
823 GList *buttons = NULL;
825 GtkSizeGroup *sizegroup;
826 ModestFolderView *folder_view;
828 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (parent_window), GTK_RESPONSE_NONE);
830 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window));
832 /* Ask the user for the folder name */
833 dialog = gtk_dialog_new_with_buttons (dialog_title,
835 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
836 _FM("ckdg_bd_new_folder_dialog_ok"),
840 /* Add accept button (with unsensitive handler) */
841 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
842 accept_btn = GTK_WIDGET (buttons->data);
844 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
847 label_entry = gtk_label_new (label_text);
848 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
849 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
851 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
852 gtk_size_group_add_widget (sizegroup, label_entry);
855 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
857 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
858 gtk_entry_set_width_chars (GTK_ENTRY (entry),
859 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
860 g_utf8_strlen (_("mcen_ia_default_folder_name"), -1)));
861 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
866 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
868 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
869 gtk_size_group_add_widget (sizegroup, label_location);
871 account_picker = folder_picker_new (folder_view, suggested_parent);
874 g_object_unref (sizegroup);
876 /* Connect to the response method to avoid closing the dialog
877 when an invalid name is selected*/
878 g_signal_connect (dialog,
880 G_CALLBACK (on_response),
884 /* Track entry changes */
885 g_signal_connect (entry,
887 G_CALLBACK (entry_insert_text),
889 g_signal_connect (entry,
891 G_CALLBACK (entry_changed),
896 /* Some locales like pt_BR need this to get the full window
898 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
900 /* Create the hbox */
902 hbox = gtk_hbox_new (FALSE, 12);
903 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
904 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
906 /* Add hbox to dialog */
907 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
908 hbox, FALSE, FALSE, 0);
909 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
913 hbox = gtk_hbox_new (FALSE, 12);
914 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
915 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
917 /* Add hbox to dialog */
918 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
919 hbox, FALSE, FALSE, 0);
920 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
922 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
923 GTK_WINDOW (dialog), parent_window);
924 gtk_widget_show_all (GTK_WIDGET(dialog));
926 result = gtk_dialog_run (GTK_DIALOG(dialog));
927 if (result == GTK_RESPONSE_ACCEPT) {
929 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
931 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
933 g_object_ref (*parent);
937 gtk_widget_destroy (dialog);
939 while (gtk_events_pending ())
940 gtk_main_iteration ();
946 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
947 TnyFolderStore *suggested_folder,
948 gchar *suggested_name,
950 TnyFolderStore **parent_folder)
952 gchar *real_suggested_name = NULL, *tmp = NULL;
955 if(suggested_name == NULL)
957 const gchar *default_name = _("mcen_ia_default_folder_name");
961 for(i = 0; i < 100; ++ i) {
962 gboolean exists = FALSE;
964 sprintf(num_str, "%.2u", i);
967 real_suggested_name = g_strdup (default_name);
969 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
971 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
978 g_free (real_suggested_name);
981 /* Didn't find a free number */
983 real_suggested_name = g_strdup (default_name);
985 real_suggested_name = suggested_name;
988 /* In hildon 2.2 we always suggest the archive folder as parent */
989 suggested_folder = TNY_FOLDER_STORE (
990 modest_tny_account_get_special_folder
991 (modest_tny_account_store_get_local_folders_account (modest_runtime_get_account_store ()),
992 TNY_FOLDER_TYPE_ARCHIVE));
994 tmp = g_strconcat (_("mcen_fi_new_folder_name"), ":", NULL);
995 result = modest_platform_run_folder_common_dialog (parent_window,
997 _("mcen_ti_new_folder"),
1006 if (suggested_name == NULL)
1007 g_free(real_suggested_name);
1013 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1014 TnyFolderStore *parent_folder,
1015 const gchar *suggested_name,
1016 gchar **folder_name)
1018 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1020 return modest_platform_run_folder_common_dialog (parent_window,
1022 _HL("ckdg_ti_rename_folder"),
1023 _HL("ckdg_fi_rename_name"),
1034 on_destroy_dialog (GtkWidget *dialog)
1036 /* This could happen when the dialogs get programatically
1037 hidden or destroyed (for example when closing the
1038 application while a dialog is being shown) */
1039 if (!GTK_IS_WIDGET (dialog))
1042 gtk_widget_destroy (dialog);
1044 if (gtk_events_pending ())
1045 gtk_main_iteration ();
1049 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1050 const gchar *message)
1055 dialog = hildon_note_new_confirmation (parent_window, message);
1056 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1057 GTK_WINDOW (dialog), parent_window);
1059 response = gtk_dialog_run (GTK_DIALOG (dialog));
1061 on_destroy_dialog (dialog);
1067 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1068 const gchar *message,
1069 const gchar *button_accept,
1070 const gchar *button_cancel)
1075 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1076 button_accept, GTK_RESPONSE_ACCEPT,
1077 button_cancel, GTK_RESPONSE_CANCEL,
1080 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1081 GTK_WINDOW (dialog), parent_window);
1083 response = gtk_dialog_run (GTK_DIALOG (dialog));
1085 on_destroy_dialog (dialog);
1091 modest_platform_run_information_dialog (GtkWindow *parent_window,
1092 const gchar *message,
1097 note = hildon_note_new_information (parent_window, message);
1099 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1100 GTK_WINDOW (note), parent_window);
1103 gtk_dialog_run (GTK_DIALOG (note));
1105 on_destroy_dialog (note);
1107 g_signal_connect_swapped (note,
1109 G_CALLBACK (on_destroy_dialog),
1112 gtk_widget_show_all (note);
1116 typedef struct _ConnectAndWaitData {
1118 GMainLoop *wait_loop;
1119 gboolean has_callback;
1121 } ConnectAndWaitData;
1125 quit_wait_loop (TnyAccount *account,
1126 ConnectAndWaitData *data)
1128 /* Set the has_callback to TRUE (means that the callback was
1129 executed and wake up every code waiting for cond to be
1131 g_mutex_lock (data->mutex);
1132 data->has_callback = TRUE;
1133 if (data->wait_loop)
1134 g_main_loop_quit (data->wait_loop);
1135 g_mutex_unlock (data->mutex);
1139 on_connection_status_changed (TnyAccount *account,
1140 TnyConnectionStatus status,
1143 TnyConnectionStatus conn_status;
1144 ConnectAndWaitData *data;
1146 /* Ignore if reconnecting or disconnected */
1147 conn_status = tny_account_get_connection_status (account);
1148 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1149 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1152 /* Remove the handler */
1153 data = (ConnectAndWaitData *) user_data;
1154 g_signal_handler_disconnect (account, data->handler);
1156 /* Quit from wait loop */
1157 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1161 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1166 /* Quit from wait loop */
1167 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1171 modest_platform_connect_and_wait (GtkWindow *parent_window,
1172 TnyAccount *account)
1174 ConnectAndWaitData *data = NULL;
1175 gboolean device_online;
1177 TnyConnectionStatus conn_status;
1178 gboolean user_requested;
1180 device = modest_runtime_get_device();
1181 device_online = tny_device_is_online (device);
1183 /* Whether the connection is user requested or automatically
1184 requested, for example via D-Bus */
1185 user_requested = (parent_window) ? TRUE : FALSE;
1187 /* If there is no account check only the device status */
1192 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1193 NULL, user_requested);
1196 /* Return if the account is already connected */
1197 conn_status = tny_account_get_connection_status (account);
1198 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1201 /* Create the helper */
1202 data = g_slice_new0 (ConnectAndWaitData);
1203 data->mutex = g_mutex_new ();
1204 data->has_callback = FALSE;
1206 /* Connect the device */
1207 if (!device_online) {
1208 /* Track account connection status changes */
1209 data->handler = g_signal_connect (account, "connection-status-changed",
1210 G_CALLBACK (on_connection_status_changed),
1212 /* Try to connect the device */
1213 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1214 NULL, user_requested);
1216 /* If the device connection failed then exit */
1217 if (!device_online && data->handler)
1220 /* Force a reconnection of the account */
1221 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1222 on_tny_camel_account_set_online_cb, data);
1225 /* Wait until the callback is executed */
1226 g_mutex_lock (data->mutex);
1227 if (!data->has_callback) {
1228 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1229 gdk_threads_leave ();
1230 g_mutex_unlock (data->mutex);
1231 g_main_loop_run (data->wait_loop);
1232 g_mutex_lock (data->mutex);
1233 gdk_threads_enter ();
1235 g_mutex_unlock (data->mutex);
1239 if (g_signal_handler_is_connected (account, data->handler))
1240 g_signal_handler_disconnect (account, data->handler);
1241 g_mutex_free (data->mutex);
1242 g_main_loop_unref (data->wait_loop);
1243 g_slice_free (ConnectAndWaitData, data);
1246 conn_status = tny_account_get_connection_status (account);
1247 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1251 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1253 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1254 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1255 /* This must be a maildir account, which does not require a connection: */
1260 return modest_platform_connect_and_wait (parent_window, account);
1264 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1267 return TRUE; /* Maybe it is something local. */
1269 gboolean result = TRUE;
1270 if (TNY_IS_FOLDER (folder_store)) {
1271 /* Get the folder's parent account: */
1272 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1273 if (account != NULL) {
1274 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1275 g_object_unref (account);
1277 } else if (TNY_IS_ACCOUNT (folder_store)) {
1278 /* Use the folder store as an account: */
1279 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1286 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1290 dialog = modest_hildon2_sort_dialog_new (parent_window);
1297 modest_platform_set_update_interval (guint minutes)
1299 #ifdef MODEST_HAVE_LIBALARM
1301 ModestConf *conf = modest_runtime_get_conf ();
1305 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1307 /* Delete any existing alarm,
1308 * because we will replace it: */
1310 if (alarmd_event_del(alarm_cookie) != 1)
1311 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1313 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1316 /* 0 means no updates: */
1321 /* Register alarm: */
1323 /* Set the interval in alarm_event_t structure: */
1324 alarm_event_t *event = alarm_event_create ();
1325 alarm_event_add_actions (event, 1);
1326 alarm_action_t *action = alarm_event_get_action (event, 0);
1327 event->alarm_time = minutes * 60; /* seconds */
1329 /* Set recurrence every few minutes: */
1330 event->recur_secs = minutes*60;
1331 event->recur_count = -1; /* Means infinite */
1333 /* Specify what should happen when the alarm happens:
1334 * It should call this D-Bus method: */
1336 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1337 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1338 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1339 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1340 action->flags = ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1342 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1343 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1344 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1345 * This is why we want to use the Alarm API instead of just g_timeout_add().
1346 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1347 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1349 event->flags = ALARM_EVENT_CONNECTED;
1351 alarm_cookie = alarmd_event_add (event);
1354 alarm_event_delete (event);
1356 /* Store the alarm ID in GConf, so we can remove it later:
1357 * This is apparently valid between application instances. */
1358 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1360 if (!alarm_cookie) {
1362 g_debug ("Error setting alarm event. \n");
1366 #endif /* MODEST_HAVE_LIBALARM */
1371 modest_platform_push_email_notification(void)
1373 gboolean screen_on = TRUE, app_in_foreground;
1375 /* Get the window status */
1376 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1378 /* If the screen is on and the app is in the
1379 foreground we don't show anything */
1380 if (!(screen_on && app_in_foreground)) {
1382 _modest_platform_play_email_tone ();
1384 /* Activate LED. This must be deactivated by
1385 modest_platform_remove_new_mail_notifications */
1386 #ifdef MODEST_HAVE_MCE
1387 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1391 MCE_ACTIVATE_LED_PATTERN,
1393 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1400 modest_platform_on_new_headers_received (TnyList *header_list,
1401 gboolean show_visual)
1403 g_return_if_fail (TNY_IS_LIST(header_list));
1405 if (tny_list_get_length(header_list) == 0) {
1406 g_warning ("%s: header list is empty", __FUNCTION__);
1411 modest_platform_push_email_notification ();
1412 /* We do a return here to avoid indentation with an else */
1416 #ifdef MODEST_HAVE_HILDON_NOTIFY
1417 HildonNotification *notification;
1419 GSList *notifications_list = NULL;
1421 /* Get previous notifications ids */
1422 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1423 MODEST_CONF_NOTIFICATION_IDS,
1424 MODEST_CONF_VALUE_INT, NULL);
1426 iter = tny_list_create_iterator (header_list);
1427 while (!tny_iterator_is_done (iter)) {
1428 gchar *url = NULL, *display_address = NULL, *summary = NULL;
1429 const gchar *display_date;
1430 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1431 TnyFolder *folder = tny_header_get_folder (header);
1432 gboolean first_notification = TRUE;
1435 ModestDatetimeFormatter *datetime_formatter;
1437 /* constant string, don't free */
1438 datetime_formatter = modest_datetime_formatter_new ();
1439 display_date = modest_datetime_formatter_display_datetime (datetime_formatter,
1440 tny_header_get_date_received (header));
1441 g_object_unref (datetime_formatter);
1443 display_address = tny_header_dup_from (header);
1444 /* string is changed in-place */
1445 modest_text_utils_get_display_address (display_address);
1447 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1448 str = tny_header_dup_subject (header);
1449 notification = hildon_notification_new (summary,
1451 "qgn_list_messagin",
1454 /* Create the message URL */
1455 str = tny_header_dup_uid (header);
1456 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1460 hildon_notification_add_dbus_action(notification,
1463 MODEST_DBUS_SERVICE,
1466 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1470 /* Play sound if the user wants. Show the LED
1471 pattern. Show and play just one */
1472 if (G_UNLIKELY (first_notification)) {
1473 gchar *active_profile;
1476 gint mail_volume_int;
1478 first_notification = FALSE;
1480 active_profile = profile_get_profile ();
1481 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
1482 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
1483 mail_volume_int = profile_parse_int (mail_volume);
1485 if (mail_volume_int > 0)
1486 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1487 "sound-file", mail_tone);
1489 g_free (mail_volume);
1491 g_free (active_profile);
1493 /* Set the led pattern */
1494 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1496 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1498 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1501 /* Notify. We need to do this in an idle because this function
1502 could be called from a thread */
1503 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1505 /* Save id in the list */
1506 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1507 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1508 /* We don't listen for the "closed" signal, because we
1509 don't care about if the notification was removed or
1510 not to store the list in gconf */
1512 /* Free & carry on */
1513 g_free (display_address);
1516 g_object_unref (folder);
1517 g_object_unref (header);
1518 tny_iterator_next (iter);
1520 g_object_unref (iter);
1523 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1524 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1526 g_slist_free (notifications_list);
1528 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1532 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1535 #ifdef MODEST_HAVE_MCE
1536 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1540 MCE_DEACTIVATE_LED_PATTERN,
1542 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1548 #ifdef MODEST_HAVE_HILDON_NOTIFY
1549 GSList *notif_list = NULL;
1551 /* Get previous notifications ids */
1552 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1553 MODEST_CONF_NOTIFICATION_IDS,
1554 MODEST_CONF_VALUE_INT, NULL);
1556 while (notif_list) {
1558 NotifyNotification *notif;
1560 /* Nasty HACK to remove the notifications, set the id
1561 of the existing ones and then close them */
1562 notif_id = GPOINTER_TO_INT(notif_list->data);
1563 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1564 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1566 /* Close the notification, note that some ids could be
1567 already invalid, but we don't care because it does
1569 notify_notification_close(notif, NULL);
1570 g_object_unref(notif);
1572 /* Delete the link, it's like going to the next */
1573 notif_list = g_slist_delete_link (notif_list, notif_list);
1577 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1578 notif_list, MODEST_CONF_VALUE_INT, NULL);
1580 g_slist_free (notif_list);
1582 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1588 modest_platform_get_global_settings_dialog ()
1590 return modest_hildon2_global_settings_dialog_new ();
1594 modest_platform_show_help (GtkWindow *parent_window,
1595 const gchar *help_id)
1601 modest_platform_show_search_messages (GtkWindow *parent_window)
1603 osso_return_t result = OSSO_ERROR;
1605 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1606 "osso_global_search",
1607 "search_email", NULL, DBUS_TYPE_INVALID);
1609 if (result != OSSO_OK) {
1610 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1615 modest_platform_show_addressbook (GtkWindow *parent_window)
1617 osso_return_t result = OSSO_ERROR;
1619 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1621 "top_application", NULL, DBUS_TYPE_INVALID);
1623 if (result != OSSO_OK) {
1624 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1629 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1631 GtkWidget *widget = modest_folder_view_new (query);
1633 /* Show one account by default */
1634 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1635 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1637 /* Restore settings */
1638 modest_widget_memory_restore (modest_runtime_get_conf(),
1640 MODEST_CONF_FOLDER_VIEW_KEY);
1646 banner_finish (gpointer data, GObject *object)
1648 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1649 modest_window_mgr_unregister_banner (mgr);
1650 g_object_unref (mgr);
1654 modest_platform_information_banner (GtkWidget *parent,
1655 const gchar *icon_name,
1658 GtkWidget *banner, *banner_parent = NULL;
1659 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1661 if (modest_window_mgr_get_num_windows (mgr) == 0)
1664 if (parent && GTK_IS_WINDOW (parent)) {
1665 /* If the window is the active one then show the
1666 banner on top of this window */
1667 if (gtk_window_is_active (GTK_WINDOW (parent)))
1668 banner_parent = parent;
1669 /* If the window is not the topmost but it's visible
1670 (it's minimized for example) then show the banner
1672 else if (GTK_WIDGET_VISIBLE (parent))
1673 banner_parent = NULL;
1674 /* If the window is hidden (like the main window when
1675 running in the background) then do not show
1682 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1684 modest_window_mgr_register_banner (mgr);
1686 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1690 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1691 const gchar *icon_name,
1697 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1700 banner = hildon_banner_show_information (parent, icon_name, text);
1701 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1705 modest_platform_animation_banner (GtkWidget *parent,
1706 const gchar *animation_name,
1709 GtkWidget *inf_note = NULL;
1711 g_return_val_if_fail (text != NULL, NULL);
1713 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1716 /* If the parent is not visible then do not show */
1717 if (parent && !GTK_WIDGET_VISIBLE (parent))
1720 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1728 TnyAccount *account;
1731 } CheckAccountIdleData;
1733 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1736 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1738 gboolean stop_trying = FALSE;
1739 g_return_val_if_fail (data && data->account, FALSE);
1741 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1742 tny_account_get_connection_status (data->account));
1744 if (data && data->account &&
1745 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1746 * after which the account is likely to be usable, or never likely to be usable soon: */
1747 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1749 data->is_online = TRUE;
1753 /* Give up if we have tried too many times: */
1754 if (data->count_tries >= NUMBER_OF_TRIES) {
1757 /* Wait for another timeout: */
1758 ++(data->count_tries);
1763 /* Allow the function that requested this idle callback to continue: */
1765 g_main_loop_quit (data->loop);
1768 g_object_unref (data->account);
1770 return FALSE; /* Don't call this again. */
1772 return TRUE; /* Call this timeout callback again. */
1776 /* Return TRUE immediately if the account is already online,
1777 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1778 * soon as the account is online, or FALSE if the account does
1779 * not become online in the NUMBER_OF_TRIES seconds.
1780 * This is useful when the D-Bus method was run immediately after
1781 * the application was started (when using D-Bus activation),
1782 * because the account usually takes a short time to go online.
1783 * The return value is maybe not very useful.
1786 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1790 g_return_val_if_fail (account, FALSE);
1792 if (!tny_device_is_online (modest_runtime_get_device())) {
1793 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1797 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1798 * so we avoid wait unnecessarily: */
1799 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1802 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1803 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1804 * we want to avoid. */
1805 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1808 /* This blocks on the result: */
1809 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1810 data->is_online = FALSE;
1811 data->account = account;
1812 g_object_ref (data->account);
1813 data->count_tries = 0;
1815 GMainContext *context = NULL; /* g_main_context_new (); */
1816 data->loop = g_main_loop_new (context, FALSE /* not running */);
1818 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1820 /* This main loop will run until the idle handler has stopped it: */
1821 g_main_loop_run (data->loop);
1823 g_main_loop_unref (data->loop);
1824 /* g_main_context_unref (context); */
1826 is_online = data->is_online;
1827 g_slice_free (CheckAccountIdleData, data);
1835 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1837 /* GTK_RESPONSE_HELP means we need to show the certificate */
1838 if (response_id == GTK_RESPONSE_APPLY) {
1842 /* Do not close the dialog */
1843 g_signal_stop_emission_by_name (dialog, "response");
1845 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1846 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1847 gtk_dialog_run (GTK_DIALOG(note));
1848 gtk_widget_destroy (note);
1854 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1855 const gchar *certificate)
1860 HildonWindowStack *stack;
1862 stack = hildon_window_stack_get_default ();
1863 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1866 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1871 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1874 /* We use GTK_RESPONSE_APPLY because we want the button in the
1875 middle of OK and CANCEL the same as the browser does for
1876 example. With GTK_RESPONSE_HELP the view button is aligned
1877 to the left while the other two to the right */
1878 note = hildon_note_new_confirmation_add_buttons (
1881 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1882 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1883 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1886 g_signal_connect (G_OBJECT(note), "response",
1887 G_CALLBACK(on_cert_dialog_response),
1888 (gpointer) certificate);
1890 response = gtk_dialog_run(GTK_DIALOG(note));
1892 on_destroy_dialog (note);
1895 return response == GTK_RESPONSE_OK;
1899 modest_platform_run_alert_dialog (const gchar* prompt,
1900 gboolean is_question)
1902 ModestWindow *top_win;
1903 HildonWindowStack *stack;
1905 stack = hildon_window_stack_get_default ();
1906 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1909 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1914 gboolean retval = TRUE;
1916 /* The Tinymail documentation says that we should show Yes and No buttons,
1917 * when it is a question.
1918 * Obviously, we need tinymail to use more specific error codes instead,
1919 * so we know what buttons to show. */
1920 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
1922 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1923 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
1925 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1926 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1928 on_destroy_dialog (dialog);
1930 /* Just show the error text and use the default response: */
1931 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
1939 GtkWindow *parent_window;
1940 ModestConnectedPerformer callback;
1941 TnyAccount *account;
1948 on_went_online_info_free (OnWentOnlineInfo *info)
1950 /* And if we cleanup, we DO cleanup :-) */
1953 g_object_unref (info->device);
1956 if (info->parent_window)
1957 g_object_unref (info->parent_window);
1959 g_object_unref (info->account);
1961 g_slice_free (OnWentOnlineInfo, info);
1963 /* We're done ... */
1969 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
1971 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1973 /* Now it's really time to callback to the caller. If going online didn't succeed,
1974 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
1975 * canceled will be set. Etcetera etcetera. */
1977 if (info->callback) {
1978 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
1981 /* This is our last call, we must cleanup here if we didn't yet do that */
1982 on_went_online_info_free (info);
1989 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
1991 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1992 info->iap = g_strdup (iap_id);
1994 if (canceled || err || !info->account) {
1996 /* If there's a problem or if there's no account (then that's it for us, we callback
1997 * the caller's callback now. He'll have to handle err or canceled, of course.
1998 * We are not really online, as the account is not really online here ... */
2000 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2001 * this info. We don't cleanup err, Tinymail does that! */
2003 if (info->callback) {
2005 /* info->account can be NULL here, this means that the user did not
2006 * provide a nice account instance. We'll assume that the user knows
2007 * what he's doing and is happy with just the device going online.
2009 * We can't do magic, we don't know what account the user wants to
2010 * see going online. So just the device goes online, end of story */
2012 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2015 } else if (info->account) {
2017 /* If there's no problem and if we have an account, we'll put the account
2018 * online too. When done, the callback of bringing the account online
2019 * will callback the caller's callback. This is the most normal case. */
2021 info->device = TNY_DEVICE (g_object_ref (device));
2023 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2024 on_account_went_online, info);
2026 /* The on_account_went_online cb frees up the info, go look if you
2027 * don't believe me! (so we return here) */
2032 /* We cleanup if we are not bringing the account online too */
2033 on_went_online_info_free (info);
2039 modest_platform_connect_and_perform (GtkWindow *parent_window,
2041 TnyAccount *account,
2042 ModestConnectedPerformer callback,
2045 gboolean device_online;
2047 TnyConnectionStatus conn_status;
2048 OnWentOnlineInfo *info;
2050 device = modest_runtime_get_device();
2051 device_online = tny_device_is_online (device);
2053 /* If there is no account check only the device status */
2056 if (device_online) {
2058 /* We promise to instantly perform the callback, so ... */
2060 callback (FALSE, NULL, parent_window, account, user_data);
2065 info = g_slice_new0 (OnWentOnlineInfo);
2068 info->device = NULL;
2069 info->account = NULL;
2072 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2074 info->parent_window = NULL;
2075 info->user_data = user_data;
2076 info->callback = callback;
2078 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2079 force, on_conic_device_went_online,
2082 /* We'll cleanup in on_conic_device_went_online */
2085 /* The other code has no more reason to run. This is all that we can do for the
2086 * caller (he should have given us a nice and clean account instance!). We
2087 * can't do magic, we don't know what account he intends to bring online. So
2088 * we'll just bring the device online (and await his false bug report). */
2094 /* Return if the account is already connected */
2096 conn_status = tny_account_get_connection_status (account);
2097 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2099 /* We promise to instantly perform the callback, so ... */
2101 callback (FALSE, NULL, parent_window, account, user_data);
2107 /* Else, we are in a state that requires that we go online before we
2108 * call the caller's callback. */
2110 info = g_slice_new0 (OnWentOnlineInfo);
2112 info->device = NULL;
2114 info->account = TNY_ACCOUNT (g_object_ref (account));
2117 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2119 info->parent_window = NULL;
2121 /* So we'll put the callback away for later ... */
2123 info->user_data = user_data;
2124 info->callback = callback;
2126 if (!device_online) {
2128 /* If also the device is offline, then we connect both the device
2129 * and the account */
2131 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2132 force, on_conic_device_went_online,
2137 /* If the device is online, we'll just connect the account */
2139 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2140 on_account_went_online, info);
2143 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2144 * in both situations, go look if you don't believe me! */
2150 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2152 TnyFolderStore *folder_store,
2153 ModestConnectedPerformer callback,
2156 TnyAccount *account = NULL;
2158 if (!folder_store) {
2159 /* We promise to instantly perform the callback, so ... */
2161 callback (FALSE, NULL, parent_window, NULL, user_data);
2165 } else if (TNY_IS_FOLDER (folder_store)) {
2166 /* Get the folder's parent account: */
2167 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2168 } else if (TNY_IS_ACCOUNT (folder_store)) {
2169 /* Use the folder store as an account: */
2170 account = TNY_ACCOUNT (g_object_ref (folder_store));
2173 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
2174 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2175 /* No need to connect a local account */
2177 callback (FALSE, NULL, parent_window, account, user_data);
2182 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2186 g_object_unref (account);
2190 src_account_connect_performer (gboolean canceled,
2192 GtkWindow *parent_window,
2193 TnyAccount *src_account,
2196 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2198 if (canceled || err) {
2199 /* If there was any error call the user callback */
2200 info->callback (canceled, err, parent_window, src_account, info->data);
2202 /* Connect the destination account */
2203 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2204 TNY_FOLDER_STORE (info->dst_account),
2205 info->callback, info->data);
2208 /* Free the info object */
2209 g_object_unref (info->dst_account);
2210 g_slice_free (DoubleConnectionInfo, info);
2215 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2217 TnyFolderStore *folder_store,
2218 DoubleConnectionInfo *connect_info)
2220 modest_platform_connect_if_remote_and_perform(parent_window,
2223 src_account_connect_performer,
2228 modest_platform_get_account_settings_wizard (void)
2230 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2232 return GTK_WIDGET (dialog);
2236 modest_platform_get_current_connection (void)
2238 TnyDevice *device = NULL;
2239 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2241 device = modest_runtime_get_device ();
2243 if (!tny_device_is_online (device))
2244 return MODEST_CONNECTED_VIA_ANY;
2246 #ifdef MODEST_HAVE_CONIC
2248 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2250 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2251 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2252 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2254 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2255 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2256 !strcmp (bearer_type, "WIMAX")) {
2257 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2259 retval = MODEST_CONNECTED_VIA_ANY;
2262 g_object_unref (iap);
2265 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2266 #endif /* MODEST_HAVE_CONIC */
2273 modest_platform_check_memory_low (ModestWindow *win,
2278 /* are we in low memory state? */
2279 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2281 if (win && lowmem && visuals)
2282 modest_platform_run_information_dialog (
2284 dgettext("ke-recv","memr_ib_operation_disabled"),
2288 g_debug ("%s: low memory reached. disallowing some operations",
2295 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2301 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2304 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2305 GTK_WINDOW (dialog),
2307 gtk_widget_show_all (dialog);
2309 g_signal_connect_swapped (dialog, "response",
2310 G_CALLBACK (gtk_widget_destroy),
2315 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2321 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2324 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2325 GTK_WINDOW (dialog),
2327 gtk_widget_show_all (dialog);
2329 g_signal_connect_swapped (dialog, "response",
2330 G_CALLBACK (gtk_widget_destroy),
2335 modest_platform_get_osso_context (void)
2337 return modest_maemo_utils_get_osso_context ();
2341 _modest_platform_play_email_tone (void)
2343 gchar *active_profile;
2346 gint mail_volume_int;
2348 ca_context *ca_con = NULL;
2349 ca_proplist *pl = NULL;
2351 active_profile = profile_get_profile ();
2352 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2353 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2354 mail_volume_int = profile_parse_int (mail_volume);
2356 if (mail_volume_int > 0) {
2358 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2359 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2363 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2364 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2365 ca_context_destroy(ca_con);
2369 ca_proplist_create(&pl);
2370 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2371 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2373 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2374 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2376 ca_proplist_destroy(pl);
2377 ca_context_destroy(ca_con);
2380 g_free (mail_volume);
2382 g_free (active_profile);
2386 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2388 GtkTreeViewColumn *column,
2391 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_OK);
2395 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2396 GtkWidget **folder_view)
2398 GtkWidget *dialog, *folder_view_container;
2400 /* Create dialog. We cannot use a touch selector because we
2401 need to use here the folder view widget directly */
2402 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2403 GTK_WINDOW (parent_window),
2404 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2405 GTK_DIALOG_DESTROY_WITH_PARENT,
2406 _("mcen_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2409 /* Create folder view */
2410 *folder_view = modest_platform_create_folder_view (NULL);
2412 /* Simulate the behaviour of a HildonPickerDialog by emitting
2413 a response when a folder is selected */
2414 g_signal_connect (*folder_view, "row-activated",
2415 G_CALLBACK (on_move_to_dialog_folder_activated),
2418 /* Create pannable and add it to the dialog */
2419 folder_view_container = hildon_pannable_area_new ();
2420 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), folder_view_container);
2421 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2423 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2425 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2426 gtk_widget_show (folder_view_container);
2427 gtk_widget_show (*folder_view);
2433 modest_platform_get_list_to_move (ModestWindow *window)
2435 if (MODEST_IS_HEADER_WINDOW (window)) {
2436 ModestHeaderView *header_view;
2438 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2440 return modest_header_view_get_selected_headers (header_view);
2441 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2442 ModestFolderView *folder_view;
2443 TnyFolderStore *selected_folder;
2446 list = TNY_LIST (tny_simple_list_new ());
2447 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2448 selected_folder = modest_folder_view_get_selected (folder_view);
2449 if (selected_folder) {
2450 tny_list_prepend (list, G_OBJECT (selected_folder));
2451 g_object_unref (selected_folder);