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-merge-folder.h>
46 #include <tny-error.h>
47 #include <tny-folder.h>
48 #include <tny-account-store-view.h>
49 #include <gtk/gtkicontheme.h>
50 #include <gtk/gtkmenuitem.h>
51 #include <gtk/gtkmain.h>
52 #include <modest-text-utils.h>
53 #include "modest-tny-folder.h"
54 #include "modest-tny-account.h"
56 #include <libgnomevfs/gnome-vfs-mime-utils.h>
57 #include <modest-account-settings-dialog.h>
58 #include <modest-easysetup-wizard-dialog.h>
59 #include "modest-hildon2-sort-dialog.h"
60 #include <hildon/hildon-sound.h>
62 #include "hildon2/modest-hildon2-details-dialog.h"
63 #include "hildon2/modest-hildon2-window-mgr.h"
64 #include <keys_nokia.h>
65 #include <libprofile.h>
67 #include <modest-datetime-formatter.h>
68 #include "modest-header-window.h"
69 #include <modest-folder-window.h>
70 #include <modest-account-mgr.h>
71 #include <modest-account-mgr-helpers.h>
72 #include <modest-ui-constants.h>
73 #include <modest-selector-picker.h>
74 #include <modest-icon-names.h>
76 #ifdef MODEST_HAVE_MCE
77 #include <mce/dbus-names.h>
78 #endif /*MODEST_HAVE_MCE*/
80 #ifdef MODEST_HAVE_ABOOK
81 #include <libosso-abook/osso-abook.h>
82 #endif /*MODEST_HAVE_ABOOK*/
84 #ifdef MODEST_HAVE_LIBALARM
85 #include <alarmd/libalarm.h> /* For alarm_event_add(), etc. */
86 #endif /*MODEST_HAVE_LIBALARM*/
89 #define HILDON_OSSO_URI_ACTION "uri-action"
90 #define URI_ACTION_COPY "copy:"
91 #define MODEST_NEW_MAIL_LIGHTING_PATTERN "PatternCommunicationEmail"
92 #define PROFILE_MAIL_TONE PROFILEKEY_EMAIL_ALERT_TONE
93 #define PROFILE_MAIL_VOLUME PROFILEKEY_EMAIL_ALERT_VOLUME
95 #define COMMON_FOLDER_DIALOG_ENTRY "entry"
96 #define COMMON_FOLDER_DIALOG_ACCOUNT_PICKER "account-picker"
97 #define FOLDER_PICKER_CURRENT_FOLDER "current-folder"
98 #define MODEST_ALARMD_APPID PACKAGE_NAME
101 static void _modest_platform_play_email_tone (void);
105 on_modest_conf_update_interval_changed (ModestConf* self,
107 ModestConfEvent event,
108 ModestConfNotificationId id,
111 g_return_if_fail (key);
113 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
114 const guint update_interval_minutes =
115 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
116 modest_platform_set_update_interval (update_interval_minutes);
123 check_required_files (void)
125 FILE *mcc_file = modest_maemo_open_mcc_mapping_file ();
127 g_printerr ("modest: check for mcc file failed\n");
132 if (access(MODEST_PROVIDER_DATA_FILE, R_OK) != 0 &&
133 access(MODEST_MAEMO_PROVIDER_DATA_FILE, R_OK) != 0) {
134 g_printerr ("modest: cannot find providers data\n");
142 /* the gpointer here is the osso_context. */
144 modest_platform_init (int argc, char *argv[])
146 osso_context_t *osso_context;
148 osso_hw_state_t hw_state = { 0 };
152 if (!check_required_files ()) {
153 g_printerr ("modest: missing required files\n");
157 osso_context = osso_initialize(PACKAGE,PACKAGE_VERSION,
160 g_printerr ("modest: failed to acquire osso context\n");
163 modest_maemo_utils_set_osso_context (osso_context);
165 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
166 g_printerr ("modest: could not get dbus connection\n");
170 /* Add a D-Bus handler to be used when the main osso-rpc
171 * D-Bus handler has not handled something.
172 * We use this for D-Bus methods that need to use more complex types
173 * than osso-rpc supports.
175 if (!dbus_connection_add_filter (con,
176 modest_dbus_req_filter,
180 g_printerr ("modest: Could not add D-Bus filter\n");
184 /* Register our simple D-Bus callbacks, via the osso API: */
185 osso_return_t result = osso_rpc_set_cb_f(osso_context,
189 modest_dbus_req_handler, NULL /* user_data */);
190 if (result != OSSO_OK) {
191 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
195 /* Register hardware event dbus callback: */
196 hw_state.shutdown_ind = TRUE;
197 osso_hw_set_event_cb(osso_context, NULL, NULL, NULL);
199 /* Register osso auto-save callbacks: */
200 result = osso_application_set_autosave_cb (osso_context,
201 modest_on_osso_application_autosave, NULL /* user_data */);
202 if (result != OSSO_OK) {
203 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
208 /* Make sure that the update interval is changed whenever its gconf key
210 /* CAUTION: we're not using here the
211 modest_conf_listen_to_namespace because we know that there
212 are other parts of Modest listening for this namespace, so
213 we'll receive the notifications anyway. We basically do not
214 use it because there is no easy way to do the
215 modest_conf_forget_namespace */
216 ModestConf *conf = modest_runtime_get_conf ();
217 g_signal_connect (G_OBJECT(conf),
219 G_CALLBACK (on_modest_conf_update_interval_changed),
222 /* only force the setting of the default interval, if there are actually
224 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
226 /* Get the initial update interval from gconf: */
227 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
228 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
229 modest_account_mgr_free_account_names (acc_names);
233 #ifdef MODEST_HAVE_ABOOK
234 /* initialize the addressbook */
235 if (!osso_abook_init (&argc, &argv, osso_context)) {
236 g_printerr ("modest: failed to initialized addressbook\n");
239 #endif /*MODEST_HAVE_ABOOK*/
245 modest_platform_uninit (void)
247 osso_context_t *osso_context =
248 modest_maemo_utils_get_osso_context ();
250 osso_deinitialize (osso_context);
259 modest_platform_get_new_device (void)
261 return TNY_DEVICE (tny_maemo_conic_device_new ());
265 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
266 gchar **effective_mime_type)
268 GString *mime_str = NULL;
269 gchar *icon_name = NULL;
270 gchar **icons, **cursor;
272 if (!mime_type || g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0)
273 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
275 mime_str = g_string_new (mime_type);
276 g_string_ascii_down (mime_str);
279 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
281 for (cursor = icons; cursor; ++cursor) {
282 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
283 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
284 icon_name = g_strdup ("qgn_list_messagin");
286 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
287 icon_name = g_strdup (*cursor);
293 if (effective_mime_type)
294 *effective_mime_type = g_string_free (mime_str, FALSE);
296 g_string_free (mime_str, TRUE);
303 checked_hildon_uri_open (const gchar *uri, HildonURIAction *action)
308 g_return_val_if_fail (uri, FALSE);
310 result = hildon_uri_open (uri, action, &err);
312 g_printerr ("modest: hildon_uri_open ('%s', %p) failed: %s",
313 uri, action, err && err->message ? err->message : "unknown error");
323 modest_platform_activate_uri (const gchar *uri)
325 HildonURIAction *action;
326 gboolean result = FALSE;
327 GSList *actions, *iter = NULL;
329 g_return_val_if_fail (uri, FALSE);
333 /* don't try to activate file: uri's -- they might confuse the user,
334 * and/or might have security implications */
335 if (!g_str_has_prefix (uri, "file:")) {
337 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
339 for (iter = actions; iter; iter = g_slist_next (iter)) {
340 action = (HildonURIAction*) iter->data;
341 if (action && strcmp (hildon_uri_action_get_service (action),
342 "com.nokia.modest") == 0) {
343 result = checked_hildon_uri_open (uri, action);
348 /* if we could not open it with email, try something else */
350 result = checked_hildon_uri_open (uri, NULL);
354 ModestWindow *parent =
355 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
356 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
357 _("mcen_ib_unsupported_link"));
358 g_warning ("%s: cannot open uri '%s'", __FUNCTION__,uri);
365 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
369 gchar *uri_path = NULL;
371 uri_path = gnome_vfs_get_uri_from_local_path (path);
372 con = osso_get_dbus_connection (modest_maemo_utils_get_osso_context());
375 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
377 result = hildon_mime_open_file (con, uri_path);
379 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"), FALSE);
387 } ModestPlatformPopupInfo;
390 delete_uri_popup (GtkWidget *menu,
394 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
396 g_free (popup_info->uri);
397 hildon_uri_free_actions (popup_info->actions);
403 activate_uri_popup_item (GtkMenuItem *menu_item,
407 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
408 const gchar* action_name;
410 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
412 g_printerr ("modest: no action name defined\n");
416 /* special handling for the copy menu item -- copy the uri to the clipboard */
417 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
418 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
419 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
420 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
422 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
423 action_name += strlen ("mailto:");
425 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
426 modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
427 return; /* we're done */
430 /* now, the real uri-actions... */
431 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
432 HildonURIAction *action = (HildonURIAction *) node->data;
433 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
434 if (!checked_hildon_uri_open (popup_info->uri, action)) {
435 ModestWindow *parent =
436 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
437 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
438 _("mcen_ib_unsupported_link"));
446 modest_platform_show_uri_popup (const gchar *uri)
448 GSList *actions_list;
453 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
456 GtkWidget *menu = gtk_menu_new ();
457 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
459 /* don't add actions for file: uri's -- they might confuse the user,
460 * and/or might have security implications
461 * we still allow to copy the url though
463 if (!g_str_has_prefix (uri, "file:")) {
466 popup_info->actions = actions_list;
467 popup_info->uri = g_strdup (uri);
469 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
470 GtkWidget *menu_item;
471 const gchar *action_name;
472 const gchar *translation_domain;
473 HildonURIAction *action = (HildonURIAction *) node->data;
474 action_name = hildon_uri_action_get_name (action);
475 translation_domain = hildon_uri_action_get_translation_domain (action);
476 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
477 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
478 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
481 if (hildon_uri_is_default_action (action, NULL)) {
482 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
484 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
486 gtk_widget_show (menu_item);
491 /* and what to do when the link is deleted */
492 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
493 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
496 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
504 modest_platform_get_icon (const gchar *name, guint icon_size)
507 GdkPixbuf* pixbuf = NULL;
508 GtkIconTheme *current_theme = NULL;
510 g_return_val_if_fail (name, NULL);
512 /* strlen == 0 is not really an error; it just
513 * means the icon is not available
515 if (!name || strlen(name) == 0)
518 current_theme = gtk_icon_theme_get_default ();
519 pixbuf = gtk_icon_theme_load_icon (current_theme, name, icon_size,
520 GTK_ICON_LOOKUP_NO_SVG,
523 g_printerr ("modest: error loading theme icon '%s': %s\n",
531 modest_platform_get_app_name (void)
533 return _("mcen_ap_name");
537 entry_insert_text (GtkEditable *editable,
546 chars = gtk_editable_get_chars (editable, 0, -1);
547 chars_length = g_utf8_strlen (chars, -1);
550 /* Show WID-INF036 */
551 if (chars_length >= 20) {
552 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
553 _CS("ckdg_ib_maximum_characters_reached"));
555 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
559 tmp = g_strndup (folder_name_forbidden_chars,
560 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
561 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
562 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
567 /* Write the text in the entry if it's valid */
568 g_signal_handlers_block_by_func (editable,
569 (gpointer) entry_insert_text, data);
570 gtk_editable_insert_text (editable, text, length, position);
571 g_signal_handlers_unblock_by_func (editable,
572 (gpointer) entry_insert_text, data);
575 /* Do not allow further processing */
576 g_signal_stop_emission_by_name (editable, "insert_text");
580 entry_changed (GtkEditable *editable,
584 GtkWidget *ok_button;
587 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
588 ok_button = GTK_WIDGET (buttons->data);
590 chars = gtk_editable_get_chars (editable, 0, -1);
591 g_return_if_fail (chars != NULL);
594 if (g_utf8_strlen (chars,-1) >= 20)
595 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
596 _CS("ckdg_ib_maximum_characters_reached"));
598 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
601 g_list_free (buttons);
608 on_response (GtkDialog *dialog,
612 GtkWidget *entry, *picker;
613 TnyFolderStore *parent;
614 const gchar *new_name;
617 if (response != GTK_RESPONSE_ACCEPT)
621 entry = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY);
622 picker = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER);
624 parent = TNY_FOLDER_STORE (user_data);
625 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
628 if (picker != NULL) {
630 parent = g_object_get_data (G_OBJECT (picker), FOLDER_PICKER_CURRENT_FOLDER);
633 /* Look for another folder with the same name */
634 if (modest_tny_folder_has_subfolder_with_name (parent,
641 if (TNY_IS_ACCOUNT (parent) &&
642 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
643 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
652 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
653 NULL, _CS("ckdg_ib_folder_already_exists"));
654 /* Select the text */
655 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
656 gtk_widget_grab_focus (entry);
657 /* Do not close the dialog */
658 g_signal_stop_emission_by_name (dialog, "response");
663 typedef struct _FolderChooserData {
664 TnyFolderStore *store;
669 folder_chooser_activated (ModestFolderView *folder_view,
670 TnyFolderStore *folder,
671 FolderChooserData *userdata)
673 userdata->store = folder;
674 gtk_dialog_response (GTK_DIALOG (userdata->dialog), GTK_RESPONSE_OK);
677 static TnyFolderStore *
678 folder_chooser_dialog_run (ModestFolderView *original)
680 GtkWidget *folder_view;
681 FolderChooserData userdata = {NULL, NULL};
683 const gchar *visible_id = NULL;
685 userdata.dialog = hildon_dialog_new ();
686 pannable = hildon_pannable_area_new ();
687 folder_view = modest_platform_create_folder_view (NULL);
688 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
689 MODEST_FOLDER_VIEW_FILTER_CAN_HAVE_FOLDERS);
691 modest_folder_view_copy_model (MODEST_FOLDER_VIEW (original),
692 MODEST_FOLDER_VIEW (folder_view));
695 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(original));
696 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view),
699 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (userdata.dialog)->vbox), pannable);
700 gtk_container_add (GTK_CONTAINER (pannable), folder_view);
701 gtk_widget_set_size_request (pannable, -1, 320);
703 gtk_widget_show (folder_view);
704 gtk_widget_show (pannable);
705 gtk_widget_show (userdata.dialog);
706 g_signal_connect (G_OBJECT (folder_view), "folder-activated",
707 G_CALLBACK (folder_chooser_activated),
708 (gpointer) &userdata);
710 gtk_dialog_run (GTK_DIALOG (userdata.dialog));
711 gtk_widget_destroy (userdata.dialog);
713 return userdata.store;
717 folder_store_get_display_name (TnyFolderStore *store)
719 if (TNY_IS_ACCOUNT (store)) {
720 return g_strdup (tny_account_get_name (TNY_ACCOUNT (store)));
723 TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
725 fname = g_strdup (tny_folder_get_name (TNY_FOLDER (store)));
726 type = tny_folder_get_folder_type (TNY_FOLDER (store));
727 if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)) ||
728 modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
729 type = modest_tny_folder_get_local_or_mmc_folder_type (TNY_FOLDER (store));
730 if (type != TNY_FOLDER_TYPE_UNKNOWN) {
732 fname = g_strdup (modest_local_folder_info_get_type_display_name (type));
735 /* Sometimes an special folder is reported by the server as
736 NORMAL, like some versions of Dovecot */
737 if (type == TNY_FOLDER_TYPE_NORMAL ||
738 type == TNY_FOLDER_TYPE_UNKNOWN) {
739 type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
743 if (type == TNY_FOLDER_TYPE_INBOX) {
745 fname = g_strdup (_("mcen_me_folder_inbox"));
752 folder_picker_set_store (GtkButton *button, TnyFolderStore *store)
757 g_object_set_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER, NULL);
759 g_object_ref (store);
760 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
761 store, (GDestroyNotify) g_object_unref);
762 name = folder_store_get_display_name (store);
763 hildon_button_set_value (HILDON_BUTTON (button), name);
769 folder_picker_clicked (GtkButton *button,
770 ModestFolderView *folder_view)
772 TnyFolderStore *store;
774 store = folder_chooser_dialog_run (folder_view);
776 folder_picker_set_store (GTK_BUTTON (button), store);
781 folder_picker_new (ModestFolderView *folder_view, TnyFolderStore *suggested)
786 button = hildon_button_new (MODEST_EDITABLE_SIZE,
787 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
788 pixbuf = modest_platform_get_icon (MODEST_FOLDER_ICON_NORMAL,
789 MODEST_ICON_SIZE_SMALL);
791 hildon_button_set_image (HILDON_BUTTON (button),
792 gtk_image_new_from_pixbuf (pixbuf));
793 hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 1.0);
796 folder_picker_set_store (GTK_BUTTON (button), suggested);
799 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (folder_picker_clicked), folder_view);
806 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
807 TnyFolderStore *suggested_parent,
808 const gchar *dialog_title,
809 const gchar *label_text,
810 const gchar *suggested_name,
812 gboolean show_parent,
814 TnyFolderStore **parent)
816 GtkWidget *accept_btn = NULL;
817 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
818 GtkWidget *account_picker = NULL;
819 GList *buttons = NULL;
821 GtkSizeGroup *sizegroup;
822 ModestFolderView *folder_view;
823 ModestWindow *folder_window;
824 ModestHildon2WindowMgr *window_mgr;
826 window_mgr = (ModestHildon2WindowMgr *) modest_runtime_get_window_mgr ();
827 folder_window = modest_hildon2_window_mgr_get_folder_window (window_mgr);
828 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
830 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
832 /* Ask the user for the folder name */
833 dialog = gtk_dialog_new_with_buttons (dialog_title,
835 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
836 _FM("ckdg_bd_new_folder_dialog_ok"),
840 /* Add accept button (with unsensitive handler) */
841 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
842 accept_btn = GTK_WIDGET (buttons->data);
844 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
847 label_entry = gtk_label_new (label_text);
848 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
849 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
851 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
852 gtk_size_group_add_widget (sizegroup, label_entry);
855 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
857 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
858 gtk_entry_set_width_chars (GTK_ENTRY (entry),
859 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
860 g_utf8_strlen (_("mcen_ia_default_folder_name"), -1)));
861 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
866 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
868 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
869 gtk_size_group_add_widget (sizegroup, label_location);
871 account_picker = folder_picker_new (folder_view, suggested_parent);
874 g_object_unref (sizegroup);
876 /* Connect to the response method to avoid closing the dialog
877 when an invalid name is selected*/
878 g_signal_connect (dialog,
880 G_CALLBACK (on_response),
884 /* Track entry changes */
885 g_signal_connect (entry,
887 G_CALLBACK (entry_insert_text),
889 g_signal_connect (entry,
891 G_CALLBACK (entry_changed),
896 /* Some locales like pt_BR need this to get the full window
898 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
900 /* Create the hbox */
902 hbox = gtk_hbox_new (FALSE, 12);
903 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
904 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
906 /* Add hbox to dialog */
907 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
908 hbox, FALSE, FALSE, 0);
909 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
913 hbox = gtk_hbox_new (FALSE, 12);
914 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
915 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
917 /* Add hbox to dialog */
918 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
919 hbox, FALSE, FALSE, 0);
920 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
922 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
923 GTK_WINDOW (dialog), parent_window);
924 gtk_widget_show_all (GTK_WIDGET(dialog));
926 result = gtk_dialog_run (GTK_DIALOG(dialog));
927 if (result == GTK_RESPONSE_ACCEPT) {
929 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
931 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
933 g_object_ref (*parent);
937 gtk_widget_destroy (dialog);
939 while (gtk_events_pending ())
940 gtk_main_iteration ();
946 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
947 TnyFolderStore *suggested_folder,
948 gchar *suggested_name,
950 TnyFolderStore **parent_folder)
952 gchar *real_suggested_name = NULL, *tmp = NULL;
954 ModestTnyAccountStore *acc_store;
957 if(suggested_name == NULL)
959 const gchar *default_name = _("mcen_ia_default_folder_name");
963 for(i = 0; i < 100; ++ i) {
964 gboolean exists = FALSE;
966 sprintf(num_str, "%.2u", i);
969 real_suggested_name = g_strdup (default_name);
971 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
973 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
980 g_free (real_suggested_name);
983 /* Didn't find a free number */
985 real_suggested_name = g_strdup (default_name);
987 real_suggested_name = suggested_name;
990 /* In hildon 2.2 we always suggest the archive folder as parent */
991 acc_store = modest_runtime_get_account_store ();
992 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
994 suggested_folder = (TnyFolderStore *)
995 modest_tny_account_get_special_folder (account,
996 TNY_FOLDER_TYPE_ARCHIVE);
997 g_object_unref (account);
1001 /* If there is not archive folder then fallback to local folders account */
1002 if (!suggested_folder)
1003 suggested_folder = (TnyFolderStore *)
1004 modest_tny_account_store_get_local_folders_account (acc_store);
1006 tmp = g_strconcat (_("mcen_fi_new_folder_name"), ":", NULL);
1007 result = modest_platform_run_folder_common_dialog (parent_window,
1009 _("mcen_ti_new_folder"),
1011 real_suggested_name,
1018 if (suggested_name == NULL)
1019 g_free(real_suggested_name);
1025 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1026 TnyFolderStore *parent_folder,
1027 const gchar *suggested_name,
1028 gchar **folder_name)
1030 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1032 return modest_platform_run_folder_common_dialog (parent_window,
1034 _HL("ckdg_ti_rename_folder"),
1035 _HL("ckdg_fi_rename_name"),
1046 on_destroy_dialog (GtkWidget *dialog)
1048 /* This could happen when the dialogs get programatically
1049 hidden or destroyed (for example when closing the
1050 application while a dialog is being shown) */
1051 if (!GTK_IS_WIDGET (dialog))
1054 gtk_widget_destroy (dialog);
1056 if (gtk_events_pending ())
1057 gtk_main_iteration ();
1061 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1062 const gchar *message)
1067 dialog = hildon_note_new_confirmation (parent_window, message);
1068 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1069 GTK_WINDOW (dialog), parent_window);
1071 response = gtk_dialog_run (GTK_DIALOG (dialog));
1073 on_destroy_dialog (dialog);
1079 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1080 const gchar *message,
1081 const gchar *button_accept,
1082 const gchar *button_cancel)
1087 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1088 button_accept, GTK_RESPONSE_ACCEPT,
1089 button_cancel, GTK_RESPONSE_CANCEL,
1092 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1093 GTK_WINDOW (dialog), parent_window);
1095 response = gtk_dialog_run (GTK_DIALOG (dialog));
1097 on_destroy_dialog (dialog);
1103 modest_platform_run_information_dialog (GtkWindow *parent_window,
1104 const gchar *message,
1109 note = hildon_note_new_information (parent_window, message);
1111 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1112 GTK_WINDOW (note), parent_window);
1115 gtk_dialog_run (GTK_DIALOG (note));
1117 on_destroy_dialog (note);
1119 g_signal_connect_swapped (note,
1121 G_CALLBACK (on_destroy_dialog),
1124 gtk_widget_show_all (note);
1128 typedef struct _ConnectAndWaitData {
1130 GMainLoop *wait_loop;
1131 gboolean has_callback;
1133 } ConnectAndWaitData;
1137 quit_wait_loop (TnyAccount *account,
1138 ConnectAndWaitData *data)
1140 /* Set the has_callback to TRUE (means that the callback was
1141 executed and wake up every code waiting for cond to be
1143 g_mutex_lock (data->mutex);
1144 data->has_callback = TRUE;
1145 if (data->wait_loop)
1146 g_main_loop_quit (data->wait_loop);
1147 g_mutex_unlock (data->mutex);
1151 on_connection_status_changed (TnyAccount *account,
1152 TnyConnectionStatus status,
1155 TnyConnectionStatus conn_status;
1156 ConnectAndWaitData *data;
1158 /* Ignore if reconnecting or disconnected */
1159 conn_status = tny_account_get_connection_status (account);
1160 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1161 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1164 /* Remove the handler */
1165 data = (ConnectAndWaitData *) user_data;
1166 g_signal_handler_disconnect (account, data->handler);
1168 /* Quit from wait loop */
1169 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1173 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1178 /* Quit from wait loop */
1179 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1183 modest_platform_connect_and_wait (GtkWindow *parent_window,
1184 TnyAccount *account)
1186 ConnectAndWaitData *data = NULL;
1187 gboolean device_online;
1189 TnyConnectionStatus conn_status;
1190 gboolean user_requested;
1192 device = modest_runtime_get_device();
1193 device_online = tny_device_is_online (device);
1195 /* Whether the connection is user requested or automatically
1196 requested, for example via D-Bus */
1197 user_requested = (parent_window) ? TRUE : FALSE;
1199 /* If there is no account check only the device status */
1204 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1205 NULL, user_requested);
1208 /* Return if the account is already connected */
1209 conn_status = tny_account_get_connection_status (account);
1210 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1213 /* Create the helper */
1214 data = g_slice_new0 (ConnectAndWaitData);
1215 data->mutex = g_mutex_new ();
1216 data->has_callback = FALSE;
1218 /* Connect the device */
1219 if (!device_online) {
1220 /* Track account connection status changes */
1221 data->handler = g_signal_connect (account, "connection-status-changed",
1222 G_CALLBACK (on_connection_status_changed),
1224 /* Try to connect the device */
1225 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1226 NULL, user_requested);
1228 /* If the device connection failed then exit */
1229 if (!device_online && data->handler)
1232 /* Force a reconnection of the account */
1233 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1234 on_tny_camel_account_set_online_cb, data);
1237 /* Wait until the callback is executed */
1238 g_mutex_lock (data->mutex);
1239 if (!data->has_callback) {
1240 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1241 gdk_threads_leave ();
1242 g_mutex_unlock (data->mutex);
1243 g_main_loop_run (data->wait_loop);
1244 g_mutex_lock (data->mutex);
1245 gdk_threads_enter ();
1247 g_mutex_unlock (data->mutex);
1251 if (g_signal_handler_is_connected (account, data->handler))
1252 g_signal_handler_disconnect (account, data->handler);
1253 g_mutex_free (data->mutex);
1254 g_main_loop_unref (data->wait_loop);
1255 g_slice_free (ConnectAndWaitData, data);
1258 conn_status = tny_account_get_connection_status (account);
1259 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1263 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1265 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1266 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1267 /* This must be a maildir account, which does not require a connection: */
1272 return modest_platform_connect_and_wait (parent_window, account);
1276 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1279 return TRUE; /* Maybe it is something local. */
1281 gboolean result = TRUE;
1282 if (TNY_IS_FOLDER (folder_store)) {
1283 /* Get the folder's parent account: */
1284 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1285 if (account != NULL) {
1286 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1287 g_object_unref (account);
1289 } else if (TNY_IS_ACCOUNT (folder_store)) {
1290 /* Use the folder store as an account: */
1291 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1298 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1302 dialog = modest_hildon2_sort_dialog_new (parent_window);
1309 modest_platform_set_update_interval (guint minutes)
1311 #ifdef MODEST_HAVE_LIBALARM
1313 ModestConf *conf = modest_runtime_get_conf ();
1317 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1319 /* Delete any existing alarm,
1320 * because we will replace it: */
1322 if (alarmd_event_del(alarm_cookie) != 0)
1323 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1325 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1328 /* 0 means no updates: */
1333 /* Register alarm: */
1335 /* Set the interval in alarm_event_t structure: */
1336 alarm_event_t *event = alarm_event_create ();
1337 alarm_event_add_actions (event, 1);
1338 alarm_action_t *action = alarm_event_get_action (event, 0);
1339 alarm_event_set_alarm_appid (event, MODEST_ALARMD_APPID);
1340 event->alarm_time = minutes * 60; /* seconds */
1342 /* Set recurrence every few minutes: */
1343 event->recur_secs = minutes*60;
1344 event->recur_count = -1; /* Means infinite */
1346 /* Specify what should happen when the alarm happens:
1347 * It should call this D-Bus method: */
1349 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1350 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1351 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1352 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1353 action->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1355 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1356 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1357 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1358 * This is why we want to use the Alarm API instead of just g_timeout_add().
1359 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1360 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1362 event->flags = ALARM_EVENT_CONNECTED;
1364 alarm_cookie = alarmd_event_add (event);
1367 alarm_event_delete (event);
1369 /* Store the alarm ID in GConf, so we can remove it later:
1370 * This is apparently valid between application instances. */
1371 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1373 if (!alarm_cookie) {
1375 g_debug ("Error setting alarm event. \n");
1379 #endif /* MODEST_HAVE_LIBALARM */
1384 modest_platform_push_email_notification(void)
1386 gboolean screen_on, app_in_foreground;
1388 /* Get the window status */
1389 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1391 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1393 /* If the screen is on and the app is in the
1394 foreground we don't show anything */
1395 if (!(screen_on && app_in_foreground)) {
1397 _modest_platform_play_email_tone ();
1399 /* Activate LED. This must be deactivated by
1400 modest_platform_remove_new_mail_notifications */
1401 #ifdef MODEST_HAVE_MCE
1402 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1406 MCE_ACTIVATE_LED_PATTERN,
1408 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1415 modest_platform_on_new_headers_received (TnyList *header_list,
1416 gboolean show_visual)
1418 g_return_if_fail (TNY_IS_LIST(header_list));
1420 if (tny_list_get_length(header_list) == 0) {
1421 g_warning ("%s: header list is empty", __FUNCTION__);
1426 modest_platform_push_email_notification ();
1427 /* We do a return here to avoid indentation with an else */
1431 #ifdef MODEST_HAVE_HILDON_NOTIFY
1432 HildonNotification *notification;
1434 GSList *notifications_list = NULL;
1436 /* Get previous notifications ids */
1437 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1438 MODEST_CONF_NOTIFICATION_IDS,
1439 MODEST_CONF_VALUE_INT, NULL);
1441 iter = tny_list_create_iterator (header_list);
1442 while (!tny_iterator_is_done (iter)) {
1443 gchar *url = NULL, *display_address = NULL, *summary = NULL;
1444 const gchar *display_date;
1445 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1446 TnyFolder *folder = tny_header_get_folder (header);
1447 gboolean first_notification = TRUE;
1450 ModestDatetimeFormatter *datetime_formatter;
1452 /* constant string, don't free */
1453 datetime_formatter = modest_datetime_formatter_new ();
1454 display_date = modest_datetime_formatter_display_datetime (datetime_formatter,
1455 tny_header_get_date_received (header));
1456 g_object_unref (datetime_formatter);
1458 display_address = tny_header_dup_from (header);
1459 /* string is changed in-place */
1460 modest_text_utils_get_display_address (display_address);
1462 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1463 str = tny_header_dup_subject (header);
1464 notification = hildon_notification_new (summary,
1466 "qgn_list_messagin",
1469 /* Create the message URL */
1470 str = tny_header_dup_uid (header);
1471 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1475 hildon_notification_add_dbus_action(notification,
1478 MODEST_DBUS_SERVICE,
1481 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1485 /* Play sound if the user wants. Show the LED
1486 pattern. Show and play just one */
1487 if (G_UNLIKELY (first_notification)) {
1488 gchar *active_profile;
1491 gint mail_volume_int;
1493 first_notification = FALSE;
1495 active_profile = profile_get_profile ();
1496 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
1497 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
1498 mail_volume_int = profile_parse_int (mail_volume);
1500 if (mail_volume_int > 0)
1501 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1502 "sound-file", mail_tone);
1504 g_free (mail_volume);
1506 g_free (active_profile);
1508 /* Set the led pattern */
1509 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1511 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1513 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1516 /* Notify. We need to do this in an idle because this function
1517 could be called from a thread */
1518 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1520 /* Save id in the list */
1521 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1522 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1523 /* We don't listen for the "closed" signal, because we
1524 don't care about if the notification was removed or
1525 not to store the list in gconf */
1527 /* Free & carry on */
1528 g_free (display_address);
1531 g_object_unref (folder);
1532 g_object_unref (header);
1533 tny_iterator_next (iter);
1535 g_object_unref (iter);
1538 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1539 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1541 g_slist_free (notifications_list);
1543 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1547 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1550 #ifdef MODEST_HAVE_MCE
1551 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1555 MCE_DEACTIVATE_LED_PATTERN,
1557 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1563 #ifdef MODEST_HAVE_HILDON_NOTIFY
1564 GSList *notif_list = NULL;
1566 /* Get previous notifications ids */
1567 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1568 MODEST_CONF_NOTIFICATION_IDS,
1569 MODEST_CONF_VALUE_INT, NULL);
1571 while (notif_list) {
1573 NotifyNotification *notif;
1575 /* Nasty HACK to remove the notifications, set the id
1576 of the existing ones and then close them */
1577 notif_id = GPOINTER_TO_INT(notif_list->data);
1578 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1579 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1581 /* Close the notification, note that some ids could be
1582 already invalid, but we don't care because it does
1584 notify_notification_close(notif, NULL);
1585 g_object_unref(notif);
1587 /* Delete the link, it's like going to the next */
1588 notif_list = g_slist_delete_link (notif_list, notif_list);
1592 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1593 notif_list, MODEST_CONF_VALUE_INT, NULL);
1595 g_slist_free (notif_list);
1597 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1603 modest_platform_get_global_settings_dialog ()
1605 return modest_hildon2_global_settings_dialog_new ();
1609 modest_platform_show_help (GtkWindow *parent_window,
1610 const gchar *help_id)
1616 modest_platform_show_search_messages (GtkWindow *parent_window)
1618 osso_return_t result = OSSO_ERROR;
1620 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1621 "osso_global_search",
1622 "search_email", NULL, DBUS_TYPE_INVALID);
1624 if (result != OSSO_OK) {
1625 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1630 modest_platform_show_addressbook (GtkWindow *parent_window)
1632 osso_return_t result = OSSO_ERROR;
1634 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1636 "top_application", NULL, DBUS_TYPE_INVALID);
1638 if (result != OSSO_OK) {
1639 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1644 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1646 GtkWidget *widget = modest_folder_view_new (query);
1648 /* Show one account by default */
1649 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1650 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1652 /* Restore settings */
1653 modest_widget_memory_restore (modest_runtime_get_conf(),
1655 MODEST_CONF_FOLDER_VIEW_KEY);
1661 banner_finish (gpointer data, GObject *object)
1663 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1664 modest_window_mgr_unregister_banner (mgr);
1665 g_object_unref (mgr);
1669 modest_platform_information_banner (GtkWidget *parent,
1670 const gchar *icon_name,
1673 GtkWidget *banner, *banner_parent = NULL;
1674 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1676 if (modest_window_mgr_get_num_windows (mgr) == 0)
1679 if (parent && GTK_IS_WINDOW (parent)) {
1680 /* If the window is the active one then show the
1681 banner on top of this window */
1682 if (gtk_window_is_active (GTK_WINDOW (parent)))
1683 banner_parent = parent;
1684 /* If the window is not the topmost but it's visible
1685 (it's minimized for example) then show the banner
1687 else if (GTK_WIDGET_VISIBLE (parent))
1688 banner_parent = NULL;
1689 /* If the window is hidden (like the main window when
1690 running in the background) then do not show
1697 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1699 modest_window_mgr_register_banner (mgr);
1701 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1705 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1706 const gchar *icon_name,
1712 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1715 banner = hildon_banner_show_information (parent, icon_name, text);
1716 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1720 modest_platform_animation_banner (GtkWidget *parent,
1721 const gchar *animation_name,
1724 GtkWidget *inf_note = NULL;
1726 g_return_val_if_fail (text != NULL, NULL);
1728 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1731 /* If the parent is not visible then do not show */
1732 if (parent && !GTK_WIDGET_VISIBLE (parent))
1735 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1743 TnyAccount *account;
1746 } CheckAccountIdleData;
1748 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1751 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1753 gboolean stop_trying = FALSE;
1754 g_return_val_if_fail (data && data->account, FALSE);
1756 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1757 tny_account_get_connection_status (data->account));
1759 if (data && data->account &&
1760 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1761 * after which the account is likely to be usable, or never likely to be usable soon: */
1762 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1764 data->is_online = TRUE;
1768 /* Give up if we have tried too many times: */
1769 if (data->count_tries >= NUMBER_OF_TRIES) {
1772 /* Wait for another timeout: */
1773 ++(data->count_tries);
1778 /* Allow the function that requested this idle callback to continue: */
1780 g_main_loop_quit (data->loop);
1783 g_object_unref (data->account);
1785 return FALSE; /* Don't call this again. */
1787 return TRUE; /* Call this timeout callback again. */
1791 /* Return TRUE immediately if the account is already online,
1792 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1793 * soon as the account is online, or FALSE if the account does
1794 * not become online in the NUMBER_OF_TRIES seconds.
1795 * This is useful when the D-Bus method was run immediately after
1796 * the application was started (when using D-Bus activation),
1797 * because the account usually takes a short time to go online.
1798 * The return value is maybe not very useful.
1801 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1805 g_return_val_if_fail (account, FALSE);
1807 if (!tny_device_is_online (modest_runtime_get_device())) {
1808 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1812 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1813 * so we avoid wait unnecessarily: */
1814 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1817 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1818 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1819 * we want to avoid. */
1820 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1823 /* This blocks on the result: */
1824 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1825 data->is_online = FALSE;
1826 data->account = account;
1827 g_object_ref (data->account);
1828 data->count_tries = 0;
1830 GMainContext *context = NULL; /* g_main_context_new (); */
1831 data->loop = g_main_loop_new (context, FALSE /* not running */);
1833 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1835 /* This main loop will run until the idle handler has stopped it: */
1836 g_main_loop_run (data->loop);
1838 g_main_loop_unref (data->loop);
1839 /* g_main_context_unref (context); */
1841 is_online = data->is_online;
1842 g_slice_free (CheckAccountIdleData, data);
1850 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1852 /* GTK_RESPONSE_HELP means we need to show the certificate */
1853 if (response_id == GTK_RESPONSE_APPLY) {
1857 /* Do not close the dialog */
1858 g_signal_stop_emission_by_name (dialog, "response");
1860 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1861 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1862 gtk_dialog_run (GTK_DIALOG(note));
1863 gtk_widget_destroy (note);
1869 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1870 const gchar *certificate)
1875 HildonWindowStack *stack;
1877 stack = hildon_window_stack_get_default ();
1878 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1881 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1886 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1889 /* We use GTK_RESPONSE_APPLY because we want the button in the
1890 middle of OK and CANCEL the same as the browser does for
1891 example. With GTK_RESPONSE_HELP the view button is aligned
1892 to the left while the other two to the right */
1893 note = hildon_note_new_confirmation_add_buttons (
1896 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1897 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1898 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1901 g_signal_connect (G_OBJECT(note), "response",
1902 G_CALLBACK(on_cert_dialog_response),
1903 (gpointer) certificate);
1905 response = gtk_dialog_run(GTK_DIALOG(note));
1907 on_destroy_dialog (note);
1910 return response == GTK_RESPONSE_OK;
1914 modest_platform_run_alert_dialog (const gchar* prompt,
1915 gboolean is_question)
1917 ModestWindow *top_win;
1918 HildonWindowStack *stack;
1920 stack = hildon_window_stack_get_default ();
1921 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1924 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1929 gboolean retval = TRUE;
1931 /* The Tinymail documentation says that we should show Yes and No buttons,
1932 * when it is a question.
1933 * Obviously, we need tinymail to use more specific error codes instead,
1934 * so we know what buttons to show. */
1935 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
1937 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1938 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
1940 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1941 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1943 on_destroy_dialog (dialog);
1945 /* Just show the error text and use the default response: */
1946 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
1954 GtkWindow *parent_window;
1955 ModestConnectedPerformer callback;
1956 TnyAccount *account;
1963 on_went_online_info_free (OnWentOnlineInfo *info)
1965 /* And if we cleanup, we DO cleanup :-) */
1968 g_object_unref (info->device);
1971 if (info->parent_window)
1972 g_object_unref (info->parent_window);
1974 g_object_unref (info->account);
1976 g_slice_free (OnWentOnlineInfo, info);
1978 /* We're done ... */
1984 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
1986 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1988 /* Now it's really time to callback to the caller. If going online didn't succeed,
1989 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
1990 * canceled will be set. Etcetera etcetera. */
1992 if (info->callback) {
1993 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
1996 /* This is our last call, we must cleanup here if we didn't yet do that */
1997 on_went_online_info_free (info);
2004 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2006 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2007 info->iap = g_strdup (iap_id);
2009 if (canceled || err || !info->account) {
2011 /* If there's a problem or if there's no account (then that's it for us, we callback
2012 * the caller's callback now. He'll have to handle err or canceled, of course.
2013 * We are not really online, as the account is not really online here ... */
2015 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2016 * this info. We don't cleanup err, Tinymail does that! */
2018 if (info->callback) {
2020 /* info->account can be NULL here, this means that the user did not
2021 * provide a nice account instance. We'll assume that the user knows
2022 * what he's doing and is happy with just the device going online.
2024 * We can't do magic, we don't know what account the user wants to
2025 * see going online. So just the device goes online, end of story */
2027 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2030 } else if (info->account) {
2032 /* If there's no problem and if we have an account, we'll put the account
2033 * online too. When done, the callback of bringing the account online
2034 * will callback the caller's callback. This is the most normal case. */
2036 info->device = TNY_DEVICE (g_object_ref (device));
2038 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2039 on_account_went_online, info);
2041 /* The on_account_went_online cb frees up the info, go look if you
2042 * don't believe me! (so we return here) */
2047 /* We cleanup if we are not bringing the account online too */
2048 on_went_online_info_free (info);
2054 modest_platform_connect_and_perform (GtkWindow *parent_window,
2056 TnyAccount *account,
2057 ModestConnectedPerformer callback,
2060 gboolean device_online;
2062 TnyConnectionStatus conn_status;
2063 OnWentOnlineInfo *info;
2065 device = modest_runtime_get_device();
2066 device_online = tny_device_is_online (device);
2068 /* If there is no account check only the device status */
2071 if (device_online) {
2073 /* We promise to instantly perform the callback, so ... */
2075 callback (FALSE, NULL, parent_window, account, user_data);
2080 info = g_slice_new0 (OnWentOnlineInfo);
2083 info->device = NULL;
2084 info->account = NULL;
2087 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2089 info->parent_window = NULL;
2090 info->user_data = user_data;
2091 info->callback = callback;
2093 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2094 force, on_conic_device_went_online,
2097 /* We'll cleanup in on_conic_device_went_online */
2100 /* The other code has no more reason to run. This is all that we can do for the
2101 * caller (he should have given us a nice and clean account instance!). We
2102 * can't do magic, we don't know what account he intends to bring online. So
2103 * we'll just bring the device online (and await his false bug report). */
2109 /* Return if the account is already connected */
2111 conn_status = tny_account_get_connection_status (account);
2112 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2114 /* We promise to instantly perform the callback, so ... */
2116 callback (FALSE, NULL, parent_window, account, user_data);
2122 /* Else, we are in a state that requires that we go online before we
2123 * call the caller's callback. */
2125 info = g_slice_new0 (OnWentOnlineInfo);
2127 info->device = NULL;
2129 info->account = TNY_ACCOUNT (g_object_ref (account));
2132 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2134 info->parent_window = NULL;
2136 /* So we'll put the callback away for later ... */
2138 info->user_data = user_data;
2139 info->callback = callback;
2141 if (!device_online) {
2143 /* If also the device is offline, then we connect both the device
2144 * and the account */
2146 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2147 force, on_conic_device_went_online,
2152 /* If the device is online, we'll just connect the account */
2154 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2155 on_account_went_online, info);
2158 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2159 * in both situations, go look if you don't believe me! */
2165 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2167 TnyFolderStore *folder_store,
2168 ModestConnectedPerformer callback,
2171 TnyAccount *account = NULL;
2173 if (!folder_store ||
2174 (TNY_IS_MERGE_FOLDER (folder_store) &&
2175 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2177 /* We promise to instantly perform the callback, so ... */
2179 GError *error = NULL;
2180 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2181 "Unable to move or not found folder");
2182 callback (FALSE, error, parent_window, NULL, user_data);
2183 g_error_free (error);
2187 } else if (TNY_IS_FOLDER (folder_store)) {
2188 /* Get the folder's parent account: */
2189 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2190 } else if (TNY_IS_ACCOUNT (folder_store)) {
2191 /* Use the folder store as an account: */
2192 account = TNY_ACCOUNT (g_object_ref (folder_store));
2195 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
2196 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2197 /* No need to connect a local account */
2199 callback (FALSE, NULL, parent_window, account, user_data);
2204 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2208 g_object_unref (account);
2212 src_account_connect_performer (gboolean canceled,
2214 GtkWindow *parent_window,
2215 TnyAccount *src_account,
2218 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2220 if (canceled || err) {
2221 /* If there was any error call the user callback */
2222 info->callback (canceled, err, parent_window, src_account, info->data);
2224 /* Connect the destination account */
2225 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2226 TNY_FOLDER_STORE (info->dst_account),
2227 info->callback, info->data);
2230 /* Free the info object */
2231 g_object_unref (info->dst_account);
2232 g_slice_free (DoubleConnectionInfo, info);
2237 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2239 TnyFolderStore *folder_store,
2240 DoubleConnectionInfo *connect_info)
2242 modest_platform_connect_if_remote_and_perform(parent_window,
2245 src_account_connect_performer,
2250 modest_platform_get_account_settings_wizard (void)
2252 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2254 return GTK_WIDGET (dialog);
2258 modest_platform_get_current_connection (void)
2260 TnyDevice *device = NULL;
2261 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2263 device = modest_runtime_get_device ();
2265 if (!tny_device_is_online (device))
2266 return MODEST_CONNECTED_VIA_ANY;
2268 #ifdef MODEST_HAVE_CONIC
2270 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2272 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2273 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2274 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2276 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2277 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2278 !strcmp (bearer_type, "WIMAX")) {
2279 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2281 retval = MODEST_CONNECTED_VIA_ANY;
2284 g_object_unref (iap);
2287 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2288 #endif /* MODEST_HAVE_CONIC */
2295 modest_platform_check_memory_low (ModestWindow *win,
2300 /* are we in low memory state? */
2301 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2303 if (win && lowmem && visuals)
2304 modest_platform_run_information_dialog (
2306 dgettext("ke-recv","memr_ib_operation_disabled"),
2310 g_debug ("%s: low memory reached. disallowing some operations",
2317 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2323 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2326 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2327 GTK_WINDOW (dialog),
2329 gtk_widget_show_all (dialog);
2331 g_signal_connect_swapped (dialog, "response",
2332 G_CALLBACK (gtk_widget_destroy),
2337 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2343 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2346 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2347 GTK_WINDOW (dialog),
2349 gtk_widget_show_all (dialog);
2351 g_signal_connect_swapped (dialog, "response",
2352 G_CALLBACK (gtk_widget_destroy),
2357 modest_platform_get_osso_context (void)
2359 return modest_maemo_utils_get_osso_context ();
2363 _modest_platform_play_email_tone (void)
2365 gchar *active_profile;
2368 gint mail_volume_int;
2370 ca_context *ca_con = NULL;
2371 ca_proplist *pl = NULL;
2373 active_profile = profile_get_profile ();
2374 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2375 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2376 mail_volume_int = profile_parse_int (mail_volume);
2378 if (mail_volume_int > 0) {
2380 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2381 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2385 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2386 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2387 ca_context_destroy(ca_con);
2391 ca_proplist_create(&pl);
2392 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2393 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2395 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2396 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2398 ca_proplist_destroy(pl);
2399 ca_context_destroy(ca_con);
2402 g_free (mail_volume);
2404 g_free (active_profile);
2408 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2410 GtkTreeViewColumn *column,
2413 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_OK);
2417 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2418 GtkWidget **folder_view)
2420 GtkWidget *dialog, *folder_view_container;
2422 /* Create dialog. We cannot use a touch selector because we
2423 need to use here the folder view widget directly */
2424 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2425 GTK_WINDOW (parent_window),
2426 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2427 GTK_DIALOG_DESTROY_WITH_PARENT,
2428 _("mcen_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2431 /* Create folder view */
2432 *folder_view = modest_platform_create_folder_view (NULL);
2434 /* Simulate the behaviour of a HildonPickerDialog by emitting
2435 a response when a folder is selected */
2436 g_signal_connect (*folder_view, "row-activated",
2437 G_CALLBACK (on_move_to_dialog_folder_activated),
2440 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2441 (TnyAccountStore *) modest_runtime_get_account_store ());
2443 /* Create pannable and add it to the dialog */
2444 folder_view_container = hildon_pannable_area_new ();
2445 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), folder_view_container);
2446 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2448 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2450 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2451 gtk_widget_show (folder_view_container);
2452 gtk_widget_show (*folder_view);
2458 modest_platform_get_list_to_move (ModestWindow *window)
2460 TnyList *list = NULL;
2462 if (MODEST_IS_HEADER_WINDOW (window)) {
2463 ModestHeaderView *header_view;
2465 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2466 list = modest_header_view_get_selected_headers (header_view);
2467 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2468 ModestFolderView *folder_view;
2469 TnyFolderStore *selected_folder;
2471 list = TNY_LIST (tny_simple_list_new ());
2472 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2473 selected_folder = modest_folder_view_get_selected (folder_view);
2474 if (selected_folder) {
2475 tny_list_prepend (list, G_OBJECT (selected_folder));
2476 g_object_unref (selected_folder);
2479 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2482 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2484 list = TNY_LIST (tny_simple_list_new ());
2485 tny_list_prepend (list, G_OBJECT (header));
2486 g_object_unref (header);
2489 g_return_val_if_reached (NULL);