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;
958 ModestTnyAccountStore *acc_store;
961 if(suggested_name == NULL)
963 const gchar *default_name = _("mcen_ia_default_folder_name");
967 for(i = 0; i < 100; ++ i) {
968 gboolean exists = FALSE;
970 sprintf(num_str, "%.2u", i);
973 real_suggested_name = g_strdup (default_name);
975 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
977 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
984 g_free (real_suggested_name);
987 /* Didn't find a free number */
989 real_suggested_name = g_strdup (default_name);
991 real_suggested_name = suggested_name;
994 /* In hildon 2.2 we always suggest the archive folder as parent */
995 acc_store = modest_runtime_get_account_store ();
996 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
998 suggested_folder = (TnyFolderStore *)
999 modest_tny_account_get_special_folder (account,
1000 TNY_FOLDER_TYPE_ARCHIVE);
1001 g_object_unref (account);
1005 /* If there is not archive folder then fallback to local folders account */
1006 if (!suggested_folder)
1007 suggested_folder = (TnyFolderStore *)
1008 modest_tny_account_store_get_local_folders_account (acc_store);
1010 tmp = g_strconcat (_("mcen_fi_new_folder_name"), ":", NULL);
1011 result = modest_platform_run_folder_common_dialog (parent_window,
1013 _("mcen_ti_new_folder"),
1015 real_suggested_name,
1022 if (suggested_name == NULL)
1023 g_free(real_suggested_name);
1029 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1030 TnyFolderStore *parent_folder,
1031 const gchar *suggested_name,
1032 gchar **folder_name)
1034 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1036 return modest_platform_run_folder_common_dialog (parent_window,
1038 _HL("ckdg_ti_rename_folder"),
1039 _HL("ckdg_fi_rename_name"),
1050 on_destroy_dialog (GtkWidget *dialog)
1052 /* This could happen when the dialogs get programatically
1053 hidden or destroyed (for example when closing the
1054 application while a dialog is being shown) */
1055 if (!GTK_IS_WIDGET (dialog))
1058 gtk_widget_destroy (dialog);
1060 if (gtk_events_pending ())
1061 gtk_main_iteration ();
1065 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1066 const gchar *message)
1071 dialog = hildon_note_new_confirmation (parent_window, message);
1072 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1073 GTK_WINDOW (dialog), parent_window);
1075 response = gtk_dialog_run (GTK_DIALOG (dialog));
1077 on_destroy_dialog (dialog);
1083 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1084 const gchar *message,
1085 const gchar *button_accept,
1086 const gchar *button_cancel)
1091 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1092 button_accept, GTK_RESPONSE_ACCEPT,
1093 button_cancel, GTK_RESPONSE_CANCEL,
1096 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1097 GTK_WINDOW (dialog), parent_window);
1099 response = gtk_dialog_run (GTK_DIALOG (dialog));
1101 on_destroy_dialog (dialog);
1107 modest_platform_run_information_dialog (GtkWindow *parent_window,
1108 const gchar *message,
1113 note = hildon_note_new_information (parent_window, message);
1115 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1116 GTK_WINDOW (note), parent_window);
1119 gtk_dialog_run (GTK_DIALOG (note));
1121 on_destroy_dialog (note);
1123 g_signal_connect_swapped (note,
1125 G_CALLBACK (on_destroy_dialog),
1128 gtk_widget_show_all (note);
1132 typedef struct _ConnectAndWaitData {
1134 GMainLoop *wait_loop;
1135 gboolean has_callback;
1137 } ConnectAndWaitData;
1141 quit_wait_loop (TnyAccount *account,
1142 ConnectAndWaitData *data)
1144 /* Set the has_callback to TRUE (means that the callback was
1145 executed and wake up every code waiting for cond to be
1147 g_mutex_lock (data->mutex);
1148 data->has_callback = TRUE;
1149 if (data->wait_loop)
1150 g_main_loop_quit (data->wait_loop);
1151 g_mutex_unlock (data->mutex);
1155 on_connection_status_changed (TnyAccount *account,
1156 TnyConnectionStatus status,
1159 TnyConnectionStatus conn_status;
1160 ConnectAndWaitData *data;
1162 /* Ignore if reconnecting or disconnected */
1163 conn_status = tny_account_get_connection_status (account);
1164 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1165 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1168 /* Remove the handler */
1169 data = (ConnectAndWaitData *) user_data;
1170 g_signal_handler_disconnect (account, data->handler);
1172 /* Quit from wait loop */
1173 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1177 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1182 /* Quit from wait loop */
1183 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1187 modest_platform_connect_and_wait (GtkWindow *parent_window,
1188 TnyAccount *account)
1190 ConnectAndWaitData *data = NULL;
1191 gboolean device_online;
1193 TnyConnectionStatus conn_status;
1194 gboolean user_requested;
1196 device = modest_runtime_get_device();
1197 device_online = tny_device_is_online (device);
1199 /* Whether the connection is user requested or automatically
1200 requested, for example via D-Bus */
1201 user_requested = (parent_window) ? TRUE : FALSE;
1203 /* If there is no account check only the device status */
1208 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1209 NULL, user_requested);
1212 /* Return if the account is already connected */
1213 conn_status = tny_account_get_connection_status (account);
1214 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1217 /* Create the helper */
1218 data = g_slice_new0 (ConnectAndWaitData);
1219 data->mutex = g_mutex_new ();
1220 data->has_callback = FALSE;
1222 /* Connect the device */
1223 if (!device_online) {
1224 /* Track account connection status changes */
1225 data->handler = g_signal_connect (account, "connection-status-changed",
1226 G_CALLBACK (on_connection_status_changed),
1228 /* Try to connect the device */
1229 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1230 NULL, user_requested);
1232 /* If the device connection failed then exit */
1233 if (!device_online && data->handler)
1236 /* Force a reconnection of the account */
1237 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1238 on_tny_camel_account_set_online_cb, data);
1241 /* Wait until the callback is executed */
1242 g_mutex_lock (data->mutex);
1243 if (!data->has_callback) {
1244 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1245 gdk_threads_leave ();
1246 g_mutex_unlock (data->mutex);
1247 g_main_loop_run (data->wait_loop);
1248 g_mutex_lock (data->mutex);
1249 gdk_threads_enter ();
1251 g_mutex_unlock (data->mutex);
1255 if (g_signal_handler_is_connected (account, data->handler))
1256 g_signal_handler_disconnect (account, data->handler);
1257 g_mutex_free (data->mutex);
1258 g_main_loop_unref (data->wait_loop);
1259 g_slice_free (ConnectAndWaitData, data);
1262 conn_status = tny_account_get_connection_status (account);
1263 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1267 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1269 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1270 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1271 /* This must be a maildir account, which does not require a connection: */
1276 return modest_platform_connect_and_wait (parent_window, account);
1280 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1283 return TRUE; /* Maybe it is something local. */
1285 gboolean result = TRUE;
1286 if (TNY_IS_FOLDER (folder_store)) {
1287 /* Get the folder's parent account: */
1288 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1289 if (account != NULL) {
1290 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1291 g_object_unref (account);
1293 } else if (TNY_IS_ACCOUNT (folder_store)) {
1294 /* Use the folder store as an account: */
1295 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1302 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1306 dialog = modest_hildon2_sort_dialog_new (parent_window);
1313 modest_platform_set_update_interval (guint minutes)
1315 #ifdef MODEST_HAVE_LIBALARM
1317 ModestConf *conf = modest_runtime_get_conf ();
1321 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1323 /* Delete any existing alarm,
1324 * because we will replace it: */
1326 if (alarmd_event_del(alarm_cookie) != 1)
1327 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1329 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1332 /* 0 means no updates: */
1337 /* Register alarm: */
1339 /* Set the interval in alarm_event_t structure: */
1340 alarm_event_t *event = alarm_event_create ();
1341 alarm_event_add_actions (event, 1);
1342 alarm_action_t *action = alarm_event_get_action (event, 0);
1343 event->alarm_time = minutes * 60; /* seconds */
1345 /* Set recurrence every few minutes: */
1346 event->recur_secs = minutes*60;
1347 event->recur_count = -1; /* Means infinite */
1349 /* Specify what should happen when the alarm happens:
1350 * It should call this D-Bus method: */
1352 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1353 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1354 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1355 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1356 action->flags = ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1358 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1359 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1360 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1361 * This is why we want to use the Alarm API instead of just g_timeout_add().
1362 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1363 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1365 event->flags = ALARM_EVENT_CONNECTED;
1367 alarm_cookie = alarmd_event_add (event);
1370 alarm_event_delete (event);
1372 /* Store the alarm ID in GConf, so we can remove it later:
1373 * This is apparently valid between application instances. */
1374 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1376 if (!alarm_cookie) {
1378 g_debug ("Error setting alarm event. \n");
1382 #endif /* MODEST_HAVE_LIBALARM */
1387 modest_platform_push_email_notification(void)
1389 gboolean screen_on, app_in_foreground;
1391 /* Get the window status */
1392 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1394 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1396 /* If the screen is on and the app is in the
1397 foreground we don't show anything */
1398 if (!(screen_on && app_in_foreground)) {
1400 _modest_platform_play_email_tone ();
1402 /* Activate LED. This must be deactivated by
1403 modest_platform_remove_new_mail_notifications */
1404 #ifdef MODEST_HAVE_MCE
1405 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1409 MCE_ACTIVATE_LED_PATTERN,
1411 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1418 modest_platform_on_new_headers_received (TnyList *header_list,
1419 gboolean show_visual)
1421 g_return_if_fail (TNY_IS_LIST(header_list));
1423 if (tny_list_get_length(header_list) == 0) {
1424 g_warning ("%s: header list is empty", __FUNCTION__);
1429 modest_platform_push_email_notification ();
1430 /* We do a return here to avoid indentation with an else */
1434 #ifdef MODEST_HAVE_HILDON_NOTIFY
1435 HildonNotification *notification;
1437 GSList *notifications_list = NULL;
1439 /* Get previous notifications ids */
1440 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1441 MODEST_CONF_NOTIFICATION_IDS,
1442 MODEST_CONF_VALUE_INT, NULL);
1444 iter = tny_list_create_iterator (header_list);
1445 while (!tny_iterator_is_done (iter)) {
1446 gchar *url = NULL, *display_address = NULL, *summary = NULL;
1447 const gchar *display_date;
1448 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1449 TnyFolder *folder = tny_header_get_folder (header);
1450 gboolean first_notification = TRUE;
1453 ModestDatetimeFormatter *datetime_formatter;
1455 /* constant string, don't free */
1456 datetime_formatter = modest_datetime_formatter_new ();
1457 display_date = modest_datetime_formatter_display_datetime (datetime_formatter,
1458 tny_header_get_date_received (header));
1459 g_object_unref (datetime_formatter);
1461 display_address = tny_header_dup_from (header);
1462 /* string is changed in-place */
1463 modest_text_utils_get_display_address (display_address);
1465 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1466 str = tny_header_dup_subject (header);
1467 notification = hildon_notification_new (summary,
1469 "qgn_list_messagin",
1472 /* Create the message URL */
1473 str = tny_header_dup_uid (header);
1474 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1478 hildon_notification_add_dbus_action(notification,
1481 MODEST_DBUS_SERVICE,
1484 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1488 /* Play sound if the user wants. Show the LED
1489 pattern. Show and play just one */
1490 if (G_UNLIKELY (first_notification)) {
1491 gchar *active_profile;
1494 gint mail_volume_int;
1496 first_notification = FALSE;
1498 active_profile = profile_get_profile ();
1499 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
1500 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
1501 mail_volume_int = profile_parse_int (mail_volume);
1503 if (mail_volume_int > 0)
1504 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1505 "sound-file", mail_tone);
1507 g_free (mail_volume);
1509 g_free (active_profile);
1511 /* Set the led pattern */
1512 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1514 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1516 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1519 /* Notify. We need to do this in an idle because this function
1520 could be called from a thread */
1521 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1523 /* Save id in the list */
1524 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1525 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1526 /* We don't listen for the "closed" signal, because we
1527 don't care about if the notification was removed or
1528 not to store the list in gconf */
1530 /* Free & carry on */
1531 g_free (display_address);
1534 g_object_unref (folder);
1535 g_object_unref (header);
1536 tny_iterator_next (iter);
1538 g_object_unref (iter);
1541 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1542 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1544 g_slist_free (notifications_list);
1546 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1550 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1553 #ifdef MODEST_HAVE_MCE
1554 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1558 MCE_DEACTIVATE_LED_PATTERN,
1560 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1566 #ifdef MODEST_HAVE_HILDON_NOTIFY
1567 GSList *notif_list = NULL;
1569 /* Get previous notifications ids */
1570 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1571 MODEST_CONF_NOTIFICATION_IDS,
1572 MODEST_CONF_VALUE_INT, NULL);
1574 while (notif_list) {
1576 NotifyNotification *notif;
1578 /* Nasty HACK to remove the notifications, set the id
1579 of the existing ones and then close them */
1580 notif_id = GPOINTER_TO_INT(notif_list->data);
1581 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1582 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1584 /* Close the notification, note that some ids could be
1585 already invalid, but we don't care because it does
1587 notify_notification_close(notif, NULL);
1588 g_object_unref(notif);
1590 /* Delete the link, it's like going to the next */
1591 notif_list = g_slist_delete_link (notif_list, notif_list);
1595 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1596 notif_list, MODEST_CONF_VALUE_INT, NULL);
1598 g_slist_free (notif_list);
1600 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1606 modest_platform_get_global_settings_dialog ()
1608 return modest_hildon2_global_settings_dialog_new ();
1612 modest_platform_show_help (GtkWindow *parent_window,
1613 const gchar *help_id)
1619 modest_platform_show_search_messages (GtkWindow *parent_window)
1621 osso_return_t result = OSSO_ERROR;
1623 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1624 "osso_global_search",
1625 "search_email", NULL, DBUS_TYPE_INVALID);
1627 if (result != OSSO_OK) {
1628 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1633 modest_platform_show_addressbook (GtkWindow *parent_window)
1635 osso_return_t result = OSSO_ERROR;
1637 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1639 "top_application", NULL, DBUS_TYPE_INVALID);
1641 if (result != OSSO_OK) {
1642 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1647 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1649 GtkWidget *widget = modest_folder_view_new (query);
1651 /* Show one account by default */
1652 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1653 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1655 /* Restore settings */
1656 modest_widget_memory_restore (modest_runtime_get_conf(),
1658 MODEST_CONF_FOLDER_VIEW_KEY);
1664 banner_finish (gpointer data, GObject *object)
1666 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1667 modest_window_mgr_unregister_banner (mgr);
1668 g_object_unref (mgr);
1672 modest_platform_information_banner (GtkWidget *parent,
1673 const gchar *icon_name,
1676 GtkWidget *banner, *banner_parent = NULL;
1677 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1679 if (modest_window_mgr_get_num_windows (mgr) == 0)
1682 if (parent && GTK_IS_WINDOW (parent)) {
1683 /* If the window is the active one then show the
1684 banner on top of this window */
1685 if (gtk_window_is_active (GTK_WINDOW (parent)))
1686 banner_parent = parent;
1687 /* If the window is not the topmost but it's visible
1688 (it's minimized for example) then show the banner
1690 else if (GTK_WIDGET_VISIBLE (parent))
1691 banner_parent = NULL;
1692 /* If the window is hidden (like the main window when
1693 running in the background) then do not show
1700 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1702 modest_window_mgr_register_banner (mgr);
1704 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1708 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1709 const gchar *icon_name,
1715 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1718 banner = hildon_banner_show_information (parent, icon_name, text);
1719 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1723 modest_platform_animation_banner (GtkWidget *parent,
1724 const gchar *animation_name,
1727 GtkWidget *inf_note = NULL;
1729 g_return_val_if_fail (text != NULL, NULL);
1731 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1734 /* If the parent is not visible then do not show */
1735 if (parent && !GTK_WIDGET_VISIBLE (parent))
1738 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1746 TnyAccount *account;
1749 } CheckAccountIdleData;
1751 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1754 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1756 gboolean stop_trying = FALSE;
1757 g_return_val_if_fail (data && data->account, FALSE);
1759 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1760 tny_account_get_connection_status (data->account));
1762 if (data && data->account &&
1763 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1764 * after which the account is likely to be usable, or never likely to be usable soon: */
1765 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1767 data->is_online = TRUE;
1771 /* Give up if we have tried too many times: */
1772 if (data->count_tries >= NUMBER_OF_TRIES) {
1775 /* Wait for another timeout: */
1776 ++(data->count_tries);
1781 /* Allow the function that requested this idle callback to continue: */
1783 g_main_loop_quit (data->loop);
1786 g_object_unref (data->account);
1788 return FALSE; /* Don't call this again. */
1790 return TRUE; /* Call this timeout callback again. */
1794 /* Return TRUE immediately if the account is already online,
1795 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1796 * soon as the account is online, or FALSE if the account does
1797 * not become online in the NUMBER_OF_TRIES seconds.
1798 * This is useful when the D-Bus method was run immediately after
1799 * the application was started (when using D-Bus activation),
1800 * because the account usually takes a short time to go online.
1801 * The return value is maybe not very useful.
1804 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1808 g_return_val_if_fail (account, FALSE);
1810 if (!tny_device_is_online (modest_runtime_get_device())) {
1811 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1815 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1816 * so we avoid wait unnecessarily: */
1817 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1820 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1821 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1822 * we want to avoid. */
1823 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1826 /* This blocks on the result: */
1827 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1828 data->is_online = FALSE;
1829 data->account = account;
1830 g_object_ref (data->account);
1831 data->count_tries = 0;
1833 GMainContext *context = NULL; /* g_main_context_new (); */
1834 data->loop = g_main_loop_new (context, FALSE /* not running */);
1836 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1838 /* This main loop will run until the idle handler has stopped it: */
1839 g_main_loop_run (data->loop);
1841 g_main_loop_unref (data->loop);
1842 /* g_main_context_unref (context); */
1844 is_online = data->is_online;
1845 g_slice_free (CheckAccountIdleData, data);
1853 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1855 /* GTK_RESPONSE_HELP means we need to show the certificate */
1856 if (response_id == GTK_RESPONSE_APPLY) {
1860 /* Do not close the dialog */
1861 g_signal_stop_emission_by_name (dialog, "response");
1863 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1864 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1865 gtk_dialog_run (GTK_DIALOG(note));
1866 gtk_widget_destroy (note);
1872 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1873 const gchar *certificate)
1878 HildonWindowStack *stack;
1880 stack = hildon_window_stack_get_default ();
1881 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1884 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1889 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1892 /* We use GTK_RESPONSE_APPLY because we want the button in the
1893 middle of OK and CANCEL the same as the browser does for
1894 example. With GTK_RESPONSE_HELP the view button is aligned
1895 to the left while the other two to the right */
1896 note = hildon_note_new_confirmation_add_buttons (
1899 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1900 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1901 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1904 g_signal_connect (G_OBJECT(note), "response",
1905 G_CALLBACK(on_cert_dialog_response),
1906 (gpointer) certificate);
1908 response = gtk_dialog_run(GTK_DIALOG(note));
1910 on_destroy_dialog (note);
1913 return response == GTK_RESPONSE_OK;
1917 modest_platform_run_alert_dialog (const gchar* prompt,
1918 gboolean is_question)
1920 ModestWindow *top_win;
1921 HildonWindowStack *stack;
1923 stack = hildon_window_stack_get_default ();
1924 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1927 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1932 gboolean retval = TRUE;
1934 /* The Tinymail documentation says that we should show Yes and No buttons,
1935 * when it is a question.
1936 * Obviously, we need tinymail to use more specific error codes instead,
1937 * so we know what buttons to show. */
1938 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
1940 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1941 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
1943 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1944 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1946 on_destroy_dialog (dialog);
1948 /* Just show the error text and use the default response: */
1949 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
1957 GtkWindow *parent_window;
1958 ModestConnectedPerformer callback;
1959 TnyAccount *account;
1966 on_went_online_info_free (OnWentOnlineInfo *info)
1968 /* And if we cleanup, we DO cleanup :-) */
1971 g_object_unref (info->device);
1974 if (info->parent_window)
1975 g_object_unref (info->parent_window);
1977 g_object_unref (info->account);
1979 g_slice_free (OnWentOnlineInfo, info);
1981 /* We're done ... */
1987 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
1989 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1991 /* Now it's really time to callback to the caller. If going online didn't succeed,
1992 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
1993 * canceled will be set. Etcetera etcetera. */
1995 if (info->callback) {
1996 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
1999 /* This is our last call, we must cleanup here if we didn't yet do that */
2000 on_went_online_info_free (info);
2007 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2009 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2010 info->iap = g_strdup (iap_id);
2012 if (canceled || err || !info->account) {
2014 /* If there's a problem or if there's no account (then that's it for us, we callback
2015 * the caller's callback now. He'll have to handle err or canceled, of course.
2016 * We are not really online, as the account is not really online here ... */
2018 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2019 * this info. We don't cleanup err, Tinymail does that! */
2021 if (info->callback) {
2023 /* info->account can be NULL here, this means that the user did not
2024 * provide a nice account instance. We'll assume that the user knows
2025 * what he's doing and is happy with just the device going online.
2027 * We can't do magic, we don't know what account the user wants to
2028 * see going online. So just the device goes online, end of story */
2030 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2033 } else if (info->account) {
2035 /* If there's no problem and if we have an account, we'll put the account
2036 * online too. When done, the callback of bringing the account online
2037 * will callback the caller's callback. This is the most normal case. */
2039 info->device = TNY_DEVICE (g_object_ref (device));
2041 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2042 on_account_went_online, info);
2044 /* The on_account_went_online cb frees up the info, go look if you
2045 * don't believe me! (so we return here) */
2050 /* We cleanup if we are not bringing the account online too */
2051 on_went_online_info_free (info);
2057 modest_platform_connect_and_perform (GtkWindow *parent_window,
2059 TnyAccount *account,
2060 ModestConnectedPerformer callback,
2063 gboolean device_online;
2065 TnyConnectionStatus conn_status;
2066 OnWentOnlineInfo *info;
2068 device = modest_runtime_get_device();
2069 device_online = tny_device_is_online (device);
2071 /* If there is no account check only the device status */
2074 if (device_online) {
2076 /* We promise to instantly perform the callback, so ... */
2078 callback (FALSE, NULL, parent_window, account, user_data);
2083 info = g_slice_new0 (OnWentOnlineInfo);
2086 info->device = NULL;
2087 info->account = NULL;
2090 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2092 info->parent_window = NULL;
2093 info->user_data = user_data;
2094 info->callback = callback;
2096 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2097 force, on_conic_device_went_online,
2100 /* We'll cleanup in on_conic_device_went_online */
2103 /* The other code has no more reason to run. This is all that we can do for the
2104 * caller (he should have given us a nice and clean account instance!). We
2105 * can't do magic, we don't know what account he intends to bring online. So
2106 * we'll just bring the device online (and await his false bug report). */
2112 /* Return if the account is already connected */
2114 conn_status = tny_account_get_connection_status (account);
2115 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2117 /* We promise to instantly perform the callback, so ... */
2119 callback (FALSE, NULL, parent_window, account, user_data);
2125 /* Else, we are in a state that requires that we go online before we
2126 * call the caller's callback. */
2128 info = g_slice_new0 (OnWentOnlineInfo);
2130 info->device = NULL;
2132 info->account = TNY_ACCOUNT (g_object_ref (account));
2135 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2137 info->parent_window = NULL;
2139 /* So we'll put the callback away for later ... */
2141 info->user_data = user_data;
2142 info->callback = callback;
2144 if (!device_online) {
2146 /* If also the device is offline, then we connect both the device
2147 * and the account */
2149 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2150 force, on_conic_device_went_online,
2155 /* If the device is online, we'll just connect the account */
2157 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2158 on_account_went_online, info);
2161 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2162 * in both situations, go look if you don't believe me! */
2168 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2170 TnyFolderStore *folder_store,
2171 ModestConnectedPerformer callback,
2174 TnyAccount *account = NULL;
2176 if (!folder_store) {
2177 /* We promise to instantly perform the callback, so ... */
2179 callback (FALSE, NULL, parent_window, NULL, user_data);
2183 } else if (TNY_IS_FOLDER (folder_store)) {
2184 /* Get the folder's parent account: */
2185 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2186 } else if (TNY_IS_ACCOUNT (folder_store)) {
2187 /* Use the folder store as an account: */
2188 account = TNY_ACCOUNT (g_object_ref (folder_store));
2191 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
2192 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2193 /* No need to connect a local account */
2195 callback (FALSE, NULL, parent_window, account, user_data);
2200 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2204 g_object_unref (account);
2208 src_account_connect_performer (gboolean canceled,
2210 GtkWindow *parent_window,
2211 TnyAccount *src_account,
2214 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2216 if (canceled || err) {
2217 /* If there was any error call the user callback */
2218 info->callback (canceled, err, parent_window, src_account, info->data);
2220 /* Connect the destination account */
2221 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2222 TNY_FOLDER_STORE (info->dst_account),
2223 info->callback, info->data);
2226 /* Free the info object */
2227 g_object_unref (info->dst_account);
2228 g_slice_free (DoubleConnectionInfo, info);
2233 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2235 TnyFolderStore *folder_store,
2236 DoubleConnectionInfo *connect_info)
2238 modest_platform_connect_if_remote_and_perform(parent_window,
2241 src_account_connect_performer,
2246 modest_platform_get_account_settings_wizard (void)
2248 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2250 return GTK_WIDGET (dialog);
2254 modest_platform_get_current_connection (void)
2256 TnyDevice *device = NULL;
2257 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2259 device = modest_runtime_get_device ();
2261 if (!tny_device_is_online (device))
2262 return MODEST_CONNECTED_VIA_ANY;
2264 #ifdef MODEST_HAVE_CONIC
2266 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2268 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2269 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2270 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2272 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2273 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2274 !strcmp (bearer_type, "WIMAX")) {
2275 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2277 retval = MODEST_CONNECTED_VIA_ANY;
2280 g_object_unref (iap);
2283 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2284 #endif /* MODEST_HAVE_CONIC */
2291 modest_platform_check_memory_low (ModestWindow *win,
2296 /* are we in low memory state? */
2297 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2299 if (win && lowmem && visuals)
2300 modest_platform_run_information_dialog (
2302 dgettext("ke-recv","memr_ib_operation_disabled"),
2306 g_debug ("%s: low memory reached. disallowing some operations",
2313 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2319 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2322 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2323 GTK_WINDOW (dialog),
2325 gtk_widget_show_all (dialog);
2327 g_signal_connect_swapped (dialog, "response",
2328 G_CALLBACK (gtk_widget_destroy),
2333 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2339 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2342 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2343 GTK_WINDOW (dialog),
2345 gtk_widget_show_all (dialog);
2347 g_signal_connect_swapped (dialog, "response",
2348 G_CALLBACK (gtk_widget_destroy),
2353 modest_platform_get_osso_context (void)
2355 return modest_maemo_utils_get_osso_context ();
2359 _modest_platform_play_email_tone (void)
2361 gchar *active_profile;
2364 gint mail_volume_int;
2366 ca_context *ca_con = NULL;
2367 ca_proplist *pl = NULL;
2369 active_profile = profile_get_profile ();
2370 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2371 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2372 mail_volume_int = profile_parse_int (mail_volume);
2374 if (mail_volume_int > 0) {
2376 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2377 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2381 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2382 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2383 ca_context_destroy(ca_con);
2387 ca_proplist_create(&pl);
2388 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2389 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2391 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2392 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2394 ca_proplist_destroy(pl);
2395 ca_context_destroy(ca_con);
2398 g_free (mail_volume);
2400 g_free (active_profile);
2404 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2406 GtkTreeViewColumn *column,
2409 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_OK);
2413 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2414 GtkWidget **folder_view)
2416 GtkWidget *dialog, *folder_view_container;
2418 /* Create dialog. We cannot use a touch selector because we
2419 need to use here the folder view widget directly */
2420 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2421 GTK_WINDOW (parent_window),
2422 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2423 GTK_DIALOG_DESTROY_WITH_PARENT,
2424 _("mcen_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2427 /* Create folder view */
2428 *folder_view = modest_platform_create_folder_view (NULL);
2430 /* Simulate the behaviour of a HildonPickerDialog by emitting
2431 a response when a folder is selected */
2432 g_signal_connect (*folder_view, "row-activated",
2433 G_CALLBACK (on_move_to_dialog_folder_activated),
2436 /* Create pannable and add it to the dialog */
2437 folder_view_container = hildon_pannable_area_new ();
2438 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), folder_view_container);
2439 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2441 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2443 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2444 gtk_widget_show (folder_view_container);
2445 gtk_widget_show (*folder_view);
2451 modest_platform_get_list_to_move (ModestWindow *window)
2453 if (MODEST_IS_HEADER_WINDOW (window)) {
2454 ModestHeaderView *header_view;
2456 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2458 return modest_header_view_get_selected_headers (header_view);
2459 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2460 ModestFolderView *folder_view;
2461 TnyFolderStore *selected_folder;
2464 list = TNY_LIST (tny_simple_list_new ());
2465 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2466 selected_folder = modest_folder_view_get_selected (folder_view);
2467 if (selected_folder) {
2468 tny_list_prepend (list, G_OBJECT (selected_folder));
2469 g_object_unref (selected_folder);