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 = TRUE, app_in_foreground;
1391 /* Get the window status */
1392 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1394 /* If the screen is on and the app is in the
1395 foreground we don't show anything */
1396 if (!(screen_on && app_in_foreground)) {
1398 _modest_platform_play_email_tone ();
1400 /* Activate LED. This must be deactivated by
1401 modest_platform_remove_new_mail_notifications */
1402 #ifdef MODEST_HAVE_MCE
1403 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1407 MCE_ACTIVATE_LED_PATTERN,
1409 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1416 modest_platform_on_new_headers_received (TnyList *header_list,
1417 gboolean show_visual)
1419 g_return_if_fail (TNY_IS_LIST(header_list));
1421 if (tny_list_get_length(header_list) == 0) {
1422 g_warning ("%s: header list is empty", __FUNCTION__);
1427 modest_platform_push_email_notification ();
1428 /* We do a return here to avoid indentation with an else */
1432 #ifdef MODEST_HAVE_HILDON_NOTIFY
1433 HildonNotification *notification;
1435 GSList *notifications_list = NULL;
1437 /* Get previous notifications ids */
1438 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1439 MODEST_CONF_NOTIFICATION_IDS,
1440 MODEST_CONF_VALUE_INT, NULL);
1442 iter = tny_list_create_iterator (header_list);
1443 while (!tny_iterator_is_done (iter)) {
1444 gchar *url = NULL, *display_address = NULL, *summary = NULL;
1445 const gchar *display_date;
1446 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1447 TnyFolder *folder = tny_header_get_folder (header);
1448 gboolean first_notification = TRUE;
1451 ModestDatetimeFormatter *datetime_formatter;
1453 /* constant string, don't free */
1454 datetime_formatter = modest_datetime_formatter_new ();
1455 display_date = modest_datetime_formatter_display_datetime (datetime_formatter,
1456 tny_header_get_date_received (header));
1457 g_object_unref (datetime_formatter);
1459 display_address = tny_header_dup_from (header);
1460 /* string is changed in-place */
1461 modest_text_utils_get_display_address (display_address);
1463 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1464 str = tny_header_dup_subject (header);
1465 notification = hildon_notification_new (summary,
1467 "qgn_list_messagin",
1470 /* Create the message URL */
1471 str = tny_header_dup_uid (header);
1472 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1476 hildon_notification_add_dbus_action(notification,
1479 MODEST_DBUS_SERVICE,
1482 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1486 /* Play sound if the user wants. Show the LED
1487 pattern. Show and play just one */
1488 if (G_UNLIKELY (first_notification)) {
1489 gchar *active_profile;
1492 gint mail_volume_int;
1494 first_notification = FALSE;
1496 active_profile = profile_get_profile ();
1497 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
1498 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
1499 mail_volume_int = profile_parse_int (mail_volume);
1501 if (mail_volume_int > 0)
1502 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1503 "sound-file", mail_tone);
1505 g_free (mail_volume);
1507 g_free (active_profile);
1509 /* Set the led pattern */
1510 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1512 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1514 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1517 /* Notify. We need to do this in an idle because this function
1518 could be called from a thread */
1519 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1521 /* Save id in the list */
1522 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1523 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1524 /* We don't listen for the "closed" signal, because we
1525 don't care about if the notification was removed or
1526 not to store the list in gconf */
1528 /* Free & carry on */
1529 g_free (display_address);
1532 g_object_unref (folder);
1533 g_object_unref (header);
1534 tny_iterator_next (iter);
1536 g_object_unref (iter);
1539 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1540 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1542 g_slist_free (notifications_list);
1544 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1548 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1551 #ifdef MODEST_HAVE_MCE
1552 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1556 MCE_DEACTIVATE_LED_PATTERN,
1558 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1564 #ifdef MODEST_HAVE_HILDON_NOTIFY
1565 GSList *notif_list = NULL;
1567 /* Get previous notifications ids */
1568 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1569 MODEST_CONF_NOTIFICATION_IDS,
1570 MODEST_CONF_VALUE_INT, NULL);
1572 while (notif_list) {
1574 NotifyNotification *notif;
1576 /* Nasty HACK to remove the notifications, set the id
1577 of the existing ones and then close them */
1578 notif_id = GPOINTER_TO_INT(notif_list->data);
1579 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1580 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1582 /* Close the notification, note that some ids could be
1583 already invalid, but we don't care because it does
1585 notify_notification_close(notif, NULL);
1586 g_object_unref(notif);
1588 /* Delete the link, it's like going to the next */
1589 notif_list = g_slist_delete_link (notif_list, notif_list);
1593 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1594 notif_list, MODEST_CONF_VALUE_INT, NULL);
1596 g_slist_free (notif_list);
1598 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1604 modest_platform_get_global_settings_dialog ()
1606 return modest_hildon2_global_settings_dialog_new ();
1610 modest_platform_show_help (GtkWindow *parent_window,
1611 const gchar *help_id)
1617 modest_platform_show_search_messages (GtkWindow *parent_window)
1619 osso_return_t result = OSSO_ERROR;
1621 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1622 "osso_global_search",
1623 "search_email", NULL, DBUS_TYPE_INVALID);
1625 if (result != OSSO_OK) {
1626 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1631 modest_platform_show_addressbook (GtkWindow *parent_window)
1633 osso_return_t result = OSSO_ERROR;
1635 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1637 "top_application", NULL, DBUS_TYPE_INVALID);
1639 if (result != OSSO_OK) {
1640 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1645 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1647 GtkWidget *widget = modest_folder_view_new (query);
1649 /* Show one account by default */
1650 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1651 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1653 /* Restore settings */
1654 modest_widget_memory_restore (modest_runtime_get_conf(),
1656 MODEST_CONF_FOLDER_VIEW_KEY);
1662 banner_finish (gpointer data, GObject *object)
1664 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1665 modest_window_mgr_unregister_banner (mgr);
1666 g_object_unref (mgr);
1670 modest_platform_information_banner (GtkWidget *parent,
1671 const gchar *icon_name,
1674 GtkWidget *banner, *banner_parent = NULL;
1675 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1677 if (modest_window_mgr_get_num_windows (mgr) == 0)
1680 if (parent && GTK_IS_WINDOW (parent)) {
1681 /* If the window is the active one then show the
1682 banner on top of this window */
1683 if (gtk_window_is_active (GTK_WINDOW (parent)))
1684 banner_parent = parent;
1685 /* If the window is not the topmost but it's visible
1686 (it's minimized for example) then show the banner
1688 else if (GTK_WIDGET_VISIBLE (parent))
1689 banner_parent = NULL;
1690 /* If the window is hidden (like the main window when
1691 running in the background) then do not show
1698 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1700 modest_window_mgr_register_banner (mgr);
1702 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1706 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1707 const gchar *icon_name,
1713 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1716 banner = hildon_banner_show_information (parent, icon_name, text);
1717 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1721 modest_platform_animation_banner (GtkWidget *parent,
1722 const gchar *animation_name,
1725 GtkWidget *inf_note = NULL;
1727 g_return_val_if_fail (text != NULL, NULL);
1729 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1732 /* If the parent is not visible then do not show */
1733 if (parent && !GTK_WIDGET_VISIBLE (parent))
1736 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1744 TnyAccount *account;
1747 } CheckAccountIdleData;
1749 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1752 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1754 gboolean stop_trying = FALSE;
1755 g_return_val_if_fail (data && data->account, FALSE);
1757 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1758 tny_account_get_connection_status (data->account));
1760 if (data && data->account &&
1761 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1762 * after which the account is likely to be usable, or never likely to be usable soon: */
1763 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1765 data->is_online = TRUE;
1769 /* Give up if we have tried too many times: */
1770 if (data->count_tries >= NUMBER_OF_TRIES) {
1773 /* Wait for another timeout: */
1774 ++(data->count_tries);
1779 /* Allow the function that requested this idle callback to continue: */
1781 g_main_loop_quit (data->loop);
1784 g_object_unref (data->account);
1786 return FALSE; /* Don't call this again. */
1788 return TRUE; /* Call this timeout callback again. */
1792 /* Return TRUE immediately if the account is already online,
1793 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1794 * soon as the account is online, or FALSE if the account does
1795 * not become online in the NUMBER_OF_TRIES seconds.
1796 * This is useful when the D-Bus method was run immediately after
1797 * the application was started (when using D-Bus activation),
1798 * because the account usually takes a short time to go online.
1799 * The return value is maybe not very useful.
1802 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1806 g_return_val_if_fail (account, FALSE);
1808 if (!tny_device_is_online (modest_runtime_get_device())) {
1809 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1813 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1814 * so we avoid wait unnecessarily: */
1815 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1818 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1819 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1820 * we want to avoid. */
1821 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1824 /* This blocks on the result: */
1825 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1826 data->is_online = FALSE;
1827 data->account = account;
1828 g_object_ref (data->account);
1829 data->count_tries = 0;
1831 GMainContext *context = NULL; /* g_main_context_new (); */
1832 data->loop = g_main_loop_new (context, FALSE /* not running */);
1834 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1836 /* This main loop will run until the idle handler has stopped it: */
1837 g_main_loop_run (data->loop);
1839 g_main_loop_unref (data->loop);
1840 /* g_main_context_unref (context); */
1842 is_online = data->is_online;
1843 g_slice_free (CheckAccountIdleData, data);
1851 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1853 /* GTK_RESPONSE_HELP means we need to show the certificate */
1854 if (response_id == GTK_RESPONSE_APPLY) {
1858 /* Do not close the dialog */
1859 g_signal_stop_emission_by_name (dialog, "response");
1861 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1862 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1863 gtk_dialog_run (GTK_DIALOG(note));
1864 gtk_widget_destroy (note);
1870 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1871 const gchar *certificate)
1876 HildonWindowStack *stack;
1878 stack = hildon_window_stack_get_default ();
1879 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1882 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1887 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1890 /* We use GTK_RESPONSE_APPLY because we want the button in the
1891 middle of OK and CANCEL the same as the browser does for
1892 example. With GTK_RESPONSE_HELP the view button is aligned
1893 to the left while the other two to the right */
1894 note = hildon_note_new_confirmation_add_buttons (
1897 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1898 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1899 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1902 g_signal_connect (G_OBJECT(note), "response",
1903 G_CALLBACK(on_cert_dialog_response),
1904 (gpointer) certificate);
1906 response = gtk_dialog_run(GTK_DIALOG(note));
1908 on_destroy_dialog (note);
1911 return response == GTK_RESPONSE_OK;
1915 modest_platform_run_alert_dialog (const gchar* prompt,
1916 gboolean is_question)
1918 ModestWindow *top_win;
1919 HildonWindowStack *stack;
1921 stack = hildon_window_stack_get_default ();
1922 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1925 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1930 gboolean retval = TRUE;
1932 /* The Tinymail documentation says that we should show Yes and No buttons,
1933 * when it is a question.
1934 * Obviously, we need tinymail to use more specific error codes instead,
1935 * so we know what buttons to show. */
1936 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
1938 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1939 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
1941 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1942 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1944 on_destroy_dialog (dialog);
1946 /* Just show the error text and use the default response: */
1947 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
1955 GtkWindow *parent_window;
1956 ModestConnectedPerformer callback;
1957 TnyAccount *account;
1964 on_went_online_info_free (OnWentOnlineInfo *info)
1966 /* And if we cleanup, we DO cleanup :-) */
1969 g_object_unref (info->device);
1972 if (info->parent_window)
1973 g_object_unref (info->parent_window);
1975 g_object_unref (info->account);
1977 g_slice_free (OnWentOnlineInfo, info);
1979 /* We're done ... */
1985 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
1987 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1989 /* Now it's really time to callback to the caller. If going online didn't succeed,
1990 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
1991 * canceled will be set. Etcetera etcetera. */
1993 if (info->callback) {
1994 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
1997 /* This is our last call, we must cleanup here if we didn't yet do that */
1998 on_went_online_info_free (info);
2005 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2007 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2008 info->iap = g_strdup (iap_id);
2010 if (canceled || err || !info->account) {
2012 /* If there's a problem or if there's no account (then that's it for us, we callback
2013 * the caller's callback now. He'll have to handle err or canceled, of course.
2014 * We are not really online, as the account is not really online here ... */
2016 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2017 * this info. We don't cleanup err, Tinymail does that! */
2019 if (info->callback) {
2021 /* info->account can be NULL here, this means that the user did not
2022 * provide a nice account instance. We'll assume that the user knows
2023 * what he's doing and is happy with just the device going online.
2025 * We can't do magic, we don't know what account the user wants to
2026 * see going online. So just the device goes online, end of story */
2028 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2031 } else if (info->account) {
2033 /* If there's no problem and if we have an account, we'll put the account
2034 * online too. When done, the callback of bringing the account online
2035 * will callback the caller's callback. This is the most normal case. */
2037 info->device = TNY_DEVICE (g_object_ref (device));
2039 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2040 on_account_went_online, info);
2042 /* The on_account_went_online cb frees up the info, go look if you
2043 * don't believe me! (so we return here) */
2048 /* We cleanup if we are not bringing the account online too */
2049 on_went_online_info_free (info);
2055 modest_platform_connect_and_perform (GtkWindow *parent_window,
2057 TnyAccount *account,
2058 ModestConnectedPerformer callback,
2061 gboolean device_online;
2063 TnyConnectionStatus conn_status;
2064 OnWentOnlineInfo *info;
2066 device = modest_runtime_get_device();
2067 device_online = tny_device_is_online (device);
2069 /* If there is no account check only the device status */
2072 if (device_online) {
2074 /* We promise to instantly perform the callback, so ... */
2076 callback (FALSE, NULL, parent_window, account, user_data);
2081 info = g_slice_new0 (OnWentOnlineInfo);
2084 info->device = NULL;
2085 info->account = NULL;
2088 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2090 info->parent_window = NULL;
2091 info->user_data = user_data;
2092 info->callback = callback;
2094 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2095 force, on_conic_device_went_online,
2098 /* We'll cleanup in on_conic_device_went_online */
2101 /* The other code has no more reason to run. This is all that we can do for the
2102 * caller (he should have given us a nice and clean account instance!). We
2103 * can't do magic, we don't know what account he intends to bring online. So
2104 * we'll just bring the device online (and await his false bug report). */
2110 /* Return if the account is already connected */
2112 conn_status = tny_account_get_connection_status (account);
2113 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2115 /* We promise to instantly perform the callback, so ... */
2117 callback (FALSE, NULL, parent_window, account, user_data);
2123 /* Else, we are in a state that requires that we go online before we
2124 * call the caller's callback. */
2126 info = g_slice_new0 (OnWentOnlineInfo);
2128 info->device = NULL;
2130 info->account = TNY_ACCOUNT (g_object_ref (account));
2133 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2135 info->parent_window = NULL;
2137 /* So we'll put the callback away for later ... */
2139 info->user_data = user_data;
2140 info->callback = callback;
2142 if (!device_online) {
2144 /* If also the device is offline, then we connect both the device
2145 * and the account */
2147 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2148 force, on_conic_device_went_online,
2153 /* If the device is online, we'll just connect the account */
2155 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2156 on_account_went_online, info);
2159 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2160 * in both situations, go look if you don't believe me! */
2166 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2168 TnyFolderStore *folder_store,
2169 ModestConnectedPerformer callback,
2172 TnyAccount *account = NULL;
2174 if (!folder_store) {
2175 /* We promise to instantly perform the callback, so ... */
2177 callback (FALSE, NULL, parent_window, NULL, user_data);
2181 } else if (TNY_IS_FOLDER (folder_store)) {
2182 /* Get the folder's parent account: */
2183 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2184 } else if (TNY_IS_ACCOUNT (folder_store)) {
2185 /* Use the folder store as an account: */
2186 account = TNY_ACCOUNT (g_object_ref (folder_store));
2189 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
2190 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2191 /* No need to connect a local account */
2193 callback (FALSE, NULL, parent_window, account, user_data);
2198 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2202 g_object_unref (account);
2206 src_account_connect_performer (gboolean canceled,
2208 GtkWindow *parent_window,
2209 TnyAccount *src_account,
2212 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2214 if (canceled || err) {
2215 /* If there was any error call the user callback */
2216 info->callback (canceled, err, parent_window, src_account, info->data);
2218 /* Connect the destination account */
2219 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2220 TNY_FOLDER_STORE (info->dst_account),
2221 info->callback, info->data);
2224 /* Free the info object */
2225 g_object_unref (info->dst_account);
2226 g_slice_free (DoubleConnectionInfo, info);
2231 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2233 TnyFolderStore *folder_store,
2234 DoubleConnectionInfo *connect_info)
2236 modest_platform_connect_if_remote_and_perform(parent_window,
2239 src_account_connect_performer,
2244 modest_platform_get_account_settings_wizard (void)
2246 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2248 return GTK_WIDGET (dialog);
2252 modest_platform_get_current_connection (void)
2254 TnyDevice *device = NULL;
2255 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2257 device = modest_runtime_get_device ();
2259 if (!tny_device_is_online (device))
2260 return MODEST_CONNECTED_VIA_ANY;
2262 #ifdef MODEST_HAVE_CONIC
2264 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2266 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2267 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2268 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2270 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2271 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2272 !strcmp (bearer_type, "WIMAX")) {
2273 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2275 retval = MODEST_CONNECTED_VIA_ANY;
2278 g_object_unref (iap);
2281 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2282 #endif /* MODEST_HAVE_CONIC */
2289 modest_platform_check_memory_low (ModestWindow *win,
2294 /* are we in low memory state? */
2295 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2297 if (win && lowmem && visuals)
2298 modest_platform_run_information_dialog (
2300 dgettext("ke-recv","memr_ib_operation_disabled"),
2304 g_debug ("%s: low memory reached. disallowing some operations",
2311 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2317 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2320 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2321 GTK_WINDOW (dialog),
2323 gtk_widget_show_all (dialog);
2325 g_signal_connect_swapped (dialog, "response",
2326 G_CALLBACK (gtk_widget_destroy),
2331 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2337 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2340 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2341 GTK_WINDOW (dialog),
2343 gtk_widget_show_all (dialog);
2345 g_signal_connect_swapped (dialog, "response",
2346 G_CALLBACK (gtk_widget_destroy),
2351 modest_platform_get_osso_context (void)
2353 return modest_maemo_utils_get_osso_context ();
2357 _modest_platform_play_email_tone (void)
2359 gchar *active_profile;
2362 gint mail_volume_int;
2364 ca_context *ca_con = NULL;
2365 ca_proplist *pl = NULL;
2367 active_profile = profile_get_profile ();
2368 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2369 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2370 mail_volume_int = profile_parse_int (mail_volume);
2372 if (mail_volume_int > 0) {
2374 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2375 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2379 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2380 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2381 ca_context_destroy(ca_con);
2385 ca_proplist_create(&pl);
2386 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2387 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2389 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2390 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2392 ca_proplist_destroy(pl);
2393 ca_context_destroy(ca_con);
2396 g_free (mail_volume);
2398 g_free (active_profile);
2402 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2404 GtkTreeViewColumn *column,
2407 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_OK);
2411 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2412 GtkWidget **folder_view)
2414 GtkWidget *dialog, *folder_view_container;
2416 /* Create dialog. We cannot use a touch selector because we
2417 need to use here the folder view widget directly */
2418 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2419 GTK_WINDOW (parent_window),
2420 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2421 GTK_DIALOG_DESTROY_WITH_PARENT,
2422 _("mcen_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2425 /* Create folder view */
2426 *folder_view = modest_platform_create_folder_view (NULL);
2428 /* Simulate the behaviour of a HildonPickerDialog by emitting
2429 a response when a folder is selected */
2430 g_signal_connect (*folder_view, "row-activated",
2431 G_CALLBACK (on_move_to_dialog_folder_activated),
2434 /* Create pannable and add it to the dialog */
2435 folder_view_container = hildon_pannable_area_new ();
2436 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), folder_view_container);
2437 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2439 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2441 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2442 gtk_widget_show (folder_view_container);
2443 gtk_widget_show (*folder_view);
2449 modest_platform_get_list_to_move (ModestWindow *window)
2451 if (MODEST_IS_HEADER_WINDOW (window)) {
2452 ModestHeaderView *header_view;
2454 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2456 return modest_header_view_get_selected_headers (header_view);
2457 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2458 ModestFolderView *folder_view;
2459 TnyFolderStore *selected_folder;
2462 list = TNY_LIST (tny_simple_list_new ());
2463 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2464 selected_folder = modest_folder_view_get_selected (folder_view);
2465 if (selected_folder) {
2466 tny_list_prepend (list, G_OBJECT (selected_folder));
2467 g_object_unref (selected_folder);