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)),
568 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
569 _CS("ckdg_ib_maximum_characters_reached"));
571 /* Write the text in the entry if it's valid */
572 g_signal_handlers_block_by_func (editable,
573 (gpointer) entry_insert_text, data);
574 gtk_editable_insert_text (editable, text, length, position);
575 g_signal_handlers_unblock_by_func (editable,
576 (gpointer) entry_insert_text, data);
579 /* Do not allow further processing */
580 g_signal_stop_emission_by_name (editable, "insert_text");
584 entry_changed (GtkEditable *editable,
588 GtkWidget *ok_button;
591 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
592 ok_button = GTK_WIDGET (buttons->data);
594 chars = gtk_editable_get_chars (editable, 0, -1);
595 g_return_if_fail (chars != NULL);
598 if (g_utf8_strlen (chars,-1) >= 20) {
599 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
600 _CS("ckdg_ib_maximum_characters_reached"));
602 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
605 g_list_free (buttons);
612 on_response (GtkDialog *dialog,
616 GtkWidget *entry, *picker;
617 TnyFolderStore *parent;
618 const gchar *new_name;
621 if (response != GTK_RESPONSE_ACCEPT)
625 entry = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY);
626 picker = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER);
628 parent = TNY_FOLDER_STORE (user_data);
629 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
632 if (picker != NULL) {
634 parent = g_object_get_data (G_OBJECT (picker), FOLDER_PICKER_CURRENT_FOLDER);
637 /* Look for another folder with the same name */
638 if (modest_tny_folder_has_subfolder_with_name (parent,
645 if (TNY_IS_ACCOUNT (parent) &&
646 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
647 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
656 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
657 NULL, _CS("ckdg_ib_folder_already_exists"));
658 /* Select the text */
659 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
660 gtk_widget_grab_focus (entry);
661 /* Do not close the dialog */
662 g_signal_stop_emission_by_name (dialog, "response");
667 typedef struct _FolderChooserData {
668 TnyFolderStore *store;
673 folder_chooser_activated (ModestFolderView *folder_view,
674 TnyFolderStore *folder,
675 FolderChooserData *userdata)
677 userdata->store = folder;
678 gtk_dialog_response (GTK_DIALOG (userdata->dialog), GTK_RESPONSE_OK);
681 static TnyFolderStore *
682 folder_chooser_dialog_run (ModestFolderView *original)
684 GtkWidget *folder_view;
685 FolderChooserData userdata = {NULL, NULL};
687 const gchar *visible_id = NULL;
689 userdata.dialog = hildon_dialog_new ();
690 pannable = hildon_pannable_area_new ();
691 folder_view = modest_platform_create_folder_view (NULL);
692 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
693 MODEST_FOLDER_VIEW_FILTER_CAN_HAVE_FOLDERS);
695 modest_folder_view_copy_model (MODEST_FOLDER_VIEW (original),
696 MODEST_FOLDER_VIEW (folder_view));
699 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(original));
700 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view),
703 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (userdata.dialog)->vbox), pannable);
704 gtk_container_add (GTK_CONTAINER (pannable), folder_view);
705 gtk_widget_set_size_request (pannable, -1, 320);
707 gtk_widget_show (folder_view);
708 gtk_widget_show (pannable);
709 gtk_widget_show (userdata.dialog);
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);
764 const gchar *icon_name = NULL;
766 g_object_ref (store);
767 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
768 store, (GDestroyNotify) g_object_unref);
769 name = folder_store_get_display_name (store);
770 hildon_button_set_value (HILDON_BUTTON (button), name);
774 if (TNY_IS_ACCOUNT (store)) {
775 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
776 icon_name = MODEST_FOLDER_ICON_LOCAL_FOLDERS;
777 else if (modest_tny_account_is_memory_card_account (TNY_ACCOUNT (store)))
778 icon_name = MODEST_FOLDER_ICON_MMC;
780 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
782 if (modest_tny_folder_is_remote_folder (TNY_FOLDER (store))) {
783 TnyFolderType type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
785 case TNY_FOLDER_TYPE_INBOX:
786 icon_name = MODEST_FOLDER_ICON_INBOX;
789 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
791 } else if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)))
792 icon_name = MODEST_FOLDER_ICON_NORMAL;
793 else if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store)))
794 icon_name = MODEST_FOLDER_ICON_MMC_FOLDER;
798 pixbuf = modest_platform_get_icon (icon_name, MODEST_ICON_SIZE_SMALL);
801 hildon_button_set_image (HILDON_BUTTON (button),
802 gtk_image_new_from_pixbuf (pixbuf));
803 g_object_unref (pixbuf);
809 folder_picker_clicked (GtkButton *button,
810 ModestFolderView *folder_view)
812 TnyFolderStore *store;
814 store = folder_chooser_dialog_run (folder_view);
816 folder_picker_set_store (GTK_BUTTON (button), store);
821 folder_picker_new (ModestFolderView *folder_view, TnyFolderStore *suggested)
825 button = hildon_button_new (MODEST_EDITABLE_SIZE,
826 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
828 hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 1.0);
831 folder_picker_set_store (GTK_BUTTON (button), suggested);
834 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (folder_picker_clicked), folder_view);
841 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
842 TnyFolderStore *suggested_parent,
843 const gchar *dialog_title,
844 const gchar *label_text,
845 const gchar *suggested_name,
847 gboolean show_parent,
849 TnyFolderStore **parent)
851 GtkWidget *accept_btn = NULL;
852 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
853 GtkWidget *account_picker = NULL;
854 GList *buttons = NULL;
856 GtkSizeGroup *sizegroup;
857 ModestFolderView *folder_view;
858 ModestWindow *folder_window;
859 ModestHildon2WindowMgr *window_mgr;
861 window_mgr = (ModestHildon2WindowMgr *) modest_runtime_get_window_mgr ();
862 folder_window = modest_hildon2_window_mgr_get_folder_window (window_mgr);
863 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
865 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
867 /* Ask the user for the folder name */
868 dialog = gtk_dialog_new_with_buttons (dialog_title,
870 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
871 _FM("ckdg_bd_new_folder_dialog_ok"),
875 /* Add accept button (with unsensitive handler) */
876 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
877 accept_btn = GTK_WIDGET (buttons->data);
879 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
882 label_entry = gtk_label_new (label_text);
883 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
884 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
886 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
887 gtk_size_group_add_widget (sizegroup, label_entry);
890 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
892 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
893 gtk_entry_set_width_chars (GTK_ENTRY (entry),
894 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
895 g_utf8_strlen (_("mcen_ia_default_folder_name"), -1)));
896 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
901 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
903 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
904 gtk_size_group_add_widget (sizegroup, label_location);
906 account_picker = folder_picker_new (folder_view, suggested_parent);
909 g_object_unref (sizegroup);
911 /* Connect to the response method to avoid closing the dialog
912 when an invalid name is selected*/
913 g_signal_connect (dialog,
915 G_CALLBACK (on_response),
919 /* Track entry changes */
920 g_signal_connect (entry,
922 G_CALLBACK (entry_insert_text),
924 g_signal_connect (entry,
926 G_CALLBACK (entry_changed),
931 /* Some locales like pt_BR need this to get the full window
933 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
935 /* Create the hbox */
937 hbox = gtk_hbox_new (FALSE, 12);
938 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
939 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
941 /* Add hbox to dialog */
942 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
943 hbox, FALSE, FALSE, 0);
944 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
948 hbox = gtk_hbox_new (FALSE, 12);
949 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
950 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
952 /* Add hbox to dialog */
953 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
954 hbox, FALSE, FALSE, 0);
955 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
957 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
958 GTK_WINDOW (dialog), parent_window);
959 gtk_widget_show_all (GTK_WIDGET(dialog));
961 result = gtk_dialog_run (GTK_DIALOG(dialog));
962 if (result == GTK_RESPONSE_ACCEPT) {
964 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
966 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
968 g_object_ref (*parent);
972 gtk_widget_destroy (dialog);
974 while (gtk_events_pending ())
975 gtk_main_iteration ();
981 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
982 TnyFolderStore *suggested_folder,
983 gchar *suggested_name,
985 TnyFolderStore **parent_folder)
987 gchar *real_suggested_name = NULL, *tmp = NULL;
989 ModestTnyAccountStore *acc_store;
992 if(suggested_name == NULL)
994 const gchar *default_name = _("mcen_ia_default_folder_name");
998 for(i = 0; i < 100; ++ i) {
999 gboolean exists = FALSE;
1001 sprintf(num_str, "%.2u", i);
1004 real_suggested_name = g_strdup (default_name);
1006 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
1008 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
1009 real_suggested_name,
1015 g_free (real_suggested_name);
1018 /* Didn't find a free number */
1020 real_suggested_name = g_strdup (default_name);
1022 real_suggested_name = suggested_name;
1025 /* In hildon 2.2 we always suggest the archive folder as parent */
1026 acc_store = modest_runtime_get_account_store ();
1027 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
1029 suggested_folder = (TnyFolderStore *)
1030 modest_tny_account_get_special_folder (account,
1031 TNY_FOLDER_TYPE_ARCHIVE);
1032 g_object_unref (account);
1036 /* If there is not archive folder then fallback to local folders account */
1037 if (!suggested_folder)
1038 suggested_folder = (TnyFolderStore *)
1039 modest_tny_account_store_get_local_folders_account (acc_store);
1041 tmp = g_strconcat (_("mcen_fi_new_folder_name"), ":", NULL);
1042 result = modest_platform_run_folder_common_dialog (parent_window,
1044 _("mcen_ti_new_folder"),
1046 real_suggested_name,
1053 if (suggested_name == NULL)
1054 g_free(real_suggested_name);
1060 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1061 TnyFolderStore *parent_folder,
1062 const gchar *suggested_name,
1063 gchar **folder_name)
1065 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1067 return modest_platform_run_folder_common_dialog (parent_window,
1069 _HL("ckdg_ti_rename_folder"),
1070 _HL("ckdg_fi_rename_name"),
1081 on_destroy_dialog (GtkWidget *dialog)
1083 /* This could happen when the dialogs get programatically
1084 hidden or destroyed (for example when closing the
1085 application while a dialog is being shown) */
1086 if (!GTK_IS_WIDGET (dialog))
1089 gtk_widget_destroy (dialog);
1091 if (gtk_events_pending ())
1092 gtk_main_iteration ();
1096 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1097 const gchar *message)
1102 dialog = hildon_note_new_confirmation (parent_window, message);
1103 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1104 GTK_WINDOW (dialog), parent_window);
1106 response = gtk_dialog_run (GTK_DIALOG (dialog));
1108 on_destroy_dialog (dialog);
1114 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1115 const gchar *message,
1116 const gchar *button_accept,
1117 const gchar *button_cancel)
1122 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1123 button_accept, GTK_RESPONSE_ACCEPT,
1124 button_cancel, GTK_RESPONSE_CANCEL,
1127 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1128 GTK_WINDOW (dialog), parent_window);
1130 response = gtk_dialog_run (GTK_DIALOG (dialog));
1132 on_destroy_dialog (dialog);
1138 modest_platform_run_information_dialog (GtkWindow *parent_window,
1139 const gchar *message,
1144 note = hildon_note_new_information (parent_window, message);
1146 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1147 GTK_WINDOW (note), parent_window);
1150 gtk_dialog_run (GTK_DIALOG (note));
1152 on_destroy_dialog (note);
1154 g_signal_connect_swapped (note,
1156 G_CALLBACK (on_destroy_dialog),
1159 gtk_widget_show_all (note);
1163 typedef struct _ConnectAndWaitData {
1165 GMainLoop *wait_loop;
1166 gboolean has_callback;
1168 } ConnectAndWaitData;
1172 quit_wait_loop (TnyAccount *account,
1173 ConnectAndWaitData *data)
1175 /* Set the has_callback to TRUE (means that the callback was
1176 executed and wake up every code waiting for cond to be
1178 g_mutex_lock (data->mutex);
1179 data->has_callback = TRUE;
1180 if (data->wait_loop)
1181 g_main_loop_quit (data->wait_loop);
1182 g_mutex_unlock (data->mutex);
1186 on_connection_status_changed (TnyAccount *account,
1187 TnyConnectionStatus status,
1190 TnyConnectionStatus conn_status;
1191 ConnectAndWaitData *data;
1193 /* Ignore if reconnecting or disconnected */
1194 conn_status = tny_account_get_connection_status (account);
1195 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1196 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1199 /* Remove the handler */
1200 data = (ConnectAndWaitData *) user_data;
1201 g_signal_handler_disconnect (account, data->handler);
1203 /* Quit from wait loop */
1204 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1208 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1213 /* Quit from wait loop */
1214 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1218 modest_platform_connect_and_wait (GtkWindow *parent_window,
1219 TnyAccount *account)
1221 ConnectAndWaitData *data = NULL;
1222 gboolean device_online;
1224 TnyConnectionStatus conn_status;
1225 gboolean user_requested;
1227 device = modest_runtime_get_device();
1228 device_online = tny_device_is_online (device);
1230 /* Whether the connection is user requested or automatically
1231 requested, for example via D-Bus */
1232 user_requested = (parent_window) ? TRUE : FALSE;
1234 /* If there is no account check only the device status */
1239 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1240 NULL, user_requested);
1243 /* Return if the account is already connected */
1244 conn_status = tny_account_get_connection_status (account);
1245 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1248 /* Create the helper */
1249 data = g_slice_new0 (ConnectAndWaitData);
1250 data->mutex = g_mutex_new ();
1251 data->has_callback = FALSE;
1253 /* Connect the device */
1254 if (!device_online) {
1255 /* Track account connection status changes */
1256 data->handler = g_signal_connect (account, "connection-status-changed",
1257 G_CALLBACK (on_connection_status_changed),
1259 /* Try to connect the device */
1260 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1261 NULL, user_requested);
1263 /* If the device connection failed then exit */
1264 if (!device_online && data->handler)
1267 /* Force a reconnection of the account */
1268 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1269 on_tny_camel_account_set_online_cb, data);
1272 /* Wait until the callback is executed */
1273 g_mutex_lock (data->mutex);
1274 if (!data->has_callback) {
1275 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1276 gdk_threads_leave ();
1277 g_mutex_unlock (data->mutex);
1278 g_main_loop_run (data->wait_loop);
1279 g_mutex_lock (data->mutex);
1280 gdk_threads_enter ();
1282 g_mutex_unlock (data->mutex);
1286 if (g_signal_handler_is_connected (account, data->handler))
1287 g_signal_handler_disconnect (account, data->handler);
1288 g_mutex_free (data->mutex);
1289 g_main_loop_unref (data->wait_loop);
1290 g_slice_free (ConnectAndWaitData, data);
1293 conn_status = tny_account_get_connection_status (account);
1294 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1298 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1300 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1301 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1302 /* This must be a maildir account, which does not require a connection: */
1307 return modest_platform_connect_and_wait (parent_window, account);
1311 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1314 return TRUE; /* Maybe it is something local. */
1316 gboolean result = TRUE;
1317 if (TNY_IS_FOLDER (folder_store)) {
1318 /* Get the folder's parent account: */
1319 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1320 if (account != NULL) {
1321 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1322 g_object_unref (account);
1324 } else if (TNY_IS_ACCOUNT (folder_store)) {
1325 /* Use the folder store as an account: */
1326 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1333 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1337 dialog = modest_hildon2_sort_dialog_new (parent_window);
1344 modest_platform_set_update_interval (guint minutes)
1346 #ifdef MODEST_HAVE_LIBALARM
1348 ModestConf *conf = modest_runtime_get_conf ();
1352 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1354 /* Delete any existing alarm,
1355 * because we will replace it: */
1357 if (alarmd_event_del(alarm_cookie) != 0)
1358 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1360 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1363 /* 0 means no updates: */
1368 /* Register alarm: */
1370 /* Set the interval in alarm_event_t structure: */
1371 alarm_event_t *event = alarm_event_create ();
1372 alarm_event_add_actions (event, 1);
1373 alarm_action_t *action = alarm_event_get_action (event, 0);
1374 alarm_event_set_alarm_appid (event, MODEST_ALARMD_APPID);
1375 event->alarm_time = minutes * 60; /* seconds */
1377 /* Set recurrence every few minutes: */
1378 event->recur_secs = minutes*60;
1379 event->recur_count = -1; /* Means infinite */
1381 /* Specify what should happen when the alarm happens:
1382 * It should call this D-Bus method: */
1384 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1385 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1386 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1387 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1388 action->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1390 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1391 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1392 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1393 * This is why we want to use the Alarm API instead of just g_timeout_add().
1394 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1395 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1397 event->flags = ALARM_EVENT_CONNECTED;
1399 alarm_cookie = alarmd_event_add (event);
1402 alarm_event_delete (event);
1404 /* Store the alarm ID in GConf, so we can remove it later:
1405 * This is apparently valid between application instances. */
1406 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1408 if (!alarm_cookie) {
1410 g_debug ("Error setting alarm event. \n");
1414 #endif /* MODEST_HAVE_LIBALARM */
1419 modest_platform_push_email_notification(void)
1421 gboolean screen_on, app_in_foreground;
1423 /* Get the window status */
1424 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1426 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1428 /* If the screen is on and the app is in the
1429 foreground we don't show anything */
1430 if (!(screen_on && app_in_foreground)) {
1432 _modest_platform_play_email_tone ();
1434 /* Activate LED. This must be deactivated by
1435 modest_platform_remove_new_mail_notifications */
1436 #ifdef MODEST_HAVE_MCE
1437 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1441 MCE_ACTIVATE_LED_PATTERN,
1443 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1450 modest_platform_on_new_headers_received (TnyList *header_list,
1451 gboolean show_visual)
1453 g_return_if_fail (TNY_IS_LIST(header_list));
1455 if (tny_list_get_length(header_list) == 0) {
1456 g_warning ("%s: header list is empty", __FUNCTION__);
1461 modest_platform_push_email_notification ();
1462 /* We do a return here to avoid indentation with an else */
1466 #ifdef MODEST_HAVE_HILDON_NOTIFY
1467 HildonNotification *notification;
1469 GSList *notifications_list = NULL;
1471 /* Get previous notifications ids */
1472 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1473 MODEST_CONF_NOTIFICATION_IDS,
1474 MODEST_CONF_VALUE_INT, NULL);
1476 iter = tny_list_create_iterator (header_list);
1477 while (!tny_iterator_is_done (iter)) {
1478 gchar *url = NULL, *display_address = NULL, *summary = NULL;
1479 const gchar *display_date;
1480 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1481 TnyFolder *folder = tny_header_get_folder (header);
1482 gboolean first_notification = TRUE;
1485 ModestDatetimeFormatter *datetime_formatter;
1487 /* constant string, don't free */
1488 datetime_formatter = modest_datetime_formatter_new ();
1489 display_date = modest_datetime_formatter_display_datetime (datetime_formatter,
1490 tny_header_get_date_received (header));
1491 g_object_unref (datetime_formatter);
1493 display_address = tny_header_dup_from (header);
1494 /* string is changed in-place */
1495 modest_text_utils_get_display_address (display_address);
1497 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1498 str = tny_header_dup_subject (header);
1499 notification = hildon_notification_new (summary,
1501 "qgn_list_messagin",
1504 /* Create the message URL */
1505 str = tny_header_dup_uid (header);
1506 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1510 hildon_notification_add_dbus_action(notification,
1513 MODEST_DBUS_SERVICE,
1516 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1520 /* Play sound if the user wants. Show the LED
1521 pattern. Show and play just one */
1522 if (G_UNLIKELY (first_notification)) {
1523 gchar *active_profile;
1526 gint mail_volume_int;
1528 first_notification = FALSE;
1530 active_profile = profile_get_profile ();
1531 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
1532 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
1533 mail_volume_int = profile_parse_int (mail_volume);
1535 if (mail_volume_int > 0)
1536 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1537 "sound-file", mail_tone);
1539 g_free (mail_volume);
1541 g_free (active_profile);
1543 /* Set the led pattern */
1544 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1546 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1548 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1551 /* Notify. We need to do this in an idle because this function
1552 could be called from a thread */
1553 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1555 /* Save id in the list */
1556 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1557 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1558 /* We don't listen for the "closed" signal, because we
1559 don't care about if the notification was removed or
1560 not to store the list in gconf */
1562 /* Free & carry on */
1563 g_free (display_address);
1566 g_object_unref (folder);
1567 g_object_unref (header);
1568 tny_iterator_next (iter);
1570 g_object_unref (iter);
1573 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1574 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1576 g_slist_free (notifications_list);
1578 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1582 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1585 #ifdef MODEST_HAVE_MCE
1586 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1590 MCE_DEACTIVATE_LED_PATTERN,
1592 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1598 #ifdef MODEST_HAVE_HILDON_NOTIFY
1599 GSList *notif_list = NULL;
1601 /* Get previous notifications ids */
1602 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1603 MODEST_CONF_NOTIFICATION_IDS,
1604 MODEST_CONF_VALUE_INT, NULL);
1606 while (notif_list) {
1608 NotifyNotification *notif;
1610 /* Nasty HACK to remove the notifications, set the id
1611 of the existing ones and then close them */
1612 notif_id = GPOINTER_TO_INT(notif_list->data);
1613 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1614 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1616 /* Close the notification, note that some ids could be
1617 already invalid, but we don't care because it does
1619 notify_notification_close(notif, NULL);
1620 g_object_unref(notif);
1622 /* Delete the link, it's like going to the next */
1623 notif_list = g_slist_delete_link (notif_list, notif_list);
1627 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1628 notif_list, MODEST_CONF_VALUE_INT, NULL);
1630 g_slist_free (notif_list);
1632 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1638 modest_platform_get_global_settings_dialog ()
1640 return modest_hildon2_global_settings_dialog_new ();
1644 modest_platform_show_help (GtkWindow *parent_window,
1645 const gchar *help_id)
1651 modest_platform_show_search_messages (GtkWindow *parent_window)
1653 osso_return_t result = OSSO_ERROR;
1655 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1656 "osso_global_search",
1657 "search_email", NULL, DBUS_TYPE_INVALID);
1659 if (result != OSSO_OK) {
1660 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1665 modest_platform_show_addressbook (GtkWindow *parent_window)
1667 osso_return_t result = OSSO_ERROR;
1669 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1671 "top_application", NULL, DBUS_TYPE_INVALID);
1673 if (result != OSSO_OK) {
1674 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1679 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1681 GtkWidget *widget = modest_folder_view_new (query);
1683 /* Show one account by default */
1684 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1685 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1687 /* Restore settings */
1688 modest_widget_memory_restore (modest_runtime_get_conf(),
1690 MODEST_CONF_FOLDER_VIEW_KEY);
1696 banner_finish (gpointer data, GObject *object)
1698 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1699 modest_window_mgr_unregister_banner (mgr);
1700 g_object_unref (mgr);
1704 modest_platform_information_banner (GtkWidget *parent,
1705 const gchar *icon_name,
1708 GtkWidget *banner, *banner_parent = NULL;
1709 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1711 if (modest_window_mgr_get_num_windows (mgr) == 0)
1714 if (parent && GTK_IS_WINDOW (parent)) {
1715 /* If the window is the active one then show the
1716 banner on top of this window */
1717 if (gtk_window_is_active (GTK_WINDOW (parent)))
1718 banner_parent = parent;
1719 /* If the window is not the topmost but it's visible
1720 (it's minimized for example) then show the banner
1722 else if (GTK_WIDGET_VISIBLE (parent))
1723 banner_parent = NULL;
1724 /* If the window is hidden (like the main window when
1725 running in the background) then do not show
1732 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1734 modest_window_mgr_register_banner (mgr);
1736 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1740 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1741 const gchar *icon_name,
1747 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1750 banner = hildon_banner_show_information (parent, icon_name, text);
1751 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1755 modest_platform_animation_banner (GtkWidget *parent,
1756 const gchar *animation_name,
1759 GtkWidget *inf_note = NULL;
1761 g_return_val_if_fail (text != NULL, NULL);
1763 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1766 /* If the parent is not visible then do not show */
1767 if (parent && !GTK_WIDGET_VISIBLE (parent))
1770 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1778 TnyAccount *account;
1781 } CheckAccountIdleData;
1783 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1786 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1788 gboolean stop_trying = FALSE;
1789 g_return_val_if_fail (data && data->account, FALSE);
1791 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1792 tny_account_get_connection_status (data->account));
1794 if (data && data->account &&
1795 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1796 * after which the account is likely to be usable, or never likely to be usable soon: */
1797 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1799 data->is_online = TRUE;
1803 /* Give up if we have tried too many times: */
1804 if (data->count_tries >= NUMBER_OF_TRIES) {
1807 /* Wait for another timeout: */
1808 ++(data->count_tries);
1813 /* Allow the function that requested this idle callback to continue: */
1815 g_main_loop_quit (data->loop);
1818 g_object_unref (data->account);
1820 return FALSE; /* Don't call this again. */
1822 return TRUE; /* Call this timeout callback again. */
1826 /* Return TRUE immediately if the account is already online,
1827 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1828 * soon as the account is online, or FALSE if the account does
1829 * not become online in the NUMBER_OF_TRIES seconds.
1830 * This is useful when the D-Bus method was run immediately after
1831 * the application was started (when using D-Bus activation),
1832 * because the account usually takes a short time to go online.
1833 * The return value is maybe not very useful.
1836 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1840 g_return_val_if_fail (account, FALSE);
1842 if (!tny_device_is_online (modest_runtime_get_device())) {
1843 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1847 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1848 * so we avoid wait unnecessarily: */
1849 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1852 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1853 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1854 * we want to avoid. */
1855 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1858 /* This blocks on the result: */
1859 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1860 data->is_online = FALSE;
1861 data->account = account;
1862 g_object_ref (data->account);
1863 data->count_tries = 0;
1865 GMainContext *context = NULL; /* g_main_context_new (); */
1866 data->loop = g_main_loop_new (context, FALSE /* not running */);
1868 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1870 /* This main loop will run until the idle handler has stopped it: */
1871 g_main_loop_run (data->loop);
1873 g_main_loop_unref (data->loop);
1874 /* g_main_context_unref (context); */
1876 is_online = data->is_online;
1877 g_slice_free (CheckAccountIdleData, data);
1885 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1887 /* GTK_RESPONSE_HELP means we need to show the certificate */
1888 if (response_id == GTK_RESPONSE_APPLY) {
1892 /* Do not close the dialog */
1893 g_signal_stop_emission_by_name (dialog, "response");
1895 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1896 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1897 gtk_dialog_run (GTK_DIALOG(note));
1898 gtk_widget_destroy (note);
1904 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1905 const gchar *certificate)
1910 HildonWindowStack *stack;
1912 stack = hildon_window_stack_get_default ();
1913 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1916 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1921 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1924 /* We use GTK_RESPONSE_APPLY because we want the button in the
1925 middle of OK and CANCEL the same as the browser does for
1926 example. With GTK_RESPONSE_HELP the view button is aligned
1927 to the left while the other two to the right */
1928 note = hildon_note_new_confirmation_add_buttons (
1931 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1932 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1933 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1936 g_signal_connect (G_OBJECT(note), "response",
1937 G_CALLBACK(on_cert_dialog_response),
1938 (gpointer) certificate);
1940 response = gtk_dialog_run(GTK_DIALOG(note));
1942 on_destroy_dialog (note);
1945 return response == GTK_RESPONSE_OK;
1949 modest_platform_run_alert_dialog (const gchar* prompt,
1950 gboolean is_question)
1952 ModestWindow *top_win;
1953 HildonWindowStack *stack;
1955 stack = hildon_window_stack_get_default ();
1956 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1959 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1964 gboolean retval = TRUE;
1966 /* The Tinymail documentation says that we should show Yes and No buttons,
1967 * when it is a question.
1968 * Obviously, we need tinymail to use more specific error codes instead,
1969 * so we know what buttons to show. */
1970 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
1972 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1973 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
1975 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1976 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1978 on_destroy_dialog (dialog);
1980 /* Just show the error text and use the default response: */
1981 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
1989 GtkWindow *parent_window;
1990 ModestConnectedPerformer callback;
1991 TnyAccount *account;
1998 on_went_online_info_free (OnWentOnlineInfo *info)
2000 /* And if we cleanup, we DO cleanup :-) */
2003 g_object_unref (info->device);
2006 if (info->parent_window)
2007 g_object_unref (info->parent_window);
2009 g_object_unref (info->account);
2011 g_slice_free (OnWentOnlineInfo, info);
2013 /* We're done ... */
2019 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
2021 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2023 /* Now it's really time to callback to the caller. If going online didn't succeed,
2024 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
2025 * canceled will be set. Etcetera etcetera. */
2027 if (info->callback) {
2028 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2031 /* This is our last call, we must cleanup here if we didn't yet do that */
2032 on_went_online_info_free (info);
2039 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2041 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2042 info->iap = g_strdup (iap_id);
2044 if (canceled || err || !info->account) {
2046 /* If there's a problem or if there's no account (then that's it for us, we callback
2047 * the caller's callback now. He'll have to handle err or canceled, of course.
2048 * We are not really online, as the account is not really online here ... */
2050 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2051 * this info. We don't cleanup err, Tinymail does that! */
2053 if (info->callback) {
2055 /* info->account can be NULL here, this means that the user did not
2056 * provide a nice account instance. We'll assume that the user knows
2057 * what he's doing and is happy with just the device going online.
2059 * We can't do magic, we don't know what account the user wants to
2060 * see going online. So just the device goes online, end of story */
2062 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2065 } else if (info->account) {
2067 /* If there's no problem and if we have an account, we'll put the account
2068 * online too. When done, the callback of bringing the account online
2069 * will callback the caller's callback. This is the most normal case. */
2071 info->device = TNY_DEVICE (g_object_ref (device));
2073 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2074 on_account_went_online, info);
2076 /* The on_account_went_online cb frees up the info, go look if you
2077 * don't believe me! (so we return here) */
2082 /* We cleanup if we are not bringing the account online too */
2083 on_went_online_info_free (info);
2089 modest_platform_connect_and_perform (GtkWindow *parent_window,
2091 TnyAccount *account,
2092 ModestConnectedPerformer callback,
2095 gboolean device_online;
2097 TnyConnectionStatus conn_status;
2098 OnWentOnlineInfo *info;
2100 device = modest_runtime_get_device();
2101 device_online = tny_device_is_online (device);
2103 /* If there is no account check only the device status */
2106 if (device_online) {
2108 /* We promise to instantly perform the callback, so ... */
2110 callback (FALSE, NULL, parent_window, account, user_data);
2115 info = g_slice_new0 (OnWentOnlineInfo);
2118 info->device = NULL;
2119 info->account = NULL;
2122 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2124 info->parent_window = NULL;
2125 info->user_data = user_data;
2126 info->callback = callback;
2128 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2129 force, on_conic_device_went_online,
2132 /* We'll cleanup in on_conic_device_went_online */
2135 /* The other code has no more reason to run. This is all that we can do for the
2136 * caller (he should have given us a nice and clean account instance!). We
2137 * can't do magic, we don't know what account he intends to bring online. So
2138 * we'll just bring the device online (and await his false bug report). */
2144 /* Return if the account is already connected */
2146 conn_status = tny_account_get_connection_status (account);
2147 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2149 /* We promise to instantly perform the callback, so ... */
2151 callback (FALSE, NULL, parent_window, account, user_data);
2157 /* Else, we are in a state that requires that we go online before we
2158 * call the caller's callback. */
2160 info = g_slice_new0 (OnWentOnlineInfo);
2162 info->device = NULL;
2164 info->account = TNY_ACCOUNT (g_object_ref (account));
2167 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2169 info->parent_window = NULL;
2171 /* So we'll put the callback away for later ... */
2173 info->user_data = user_data;
2174 info->callback = callback;
2176 if (!device_online) {
2178 /* If also the device is offline, then we connect both the device
2179 * and the account */
2181 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2182 force, on_conic_device_went_online,
2187 /* If the device is online, we'll just connect the account */
2189 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2190 on_account_went_online, info);
2193 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2194 * in both situations, go look if you don't believe me! */
2200 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2202 TnyFolderStore *folder_store,
2203 ModestConnectedPerformer callback,
2206 TnyAccount *account = NULL;
2208 if (!folder_store ||
2209 (TNY_IS_MERGE_FOLDER (folder_store) &&
2210 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2212 /* We promise to instantly perform the callback, so ... */
2214 GError *error = NULL;
2215 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2216 "Unable to move or not found folder");
2217 callback (FALSE, error, parent_window, NULL, user_data);
2218 g_error_free (error);
2222 } else if (TNY_IS_FOLDER (folder_store)) {
2223 /* Get the folder's parent account: */
2224 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2225 } else if (TNY_IS_ACCOUNT (folder_store)) {
2226 /* Use the folder store as an account: */
2227 account = TNY_ACCOUNT (g_object_ref (folder_store));
2230 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
2231 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2232 /* No need to connect a local account */
2234 callback (FALSE, NULL, parent_window, account, user_data);
2239 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2243 g_object_unref (account);
2247 src_account_connect_performer (gboolean canceled,
2249 GtkWindow *parent_window,
2250 TnyAccount *src_account,
2253 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2255 if (canceled || err) {
2256 /* If there was any error call the user callback */
2257 info->callback (canceled, err, parent_window, src_account, info->data);
2259 /* Connect the destination account */
2260 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2261 TNY_FOLDER_STORE (info->dst_account),
2262 info->callback, info->data);
2265 /* Free the info object */
2266 g_object_unref (info->dst_account);
2267 g_slice_free (DoubleConnectionInfo, info);
2272 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2274 TnyFolderStore *folder_store,
2275 DoubleConnectionInfo *connect_info)
2277 modest_platform_connect_if_remote_and_perform(parent_window,
2280 src_account_connect_performer,
2285 modest_platform_get_account_settings_wizard (void)
2287 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2289 return GTK_WIDGET (dialog);
2293 modest_platform_get_current_connection (void)
2295 TnyDevice *device = NULL;
2296 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2298 device = modest_runtime_get_device ();
2300 if (!tny_device_is_online (device))
2301 return MODEST_CONNECTED_VIA_ANY;
2303 #ifdef MODEST_HAVE_CONIC
2305 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2307 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2308 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2309 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2311 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2312 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2313 !strcmp (bearer_type, "WIMAX")) {
2314 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2316 retval = MODEST_CONNECTED_VIA_ANY;
2319 g_object_unref (iap);
2322 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2323 #endif /* MODEST_HAVE_CONIC */
2330 modest_platform_check_memory_low (ModestWindow *win,
2335 /* are we in low memory state? */
2336 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2338 if (win && lowmem && visuals)
2339 modest_platform_run_information_dialog (
2341 _KR("memr_ib_operation_disabled"),
2345 g_debug ("%s: low memory reached. disallowing some operations",
2352 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2358 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2361 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2362 GTK_WINDOW (dialog),
2364 gtk_widget_show_all (dialog);
2366 g_signal_connect_swapped (dialog, "response",
2367 G_CALLBACK (gtk_widget_destroy),
2372 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2378 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2381 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2382 GTK_WINDOW (dialog),
2384 gtk_widget_show_all (dialog);
2386 g_signal_connect_swapped (dialog, "response",
2387 G_CALLBACK (gtk_widget_destroy),
2392 modest_platform_get_osso_context (void)
2394 return modest_maemo_utils_get_osso_context ();
2398 _modest_platform_play_email_tone (void)
2400 gchar *active_profile;
2403 gint mail_volume_int;
2405 ca_context *ca_con = NULL;
2406 ca_proplist *pl = NULL;
2408 active_profile = profile_get_profile ();
2409 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2410 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2411 mail_volume_int = profile_parse_int (mail_volume);
2413 if (mail_volume_int > 0) {
2415 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2416 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2420 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2421 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2422 ca_context_destroy(ca_con);
2426 ca_proplist_create(&pl);
2427 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2428 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2430 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2431 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2433 ca_proplist_destroy(pl);
2434 ca_context_destroy(ca_con);
2437 g_free (mail_volume);
2439 g_free (active_profile);
2443 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2445 GtkTreeViewColumn *column,
2448 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_OK);
2452 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2453 GtkWidget **folder_view)
2455 GtkWidget *dialog, *folder_view_container;
2457 /* Create dialog. We cannot use a touch selector because we
2458 need to use here the folder view widget directly */
2459 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2460 GTK_WINDOW (parent_window),
2461 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2462 GTK_DIALOG_DESTROY_WITH_PARENT,
2463 _HL("wdgt_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2466 /* Create folder view */
2467 *folder_view = modest_platform_create_folder_view (NULL);
2469 /* Simulate the behaviour of a HildonPickerDialog by emitting
2470 a response when a folder is selected */
2471 g_signal_connect (*folder_view, "row-activated",
2472 G_CALLBACK (on_move_to_dialog_folder_activated),
2475 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2476 (TnyAccountStore *) modest_runtime_get_account_store ());
2478 /* Create pannable and add it to the dialog */
2479 folder_view_container = hildon_pannable_area_new ();
2480 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), folder_view_container);
2481 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2483 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2485 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2486 gtk_widget_show (folder_view_container);
2487 gtk_widget_show (*folder_view);
2493 modest_platform_get_list_to_move (ModestWindow *window)
2495 TnyList *list = NULL;
2497 if (MODEST_IS_HEADER_WINDOW (window)) {
2498 ModestHeaderView *header_view;
2500 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2501 list = modest_header_view_get_selected_headers (header_view);
2502 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2503 ModestFolderView *folder_view;
2504 TnyFolderStore *selected_folder;
2506 list = TNY_LIST (tny_simple_list_new ());
2507 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2508 selected_folder = modest_folder_view_get_selected (folder_view);
2509 if (selected_folder) {
2510 tny_list_prepend (list, G_OBJECT (selected_folder));
2511 g_object_unref (selected_folder);
2514 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2517 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2519 list = TNY_LIST (tny_simple_list_new ());
2520 tny_list_prepend (list, G_OBJECT (header));
2521 g_object_unref (header);
2524 g_return_val_if_reached (NULL);