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 = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
822 GtkWidget *account_picker = NULL;
823 GList *buttons = NULL;
825 GtkSizeGroup *sizegroup;
826 ModestFolderView *folder_view;
827 ModestWindow *folder_window;
828 ModestHildon2WindowMgr *window_mgr;
830 window_mgr = (ModestHildon2WindowMgr *) modest_runtime_get_window_mgr ();
831 folder_window = modest_hildon2_window_mgr_get_folder_window (window_mgr);
832 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
834 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
836 /* Ask the user for the folder name */
837 dialog = gtk_dialog_new_with_buttons (dialog_title,
839 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
840 _FM("ckdg_bd_new_folder_dialog_ok"),
844 /* Add accept button (with unsensitive handler) */
845 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
846 accept_btn = GTK_WIDGET (buttons->data);
848 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
851 label_entry = gtk_label_new (label_text);
852 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
853 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
855 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
856 gtk_size_group_add_widget (sizegroup, label_entry);
859 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
861 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
862 gtk_entry_set_width_chars (GTK_ENTRY (entry),
863 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
864 g_utf8_strlen (_("mcen_ia_default_folder_name"), -1)));
865 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
870 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
872 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
873 gtk_size_group_add_widget (sizegroup, label_location);
875 account_picker = folder_picker_new (folder_view, suggested_parent);
878 g_object_unref (sizegroup);
880 /* Connect to the response method to avoid closing the dialog
881 when an invalid name is selected*/
882 g_signal_connect (dialog,
884 G_CALLBACK (on_response),
888 /* Track entry changes */
889 g_signal_connect (entry,
891 G_CALLBACK (entry_insert_text),
893 g_signal_connect (entry,
895 G_CALLBACK (entry_changed),
900 /* Some locales like pt_BR need this to get the full window
902 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
904 /* Create the hbox */
906 hbox = gtk_hbox_new (FALSE, 12);
907 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
908 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
910 /* Add hbox to dialog */
911 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
912 hbox, FALSE, FALSE, 0);
913 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
917 hbox = gtk_hbox_new (FALSE, 12);
918 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
919 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
921 /* Add hbox to dialog */
922 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
923 hbox, FALSE, FALSE, 0);
924 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
926 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
927 GTK_WINDOW (dialog), parent_window);
928 gtk_widget_show_all (GTK_WIDGET(dialog));
930 result = gtk_dialog_run (GTK_DIALOG(dialog));
931 if (result == GTK_RESPONSE_ACCEPT) {
933 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
935 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
937 g_object_ref (*parent);
941 gtk_widget_destroy (dialog);
943 while (gtk_events_pending ())
944 gtk_main_iteration ();
950 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
951 TnyFolderStore *suggested_folder,
952 gchar *suggested_name,
954 TnyFolderStore **parent_folder)
956 gchar *real_suggested_name = NULL, *tmp = NULL;
959 if(suggested_name == NULL)
961 const gchar *default_name = _("mcen_ia_default_folder_name");
965 for(i = 0; i < 100; ++ i) {
966 gboolean exists = FALSE;
968 sprintf(num_str, "%.2u", i);
971 real_suggested_name = g_strdup (default_name);
973 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
975 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
982 g_free (real_suggested_name);
985 /* Didn't find a free number */
987 real_suggested_name = g_strdup (default_name);
989 real_suggested_name = suggested_name;
992 /* In hildon 2.2 we always suggest the archive folder as parent */
993 suggested_folder = TNY_FOLDER_STORE (
994 modest_tny_account_get_special_folder
995 (modest_tny_account_store_get_local_folders_account (modest_runtime_get_account_store ()),
996 TNY_FOLDER_TYPE_ARCHIVE));
998 tmp = g_strconcat (_("mcen_fi_new_folder_name"), ":", NULL);
999 result = modest_platform_run_folder_common_dialog (parent_window,
1001 _("mcen_ti_new_folder"),
1003 real_suggested_name,
1010 if (suggested_name == NULL)
1011 g_free(real_suggested_name);
1017 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1018 TnyFolderStore *parent_folder,
1019 const gchar *suggested_name,
1020 gchar **folder_name)
1022 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1024 return modest_platform_run_folder_common_dialog (parent_window,
1026 _HL("ckdg_ti_rename_folder"),
1027 _HL("ckdg_fi_rename_name"),
1038 on_destroy_dialog (GtkWidget *dialog)
1040 /* This could happen when the dialogs get programatically
1041 hidden or destroyed (for example when closing the
1042 application while a dialog is being shown) */
1043 if (!GTK_IS_WIDGET (dialog))
1046 gtk_widget_destroy (dialog);
1048 if (gtk_events_pending ())
1049 gtk_main_iteration ();
1053 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1054 const gchar *message)
1059 dialog = hildon_note_new_confirmation (parent_window, message);
1060 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1061 GTK_WINDOW (dialog), parent_window);
1063 response = gtk_dialog_run (GTK_DIALOG (dialog));
1065 on_destroy_dialog (dialog);
1071 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1072 const gchar *message,
1073 const gchar *button_accept,
1074 const gchar *button_cancel)
1079 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1080 button_accept, GTK_RESPONSE_ACCEPT,
1081 button_cancel, GTK_RESPONSE_CANCEL,
1084 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1085 GTK_WINDOW (dialog), parent_window);
1087 response = gtk_dialog_run (GTK_DIALOG (dialog));
1089 on_destroy_dialog (dialog);
1095 modest_platform_run_information_dialog (GtkWindow *parent_window,
1096 const gchar *message,
1101 note = hildon_note_new_information (parent_window, message);
1103 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1104 GTK_WINDOW (note), parent_window);
1107 gtk_dialog_run (GTK_DIALOG (note));
1109 on_destroy_dialog (note);
1111 g_signal_connect_swapped (note,
1113 G_CALLBACK (on_destroy_dialog),
1116 gtk_widget_show_all (note);
1120 typedef struct _ConnectAndWaitData {
1122 GMainLoop *wait_loop;
1123 gboolean has_callback;
1125 } ConnectAndWaitData;
1129 quit_wait_loop (TnyAccount *account,
1130 ConnectAndWaitData *data)
1132 /* Set the has_callback to TRUE (means that the callback was
1133 executed and wake up every code waiting for cond to be
1135 g_mutex_lock (data->mutex);
1136 data->has_callback = TRUE;
1137 if (data->wait_loop)
1138 g_main_loop_quit (data->wait_loop);
1139 g_mutex_unlock (data->mutex);
1143 on_connection_status_changed (TnyAccount *account,
1144 TnyConnectionStatus status,
1147 TnyConnectionStatus conn_status;
1148 ConnectAndWaitData *data;
1150 /* Ignore if reconnecting or disconnected */
1151 conn_status = tny_account_get_connection_status (account);
1152 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1153 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1156 /* Remove the handler */
1157 data = (ConnectAndWaitData *) user_data;
1158 g_signal_handler_disconnect (account, data->handler);
1160 /* Quit from wait loop */
1161 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1165 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1170 /* Quit from wait loop */
1171 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1175 modest_platform_connect_and_wait (GtkWindow *parent_window,
1176 TnyAccount *account)
1178 ConnectAndWaitData *data = NULL;
1179 gboolean device_online;
1181 TnyConnectionStatus conn_status;
1182 gboolean user_requested;
1184 device = modest_runtime_get_device();
1185 device_online = tny_device_is_online (device);
1187 /* Whether the connection is user requested or automatically
1188 requested, for example via D-Bus */
1189 user_requested = (parent_window) ? TRUE : FALSE;
1191 /* If there is no account check only the device status */
1196 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1197 NULL, user_requested);
1200 /* Return if the account is already connected */
1201 conn_status = tny_account_get_connection_status (account);
1202 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1205 /* Create the helper */
1206 data = g_slice_new0 (ConnectAndWaitData);
1207 data->mutex = g_mutex_new ();
1208 data->has_callback = FALSE;
1210 /* Connect the device */
1211 if (!device_online) {
1212 /* Track account connection status changes */
1213 data->handler = g_signal_connect (account, "connection-status-changed",
1214 G_CALLBACK (on_connection_status_changed),
1216 /* Try to connect the device */
1217 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1218 NULL, user_requested);
1220 /* If the device connection failed then exit */
1221 if (!device_online && data->handler)
1224 /* Force a reconnection of the account */
1225 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1226 on_tny_camel_account_set_online_cb, data);
1229 /* Wait until the callback is executed */
1230 g_mutex_lock (data->mutex);
1231 if (!data->has_callback) {
1232 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1233 gdk_threads_leave ();
1234 g_mutex_unlock (data->mutex);
1235 g_main_loop_run (data->wait_loop);
1236 g_mutex_lock (data->mutex);
1237 gdk_threads_enter ();
1239 g_mutex_unlock (data->mutex);
1243 if (g_signal_handler_is_connected (account, data->handler))
1244 g_signal_handler_disconnect (account, data->handler);
1245 g_mutex_free (data->mutex);
1246 g_main_loop_unref (data->wait_loop);
1247 g_slice_free (ConnectAndWaitData, data);
1250 conn_status = tny_account_get_connection_status (account);
1251 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1255 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1257 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1258 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1259 /* This must be a maildir account, which does not require a connection: */
1264 return modest_platform_connect_and_wait (parent_window, account);
1268 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1271 return TRUE; /* Maybe it is something local. */
1273 gboolean result = TRUE;
1274 if (TNY_IS_FOLDER (folder_store)) {
1275 /* Get the folder's parent account: */
1276 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1277 if (account != NULL) {
1278 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1279 g_object_unref (account);
1281 } else if (TNY_IS_ACCOUNT (folder_store)) {
1282 /* Use the folder store as an account: */
1283 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1290 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1294 dialog = modest_hildon2_sort_dialog_new (parent_window);
1301 modest_platform_set_update_interval (guint minutes)
1303 #ifdef MODEST_HAVE_LIBALARM
1305 ModestConf *conf = modest_runtime_get_conf ();
1309 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1311 /* Delete any existing alarm,
1312 * because we will replace it: */
1314 if (alarmd_event_del(alarm_cookie) != 1)
1315 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1317 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1320 /* 0 means no updates: */
1325 /* Register alarm: */
1327 /* Set the interval in alarm_event_t structure: */
1328 alarm_event_t *event = alarm_event_create ();
1329 alarm_event_add_actions (event, 1);
1330 alarm_action_t *action = alarm_event_get_action (event, 0);
1331 event->alarm_time = minutes * 60; /* seconds */
1333 /* Set recurrence every few minutes: */
1334 event->recur_secs = minutes*60;
1335 event->recur_count = -1; /* Means infinite */
1337 /* Specify what should happen when the alarm happens:
1338 * It should call this D-Bus method: */
1340 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1341 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1342 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1343 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1344 action->flags = ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1346 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1347 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1348 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1349 * This is why we want to use the Alarm API instead of just g_timeout_add().
1350 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1351 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1353 event->flags = ALARM_EVENT_CONNECTED;
1355 alarm_cookie = alarmd_event_add (event);
1358 alarm_event_delete (event);
1360 /* Store the alarm ID in GConf, so we can remove it later:
1361 * This is apparently valid between application instances. */
1362 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1364 if (!alarm_cookie) {
1366 g_debug ("Error setting alarm event. \n");
1370 #endif /* MODEST_HAVE_LIBALARM */
1375 modest_platform_push_email_notification(void)
1377 gboolean screen_on = TRUE, app_in_foreground;
1379 /* Get the window status */
1380 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1382 /* If the screen is on and the app is in the
1383 foreground we don't show anything */
1384 if (!(screen_on && app_in_foreground)) {
1386 _modest_platform_play_email_tone ();
1388 /* Activate LED. This must be deactivated by
1389 modest_platform_remove_new_mail_notifications */
1390 #ifdef MODEST_HAVE_MCE
1391 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1395 MCE_ACTIVATE_LED_PATTERN,
1397 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1404 modest_platform_on_new_headers_received (TnyList *header_list,
1405 gboolean show_visual)
1407 g_return_if_fail (TNY_IS_LIST(header_list));
1409 if (tny_list_get_length(header_list) == 0) {
1410 g_warning ("%s: header list is empty", __FUNCTION__);
1415 modest_platform_push_email_notification ();
1416 /* We do a return here to avoid indentation with an else */
1420 #ifdef MODEST_HAVE_HILDON_NOTIFY
1421 HildonNotification *notification;
1423 GSList *notifications_list = NULL;
1425 /* Get previous notifications ids */
1426 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1427 MODEST_CONF_NOTIFICATION_IDS,
1428 MODEST_CONF_VALUE_INT, NULL);
1430 iter = tny_list_create_iterator (header_list);
1431 while (!tny_iterator_is_done (iter)) {
1432 gchar *url = NULL, *display_address = NULL, *summary = NULL;
1433 const gchar *display_date;
1434 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1435 TnyFolder *folder = tny_header_get_folder (header);
1436 gboolean first_notification = TRUE;
1439 ModestDatetimeFormatter *datetime_formatter;
1441 /* constant string, don't free */
1442 datetime_formatter = modest_datetime_formatter_new ();
1443 display_date = modest_datetime_formatter_display_datetime (datetime_formatter,
1444 tny_header_get_date_received (header));
1445 g_object_unref (datetime_formatter);
1447 display_address = tny_header_dup_from (header);
1448 /* string is changed in-place */
1449 modest_text_utils_get_display_address (display_address);
1451 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1452 str = tny_header_dup_subject (header);
1453 notification = hildon_notification_new (summary,
1455 "qgn_list_messagin",
1458 /* Create the message URL */
1459 str = tny_header_dup_uid (header);
1460 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1464 hildon_notification_add_dbus_action(notification,
1467 MODEST_DBUS_SERVICE,
1470 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1474 /* Play sound if the user wants. Show the LED
1475 pattern. Show and play just one */
1476 if (G_UNLIKELY (first_notification)) {
1477 gchar *active_profile;
1480 gint mail_volume_int;
1482 first_notification = FALSE;
1484 active_profile = profile_get_profile ();
1485 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
1486 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
1487 mail_volume_int = profile_parse_int (mail_volume);
1489 if (mail_volume_int > 0)
1490 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1491 "sound-file", mail_tone);
1493 g_free (mail_volume);
1495 g_free (active_profile);
1497 /* Set the led pattern */
1498 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1500 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1502 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1505 /* Notify. We need to do this in an idle because this function
1506 could be called from a thread */
1507 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1509 /* Save id in the list */
1510 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1511 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1512 /* We don't listen for the "closed" signal, because we
1513 don't care about if the notification was removed or
1514 not to store the list in gconf */
1516 /* Free & carry on */
1517 g_free (display_address);
1520 g_object_unref (folder);
1521 g_object_unref (header);
1522 tny_iterator_next (iter);
1524 g_object_unref (iter);
1527 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1528 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1530 g_slist_free (notifications_list);
1532 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1536 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1539 #ifdef MODEST_HAVE_MCE
1540 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1544 MCE_DEACTIVATE_LED_PATTERN,
1546 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1552 #ifdef MODEST_HAVE_HILDON_NOTIFY
1553 GSList *notif_list = NULL;
1555 /* Get previous notifications ids */
1556 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1557 MODEST_CONF_NOTIFICATION_IDS,
1558 MODEST_CONF_VALUE_INT, NULL);
1560 while (notif_list) {
1562 NotifyNotification *notif;
1564 /* Nasty HACK to remove the notifications, set the id
1565 of the existing ones and then close them */
1566 notif_id = GPOINTER_TO_INT(notif_list->data);
1567 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1568 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1570 /* Close the notification, note that some ids could be
1571 already invalid, but we don't care because it does
1573 notify_notification_close(notif, NULL);
1574 g_object_unref(notif);
1576 /* Delete the link, it's like going to the next */
1577 notif_list = g_slist_delete_link (notif_list, notif_list);
1581 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1582 notif_list, MODEST_CONF_VALUE_INT, NULL);
1584 g_slist_free (notif_list);
1586 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1592 modest_platform_get_global_settings_dialog ()
1594 return modest_hildon2_global_settings_dialog_new ();
1598 modest_platform_show_help (GtkWindow *parent_window,
1599 const gchar *help_id)
1605 modest_platform_show_search_messages (GtkWindow *parent_window)
1607 osso_return_t result = OSSO_ERROR;
1609 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1610 "osso_global_search",
1611 "search_email", NULL, DBUS_TYPE_INVALID);
1613 if (result != OSSO_OK) {
1614 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1619 modest_platform_show_addressbook (GtkWindow *parent_window)
1621 osso_return_t result = OSSO_ERROR;
1623 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1625 "top_application", NULL, DBUS_TYPE_INVALID);
1627 if (result != OSSO_OK) {
1628 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1633 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1635 GtkWidget *widget = modest_folder_view_new (query);
1637 /* Show one account by default */
1638 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1639 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1641 /* Restore settings */
1642 modest_widget_memory_restore (modest_runtime_get_conf(),
1644 MODEST_CONF_FOLDER_VIEW_KEY);
1650 banner_finish (gpointer data, GObject *object)
1652 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1653 modest_window_mgr_unregister_banner (mgr);
1654 g_object_unref (mgr);
1658 modest_platform_information_banner (GtkWidget *parent,
1659 const gchar *icon_name,
1662 GtkWidget *banner, *banner_parent = NULL;
1663 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1665 if (modest_window_mgr_get_num_windows (mgr) == 0)
1668 if (parent && GTK_IS_WINDOW (parent)) {
1669 /* If the window is the active one then show the
1670 banner on top of this window */
1671 if (gtk_window_is_active (GTK_WINDOW (parent)))
1672 banner_parent = parent;
1673 /* If the window is not the topmost but it's visible
1674 (it's minimized for example) then show the banner
1676 else if (GTK_WIDGET_VISIBLE (parent))
1677 banner_parent = NULL;
1678 /* If the window is hidden (like the main window when
1679 running in the background) then do not show
1686 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1688 modest_window_mgr_register_banner (mgr);
1690 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1694 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1695 const gchar *icon_name,
1701 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1704 banner = hildon_banner_show_information (parent, icon_name, text);
1705 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1709 modest_platform_animation_banner (GtkWidget *parent,
1710 const gchar *animation_name,
1713 GtkWidget *inf_note = NULL;
1715 g_return_val_if_fail (text != NULL, NULL);
1717 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1720 /* If the parent is not visible then do not show */
1721 if (parent && !GTK_WIDGET_VISIBLE (parent))
1724 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1732 TnyAccount *account;
1735 } CheckAccountIdleData;
1737 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1740 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1742 gboolean stop_trying = FALSE;
1743 g_return_val_if_fail (data && data->account, FALSE);
1745 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1746 tny_account_get_connection_status (data->account));
1748 if (data && data->account &&
1749 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1750 * after which the account is likely to be usable, or never likely to be usable soon: */
1751 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1753 data->is_online = TRUE;
1757 /* Give up if we have tried too many times: */
1758 if (data->count_tries >= NUMBER_OF_TRIES) {
1761 /* Wait for another timeout: */
1762 ++(data->count_tries);
1767 /* Allow the function that requested this idle callback to continue: */
1769 g_main_loop_quit (data->loop);
1772 g_object_unref (data->account);
1774 return FALSE; /* Don't call this again. */
1776 return TRUE; /* Call this timeout callback again. */
1780 /* Return TRUE immediately if the account is already online,
1781 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1782 * soon as the account is online, or FALSE if the account does
1783 * not become online in the NUMBER_OF_TRIES seconds.
1784 * This is useful when the D-Bus method was run immediately after
1785 * the application was started (when using D-Bus activation),
1786 * because the account usually takes a short time to go online.
1787 * The return value is maybe not very useful.
1790 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1794 g_return_val_if_fail (account, FALSE);
1796 if (!tny_device_is_online (modest_runtime_get_device())) {
1797 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1801 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1802 * so we avoid wait unnecessarily: */
1803 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1806 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1807 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1808 * we want to avoid. */
1809 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1812 /* This blocks on the result: */
1813 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1814 data->is_online = FALSE;
1815 data->account = account;
1816 g_object_ref (data->account);
1817 data->count_tries = 0;
1819 GMainContext *context = NULL; /* g_main_context_new (); */
1820 data->loop = g_main_loop_new (context, FALSE /* not running */);
1822 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1824 /* This main loop will run until the idle handler has stopped it: */
1825 g_main_loop_run (data->loop);
1827 g_main_loop_unref (data->loop);
1828 /* g_main_context_unref (context); */
1830 is_online = data->is_online;
1831 g_slice_free (CheckAccountIdleData, data);
1839 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1841 /* GTK_RESPONSE_HELP means we need to show the certificate */
1842 if (response_id == GTK_RESPONSE_APPLY) {
1846 /* Do not close the dialog */
1847 g_signal_stop_emission_by_name (dialog, "response");
1849 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1850 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1851 gtk_dialog_run (GTK_DIALOG(note));
1852 gtk_widget_destroy (note);
1858 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1859 const gchar *certificate)
1864 HildonWindowStack *stack;
1866 stack = hildon_window_stack_get_default ();
1867 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1870 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1875 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1878 /* We use GTK_RESPONSE_APPLY because we want the button in the
1879 middle of OK and CANCEL the same as the browser does for
1880 example. With GTK_RESPONSE_HELP the view button is aligned
1881 to the left while the other two to the right */
1882 note = hildon_note_new_confirmation_add_buttons (
1885 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1886 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1887 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1890 g_signal_connect (G_OBJECT(note), "response",
1891 G_CALLBACK(on_cert_dialog_response),
1892 (gpointer) certificate);
1894 response = gtk_dialog_run(GTK_DIALOG(note));
1896 on_destroy_dialog (note);
1899 return response == GTK_RESPONSE_OK;
1903 modest_platform_run_alert_dialog (const gchar* prompt,
1904 gboolean is_question)
1906 ModestWindow *top_win;
1907 HildonWindowStack *stack;
1909 stack = hildon_window_stack_get_default ();
1910 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1913 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1918 gboolean retval = TRUE;
1920 /* The Tinymail documentation says that we should show Yes and No buttons,
1921 * when it is a question.
1922 * Obviously, we need tinymail to use more specific error codes instead,
1923 * so we know what buttons to show. */
1924 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
1926 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1927 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
1929 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1930 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1932 on_destroy_dialog (dialog);
1934 /* Just show the error text and use the default response: */
1935 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
1943 GtkWindow *parent_window;
1944 ModestConnectedPerformer callback;
1945 TnyAccount *account;
1952 on_went_online_info_free (OnWentOnlineInfo *info)
1954 /* And if we cleanup, we DO cleanup :-) */
1957 g_object_unref (info->device);
1960 if (info->parent_window)
1961 g_object_unref (info->parent_window);
1963 g_object_unref (info->account);
1965 g_slice_free (OnWentOnlineInfo, info);
1967 /* We're done ... */
1973 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
1975 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1977 /* Now it's really time to callback to the caller. If going online didn't succeed,
1978 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
1979 * canceled will be set. Etcetera etcetera. */
1981 if (info->callback) {
1982 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
1985 /* This is our last call, we must cleanup here if we didn't yet do that */
1986 on_went_online_info_free (info);
1993 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
1995 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1996 info->iap = g_strdup (iap_id);
1998 if (canceled || err || !info->account) {
2000 /* If there's a problem or if there's no account (then that's it for us, we callback
2001 * the caller's callback now. He'll have to handle err or canceled, of course.
2002 * We are not really online, as the account is not really online here ... */
2004 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2005 * this info. We don't cleanup err, Tinymail does that! */
2007 if (info->callback) {
2009 /* info->account can be NULL here, this means that the user did not
2010 * provide a nice account instance. We'll assume that the user knows
2011 * what he's doing and is happy with just the device going online.
2013 * We can't do magic, we don't know what account the user wants to
2014 * see going online. So just the device goes online, end of story */
2016 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2019 } else if (info->account) {
2021 /* If there's no problem and if we have an account, we'll put the account
2022 * online too. When done, the callback of bringing the account online
2023 * will callback the caller's callback. This is the most normal case. */
2025 info->device = TNY_DEVICE (g_object_ref (device));
2027 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2028 on_account_went_online, info);
2030 /* The on_account_went_online cb frees up the info, go look if you
2031 * don't believe me! (so we return here) */
2036 /* We cleanup if we are not bringing the account online too */
2037 on_went_online_info_free (info);
2043 modest_platform_connect_and_perform (GtkWindow *parent_window,
2045 TnyAccount *account,
2046 ModestConnectedPerformer callback,
2049 gboolean device_online;
2051 TnyConnectionStatus conn_status;
2052 OnWentOnlineInfo *info;
2054 device = modest_runtime_get_device();
2055 device_online = tny_device_is_online (device);
2057 /* If there is no account check only the device status */
2060 if (device_online) {
2062 /* We promise to instantly perform the callback, so ... */
2064 callback (FALSE, NULL, parent_window, account, user_data);
2069 info = g_slice_new0 (OnWentOnlineInfo);
2072 info->device = NULL;
2073 info->account = NULL;
2076 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2078 info->parent_window = NULL;
2079 info->user_data = user_data;
2080 info->callback = callback;
2082 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2083 force, on_conic_device_went_online,
2086 /* We'll cleanup in on_conic_device_went_online */
2089 /* The other code has no more reason to run. This is all that we can do for the
2090 * caller (he should have given us a nice and clean account instance!). We
2091 * can't do magic, we don't know what account he intends to bring online. So
2092 * we'll just bring the device online (and await his false bug report). */
2098 /* Return if the account is already connected */
2100 conn_status = tny_account_get_connection_status (account);
2101 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2103 /* We promise to instantly perform the callback, so ... */
2105 callback (FALSE, NULL, parent_window, account, user_data);
2111 /* Else, we are in a state that requires that we go online before we
2112 * call the caller's callback. */
2114 info = g_slice_new0 (OnWentOnlineInfo);
2116 info->device = NULL;
2118 info->account = TNY_ACCOUNT (g_object_ref (account));
2121 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2123 info->parent_window = NULL;
2125 /* So we'll put the callback away for later ... */
2127 info->user_data = user_data;
2128 info->callback = callback;
2130 if (!device_online) {
2132 /* If also the device is offline, then we connect both the device
2133 * and the account */
2135 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2136 force, on_conic_device_went_online,
2141 /* If the device is online, we'll just connect the account */
2143 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2144 on_account_went_online, info);
2147 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2148 * in both situations, go look if you don't believe me! */
2154 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2156 TnyFolderStore *folder_store,
2157 ModestConnectedPerformer callback,
2160 TnyAccount *account = NULL;
2162 if (!folder_store) {
2163 /* We promise to instantly perform the callback, so ... */
2165 callback (FALSE, NULL, parent_window, NULL, user_data);
2169 } else if (TNY_IS_FOLDER (folder_store)) {
2170 /* Get the folder's parent account: */
2171 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2172 } else if (TNY_IS_ACCOUNT (folder_store)) {
2173 /* Use the folder store as an account: */
2174 account = TNY_ACCOUNT (g_object_ref (folder_store));
2177 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
2178 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2179 /* No need to connect a local account */
2181 callback (FALSE, NULL, parent_window, account, user_data);
2186 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2190 g_object_unref (account);
2194 src_account_connect_performer (gboolean canceled,
2196 GtkWindow *parent_window,
2197 TnyAccount *src_account,
2200 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2202 if (canceled || err) {
2203 /* If there was any error call the user callback */
2204 info->callback (canceled, err, parent_window, src_account, info->data);
2206 /* Connect the destination account */
2207 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2208 TNY_FOLDER_STORE (info->dst_account),
2209 info->callback, info->data);
2212 /* Free the info object */
2213 g_object_unref (info->dst_account);
2214 g_slice_free (DoubleConnectionInfo, info);
2219 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2221 TnyFolderStore *folder_store,
2222 DoubleConnectionInfo *connect_info)
2224 modest_platform_connect_if_remote_and_perform(parent_window,
2227 src_account_connect_performer,
2232 modest_platform_get_account_settings_wizard (void)
2234 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2236 return GTK_WIDGET (dialog);
2240 modest_platform_get_current_connection (void)
2242 TnyDevice *device = NULL;
2243 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2245 device = modest_runtime_get_device ();
2247 if (!tny_device_is_online (device))
2248 return MODEST_CONNECTED_VIA_ANY;
2250 #ifdef MODEST_HAVE_CONIC
2252 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2254 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2255 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2256 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2258 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2259 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2260 !strcmp (bearer_type, "WIMAX")) {
2261 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2263 retval = MODEST_CONNECTED_VIA_ANY;
2266 g_object_unref (iap);
2269 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2270 #endif /* MODEST_HAVE_CONIC */
2277 modest_platform_check_memory_low (ModestWindow *win,
2282 /* are we in low memory state? */
2283 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2285 if (win && lowmem && visuals)
2286 modest_platform_run_information_dialog (
2288 dgettext("ke-recv","memr_ib_operation_disabled"),
2292 g_debug ("%s: low memory reached. disallowing some operations",
2299 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2305 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2308 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2309 GTK_WINDOW (dialog),
2311 gtk_widget_show_all (dialog);
2313 g_signal_connect_swapped (dialog, "response",
2314 G_CALLBACK (gtk_widget_destroy),
2319 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2325 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2328 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2329 GTK_WINDOW (dialog),
2331 gtk_widget_show_all (dialog);
2333 g_signal_connect_swapped (dialog, "response",
2334 G_CALLBACK (gtk_widget_destroy),
2339 modest_platform_get_osso_context (void)
2341 return modest_maemo_utils_get_osso_context ();
2345 _modest_platform_play_email_tone (void)
2347 gchar *active_profile;
2350 gint mail_volume_int;
2352 ca_context *ca_con = NULL;
2353 ca_proplist *pl = NULL;
2355 active_profile = profile_get_profile ();
2356 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2357 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2358 mail_volume_int = profile_parse_int (mail_volume);
2360 if (mail_volume_int > 0) {
2362 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2363 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2367 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2368 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2369 ca_context_destroy(ca_con);
2373 ca_proplist_create(&pl);
2374 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2375 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2377 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2378 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2380 ca_proplist_destroy(pl);
2381 ca_context_destroy(ca_con);
2384 g_free (mail_volume);
2386 g_free (active_profile);
2390 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2392 GtkTreeViewColumn *column,
2395 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_OK);
2399 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2400 GtkWidget **folder_view)
2402 GtkWidget *dialog, *folder_view_container;
2404 /* Create dialog. We cannot use a touch selector because we
2405 need to use here the folder view widget directly */
2406 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2407 GTK_WINDOW (parent_window),
2408 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2409 GTK_DIALOG_DESTROY_WITH_PARENT,
2410 _("mcen_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2413 /* Create folder view */
2414 *folder_view = modest_platform_create_folder_view (NULL);
2416 /* Simulate the behaviour of a HildonPickerDialog by emitting
2417 a response when a folder is selected */
2418 g_signal_connect (*folder_view, "row-activated",
2419 G_CALLBACK (on_move_to_dialog_folder_activated),
2422 /* Create pannable and add it to the dialog */
2423 folder_view_container = hildon_pannable_area_new ();
2424 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), folder_view_container);
2425 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2427 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2429 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2430 gtk_widget_show (folder_view_container);
2431 gtk_widget_show (*folder_view);
2437 modest_platform_get_list_to_move (ModestWindow *window)
2439 if (MODEST_IS_HEADER_WINDOW (window)) {
2440 ModestHeaderView *header_view;
2442 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2444 return modest_header_view_get_selected_headers (header_view);
2445 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2446 ModestFolderView *folder_view;
2447 TnyFolderStore *selected_folder;
2450 list = TNY_LIST (tny_simple_list_new ());
2451 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2452 selected_folder = modest_folder_view_get_selected (folder_view);
2453 if (selected_folder) {
2454 tny_list_prepend (list, G_OBJECT (selected_folder));
2455 g_object_unref (selected_folder);