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)),
569 insert_length = g_utf8_strlen (text, -1);
571 if (insert_length + chars_length >= 20) {
572 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
573 _CS("ckdg_ib_maximum_characters_reached"));
575 /* Write the text in the entry if it's valid */
576 g_signal_handlers_block_by_func (editable,
577 (gpointer) entry_insert_text, data);
578 gtk_editable_insert_text (editable, text, MIN (chars_length + insert_length, 20), position);
579 g_signal_handlers_unblock_by_func (editable,
580 (gpointer) entry_insert_text, data);
583 /* Do not allow further processing */
584 g_signal_stop_emission_by_name (editable, "insert_text");
588 entry_changed (GtkEditable *editable,
592 GtkWidget *ok_button;
595 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
596 ok_button = GTK_WIDGET (buttons->data);
598 chars = gtk_editable_get_chars (editable, 0, -1);
599 g_return_if_fail (chars != NULL);
602 if (g_utf8_strlen (chars,-1) >= 20) {
603 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
604 _CS("ckdg_ib_maximum_characters_reached"));
606 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
609 g_list_free (buttons);
616 on_response (GtkDialog *dialog,
620 GtkWidget *entry, *picker;
621 TnyFolderStore *parent;
622 const gchar *new_name;
625 if (response != GTK_RESPONSE_ACCEPT)
629 entry = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY);
630 picker = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER);
632 parent = TNY_FOLDER_STORE (user_data);
633 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
636 if (picker != NULL) {
638 parent = g_object_get_data (G_OBJECT (picker), FOLDER_PICKER_CURRENT_FOLDER);
641 /* Look for another folder with the same name */
642 if (modest_tny_folder_has_subfolder_with_name (parent,
649 if (TNY_IS_ACCOUNT (parent) &&
650 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
651 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
660 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
661 NULL, _CS("ckdg_ib_folder_already_exists"));
662 /* Select the text */
663 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
664 gtk_widget_grab_focus (entry);
665 /* Do not close the dialog */
666 g_signal_stop_emission_by_name (dialog, "response");
671 typedef struct _FolderChooserData {
672 TnyFolderStore *store;
677 folder_chooser_activated (ModestFolderView *folder_view,
678 TnyFolderStore *folder,
679 FolderChooserData *userdata)
681 userdata->store = folder;
682 gtk_dialog_response (GTK_DIALOG (userdata->dialog), GTK_RESPONSE_OK);
685 static TnyFolderStore *
686 folder_chooser_dialog_run (ModestFolderView *original)
688 GtkWidget *folder_view;
689 FolderChooserData userdata = {NULL, NULL};
691 const gchar *visible_id = NULL;
693 userdata.dialog = hildon_dialog_new ();
694 pannable = hildon_pannable_area_new ();
695 folder_view = modest_platform_create_folder_view (NULL);
696 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
697 MODEST_FOLDER_VIEW_FILTER_CAN_HAVE_FOLDERS);
699 modest_folder_view_copy_model (MODEST_FOLDER_VIEW (original),
700 MODEST_FOLDER_VIEW (folder_view));
703 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(original));
704 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view),
707 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (userdata.dialog)->vbox), pannable);
708 gtk_container_add (GTK_CONTAINER (pannable), folder_view);
709 gtk_widget_set_size_request (pannable, -1, 320);
711 gtk_widget_show (folder_view);
712 gtk_widget_show (pannable);
713 gtk_widget_show (userdata.dialog);
714 g_signal_connect (G_OBJECT (folder_view), "folder-activated",
715 G_CALLBACK (folder_chooser_activated),
716 (gpointer) &userdata);
718 gtk_dialog_run (GTK_DIALOG (userdata.dialog));
719 gtk_widget_destroy (userdata.dialog);
721 return userdata.store;
725 folder_store_get_display_name (TnyFolderStore *store)
727 if (TNY_IS_ACCOUNT (store)) {
728 return g_strdup (tny_account_get_name (TNY_ACCOUNT (store)));
731 TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
733 fname = g_strdup (tny_folder_get_name (TNY_FOLDER (store)));
734 type = tny_folder_get_folder_type (TNY_FOLDER (store));
735 if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)) ||
736 modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
737 type = modest_tny_folder_get_local_or_mmc_folder_type (TNY_FOLDER (store));
738 if (type != TNY_FOLDER_TYPE_UNKNOWN) {
740 fname = g_strdup (modest_local_folder_info_get_type_display_name (type));
743 /* Sometimes an special folder is reported by the server as
744 NORMAL, like some versions of Dovecot */
745 if (type == TNY_FOLDER_TYPE_NORMAL ||
746 type == TNY_FOLDER_TYPE_UNKNOWN) {
747 type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
751 if (type == TNY_FOLDER_TYPE_INBOX) {
753 fname = g_strdup (_("mcen_me_folder_inbox"));
760 folder_picker_set_store (GtkButton *button, TnyFolderStore *store)
765 g_object_set_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER, NULL);
768 const gchar *icon_name = NULL;
770 g_object_ref (store);
771 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
772 store, (GDestroyNotify) g_object_unref);
773 name = folder_store_get_display_name (store);
774 hildon_button_set_value (HILDON_BUTTON (button), name);
778 if (TNY_IS_ACCOUNT (store)) {
779 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
780 icon_name = MODEST_FOLDER_ICON_LOCAL_FOLDERS;
781 else if (modest_tny_account_is_memory_card_account (TNY_ACCOUNT (store)))
782 icon_name = MODEST_FOLDER_ICON_MMC;
784 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
786 if (modest_tny_folder_is_remote_folder (TNY_FOLDER (store))) {
787 TnyFolderType type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
789 case TNY_FOLDER_TYPE_INBOX:
790 icon_name = MODEST_FOLDER_ICON_INBOX;
793 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
795 } else if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)))
796 icon_name = MODEST_FOLDER_ICON_NORMAL;
797 else if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store)))
798 icon_name = MODEST_FOLDER_ICON_MMC_FOLDER;
802 pixbuf = modest_platform_get_icon (icon_name, MODEST_ICON_SIZE_SMALL);
805 hildon_button_set_image (HILDON_BUTTON (button),
806 gtk_image_new_from_pixbuf (pixbuf));
807 g_object_unref (pixbuf);
813 folder_picker_clicked (GtkButton *button,
814 ModestFolderView *folder_view)
816 TnyFolderStore *store;
818 store = folder_chooser_dialog_run (folder_view);
820 folder_picker_set_store (GTK_BUTTON (button), store);
825 folder_picker_new (ModestFolderView *folder_view, TnyFolderStore *suggested)
829 button = hildon_button_new (MODEST_EDITABLE_SIZE,
830 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
832 hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 1.0);
835 folder_picker_set_store (GTK_BUTTON (button), suggested);
838 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (folder_picker_clicked), folder_view);
845 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
846 TnyFolderStore *suggested_parent,
847 const gchar *dialog_title,
848 const gchar *label_text,
849 const gchar *suggested_name,
851 gboolean show_parent,
853 TnyFolderStore **parent)
855 GtkWidget *accept_btn = NULL;
856 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
857 GtkWidget *account_picker = NULL;
858 GList *buttons = NULL;
860 GtkSizeGroup *sizegroup;
861 ModestFolderView *folder_view;
862 ModestWindow *folder_window;
863 ModestHildon2WindowMgr *window_mgr;
865 window_mgr = (ModestHildon2WindowMgr *) modest_runtime_get_window_mgr ();
866 folder_window = modest_hildon2_window_mgr_get_folder_window (window_mgr);
867 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
869 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
871 /* Ask the user for the folder name */
872 dialog = gtk_dialog_new_with_buttons (dialog_title,
874 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
875 _FM("ckdg_bd_new_folder_dialog_ok"),
879 /* Add accept button (with unsensitive handler) */
880 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
881 accept_btn = GTK_WIDGET (buttons->data);
883 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
886 label_entry = gtk_label_new (label_text);
887 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
888 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
890 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
891 gtk_size_group_add_widget (sizegroup, label_entry);
894 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
896 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
897 gtk_entry_set_width_chars (GTK_ENTRY (entry),
898 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
899 g_utf8_strlen (_("mcen_ia_default_folder_name"), -1)));
900 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
905 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
907 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
908 gtk_size_group_add_widget (sizegroup, label_location);
910 account_picker = folder_picker_new (folder_view, suggested_parent);
913 g_object_unref (sizegroup);
915 /* Connect to the response method to avoid closing the dialog
916 when an invalid name is selected*/
917 g_signal_connect (dialog,
919 G_CALLBACK (on_response),
923 /* Track entry changes */
924 g_signal_connect (entry,
926 G_CALLBACK (entry_insert_text),
928 g_signal_connect (entry,
930 G_CALLBACK (entry_changed),
935 /* Some locales like pt_BR need this to get the full window
937 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
939 /* Create the hbox */
941 hbox = gtk_hbox_new (FALSE, 12);
942 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
943 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
945 /* Add hbox to dialog */
946 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
947 hbox, FALSE, FALSE, 0);
948 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
952 hbox = gtk_hbox_new (FALSE, 12);
953 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
954 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
956 /* Add hbox to dialog */
957 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
958 hbox, FALSE, FALSE, 0);
959 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
961 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
962 GTK_WINDOW (dialog), parent_window);
963 gtk_widget_show_all (GTK_WIDGET(dialog));
965 result = gtk_dialog_run (GTK_DIALOG(dialog));
966 if (result == GTK_RESPONSE_ACCEPT) {
968 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
970 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
972 g_object_ref (*parent);
976 gtk_widget_destroy (dialog);
978 while (gtk_events_pending ())
979 gtk_main_iteration ();
985 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
986 TnyFolderStore *suggested_folder,
987 gchar *suggested_name,
989 TnyFolderStore **parent_folder)
991 gchar *real_suggested_name = NULL, *tmp = NULL;
993 ModestTnyAccountStore *acc_store;
996 if(suggested_name == NULL)
998 const gchar *default_name = _("mcen_ia_default_folder_name");
1002 for(i = 0; i < 100; ++ i) {
1003 gboolean exists = FALSE;
1005 sprintf(num_str, "%.2u", i);
1008 real_suggested_name = g_strdup (default_name);
1010 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
1012 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
1013 real_suggested_name,
1019 g_free (real_suggested_name);
1022 /* Didn't find a free number */
1024 real_suggested_name = g_strdup (default_name);
1026 real_suggested_name = suggested_name;
1029 /* In hildon 2.2 we always suggest the archive folder as parent */
1030 acc_store = modest_runtime_get_account_store ();
1031 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
1033 suggested_folder = (TnyFolderStore *)
1034 modest_tny_account_get_special_folder (account,
1035 TNY_FOLDER_TYPE_ARCHIVE);
1036 g_object_unref (account);
1040 /* If there is not archive folder then fallback to local folders account */
1041 if (!suggested_folder)
1042 suggested_folder = (TnyFolderStore *)
1043 modest_tny_account_store_get_local_folders_account (acc_store);
1045 tmp = g_strconcat (_("mcen_fi_new_folder_name"), ":", NULL);
1046 result = modest_platform_run_folder_common_dialog (parent_window,
1048 _("mcen_ti_new_folder"),
1050 real_suggested_name,
1057 if (suggested_name == NULL)
1058 g_free(real_suggested_name);
1064 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1065 TnyFolderStore *parent_folder,
1066 const gchar *suggested_name,
1067 gchar **folder_name)
1069 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1071 return modest_platform_run_folder_common_dialog (parent_window,
1073 _HL("ckdg_ti_rename_folder"),
1074 _HL("ckdg_fi_rename_name"),
1085 on_destroy_dialog (GtkWidget *dialog)
1087 /* This could happen when the dialogs get programatically
1088 hidden or destroyed (for example when closing the
1089 application while a dialog is being shown) */
1090 if (!GTK_IS_WIDGET (dialog))
1093 gtk_widget_destroy (dialog);
1095 if (gtk_events_pending ())
1096 gtk_main_iteration ();
1100 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1101 const gchar *message)
1106 dialog = hildon_note_new_confirmation (parent_window, message);
1107 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1108 GTK_WINDOW (dialog), parent_window);
1110 response = gtk_dialog_run (GTK_DIALOG (dialog));
1112 on_destroy_dialog (dialog);
1118 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1119 const gchar *message,
1120 const gchar *button_accept,
1121 const gchar *button_cancel)
1126 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1127 button_accept, GTK_RESPONSE_ACCEPT,
1128 button_cancel, GTK_RESPONSE_CANCEL,
1131 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1132 GTK_WINDOW (dialog), parent_window);
1134 response = gtk_dialog_run (GTK_DIALOG (dialog));
1136 on_destroy_dialog (dialog);
1142 modest_platform_run_information_dialog (GtkWindow *parent_window,
1143 const gchar *message,
1148 note = hildon_note_new_information (parent_window, message);
1150 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1151 GTK_WINDOW (note), parent_window);
1154 gtk_dialog_run (GTK_DIALOG (note));
1156 on_destroy_dialog (note);
1158 g_signal_connect_swapped (note,
1160 G_CALLBACK (on_destroy_dialog),
1163 gtk_widget_show_all (note);
1167 typedef struct _ConnectAndWaitData {
1169 GMainLoop *wait_loop;
1170 gboolean has_callback;
1172 } ConnectAndWaitData;
1176 quit_wait_loop (TnyAccount *account,
1177 ConnectAndWaitData *data)
1179 /* Set the has_callback to TRUE (means that the callback was
1180 executed and wake up every code waiting for cond to be
1182 g_mutex_lock (data->mutex);
1183 data->has_callback = TRUE;
1184 if (data->wait_loop)
1185 g_main_loop_quit (data->wait_loop);
1186 g_mutex_unlock (data->mutex);
1190 on_connection_status_changed (TnyAccount *account,
1191 TnyConnectionStatus status,
1194 TnyConnectionStatus conn_status;
1195 ConnectAndWaitData *data;
1197 /* Ignore if reconnecting or disconnected */
1198 conn_status = tny_account_get_connection_status (account);
1199 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1200 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1203 /* Remove the handler */
1204 data = (ConnectAndWaitData *) user_data;
1205 g_signal_handler_disconnect (account, data->handler);
1207 /* Quit from wait loop */
1208 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1212 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1217 /* Quit from wait loop */
1218 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1222 modest_platform_connect_and_wait (GtkWindow *parent_window,
1223 TnyAccount *account)
1225 ConnectAndWaitData *data = NULL;
1226 gboolean device_online;
1228 TnyConnectionStatus conn_status;
1229 gboolean user_requested;
1231 device = modest_runtime_get_device();
1232 device_online = tny_device_is_online (device);
1234 /* Whether the connection is user requested or automatically
1235 requested, for example via D-Bus */
1236 user_requested = (parent_window) ? TRUE : FALSE;
1238 /* If there is no account check only the device status */
1243 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1244 NULL, user_requested);
1247 /* Return if the account is already connected */
1248 conn_status = tny_account_get_connection_status (account);
1249 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1252 /* Create the helper */
1253 data = g_slice_new0 (ConnectAndWaitData);
1254 data->mutex = g_mutex_new ();
1255 data->has_callback = FALSE;
1257 /* Connect the device */
1258 if (!device_online) {
1259 /* Track account connection status changes */
1260 data->handler = g_signal_connect (account, "connection-status-changed",
1261 G_CALLBACK (on_connection_status_changed),
1263 /* Try to connect the device */
1264 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1265 NULL, user_requested);
1267 /* If the device connection failed then exit */
1268 if (!device_online && data->handler)
1271 /* Force a reconnection of the account */
1272 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1273 on_tny_camel_account_set_online_cb, data);
1276 /* Wait until the callback is executed */
1277 g_mutex_lock (data->mutex);
1278 if (!data->has_callback) {
1279 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1280 gdk_threads_leave ();
1281 g_mutex_unlock (data->mutex);
1282 g_main_loop_run (data->wait_loop);
1283 g_mutex_lock (data->mutex);
1284 gdk_threads_enter ();
1286 g_mutex_unlock (data->mutex);
1290 if (g_signal_handler_is_connected (account, data->handler))
1291 g_signal_handler_disconnect (account, data->handler);
1292 g_mutex_free (data->mutex);
1293 g_main_loop_unref (data->wait_loop);
1294 g_slice_free (ConnectAndWaitData, data);
1297 conn_status = tny_account_get_connection_status (account);
1298 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1302 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1304 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1305 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1306 /* This must be a maildir account, which does not require a connection: */
1311 return modest_platform_connect_and_wait (parent_window, account);
1315 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1318 return TRUE; /* Maybe it is something local. */
1320 gboolean result = TRUE;
1321 if (TNY_IS_FOLDER (folder_store)) {
1322 /* Get the folder's parent account: */
1323 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1324 if (account != NULL) {
1325 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1326 g_object_unref (account);
1328 } else if (TNY_IS_ACCOUNT (folder_store)) {
1329 /* Use the folder store as an account: */
1330 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1337 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1341 dialog = modest_hildon2_sort_dialog_new (parent_window);
1348 modest_platform_set_update_interval (guint minutes)
1350 #ifdef MODEST_HAVE_LIBALARM
1352 ModestConf *conf = modest_runtime_get_conf ();
1356 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1358 /* Delete any existing alarm,
1359 * because we will replace it: */
1361 if (alarmd_event_del(alarm_cookie) != 0)
1362 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1364 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1367 /* 0 means no updates: */
1372 /* Register alarm: */
1374 /* Set the interval in alarm_event_t structure: */
1375 alarm_event_t *event = alarm_event_create ();
1376 alarm_event_add_actions (event, 1);
1377 alarm_action_t *action = alarm_event_get_action (event, 0);
1378 alarm_event_set_alarm_appid (event, MODEST_ALARMD_APPID);
1379 event->alarm_time = minutes * 60; /* seconds */
1381 /* Set recurrence every few minutes: */
1382 event->recur_secs = minutes*60;
1383 event->recur_count = -1; /* Means infinite */
1385 /* Specify what should happen when the alarm happens:
1386 * It should call this D-Bus method: */
1388 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1389 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1390 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1391 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1392 action->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1394 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1395 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1396 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1397 * This is why we want to use the Alarm API instead of just g_timeout_add().
1398 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1399 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1401 event->flags = ALARM_EVENT_CONNECTED;
1403 alarm_cookie = alarmd_event_add (event);
1406 alarm_event_delete (event);
1408 /* Store the alarm ID in GConf, so we can remove it later:
1409 * This is apparently valid between application instances. */
1410 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1412 if (!alarm_cookie) {
1414 g_debug ("Error setting alarm event. \n");
1418 #endif /* MODEST_HAVE_LIBALARM */
1423 modest_platform_push_email_notification(void)
1425 gboolean screen_on, app_in_foreground;
1427 /* Get the window status */
1428 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1430 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1432 /* If the screen is on and the app is in the
1433 foreground we don't show anything */
1434 if (!(screen_on && app_in_foreground)) {
1436 _modest_platform_play_email_tone ();
1438 /* Activate LED. This must be deactivated by
1439 modest_platform_remove_new_mail_notifications */
1440 #ifdef MODEST_HAVE_MCE
1441 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1445 MCE_ACTIVATE_LED_PATTERN,
1447 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1454 modest_platform_on_new_headers_received (TnyList *header_list,
1455 gboolean show_visual)
1457 g_return_if_fail (TNY_IS_LIST(header_list));
1459 if (tny_list_get_length(header_list) == 0) {
1460 g_warning ("%s: header list is empty", __FUNCTION__);
1465 modest_platform_push_email_notification ();
1466 /* We do a return here to avoid indentation with an else */
1470 #ifdef MODEST_HAVE_HILDON_NOTIFY
1471 HildonNotification *notification;
1473 GSList *notifications_list = NULL;
1475 /* Get previous notifications ids */
1476 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1477 MODEST_CONF_NOTIFICATION_IDS,
1478 MODEST_CONF_VALUE_INT, NULL);
1480 iter = tny_list_create_iterator (header_list);
1481 while (!tny_iterator_is_done (iter)) {
1482 gchar *url = NULL, *display_address = NULL, *summary = NULL;
1483 const gchar *display_date;
1484 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1485 TnyFolder *folder = tny_header_get_folder (header);
1486 gboolean first_notification = TRUE;
1489 ModestDatetimeFormatter *datetime_formatter;
1491 /* constant string, don't free */
1492 datetime_formatter = modest_datetime_formatter_new ();
1493 display_date = modest_datetime_formatter_display_datetime (datetime_formatter,
1494 tny_header_get_date_received (header));
1495 g_object_unref (datetime_formatter);
1497 display_address = tny_header_dup_from (header);
1498 /* string is changed in-place */
1499 modest_text_utils_get_display_address (display_address);
1501 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1502 str = tny_header_dup_subject (header);
1503 notification = hildon_notification_new (summary,
1505 "qgn_list_messagin",
1508 /* Create the message URL */
1509 str = tny_header_dup_uid (header);
1510 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1514 hildon_notification_add_dbus_action(notification,
1517 MODEST_DBUS_SERVICE,
1520 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1524 /* Play sound if the user wants. Show the LED
1525 pattern. Show and play just one */
1526 if (G_UNLIKELY (first_notification)) {
1527 gchar *active_profile;
1530 gint mail_volume_int;
1532 first_notification = FALSE;
1534 active_profile = profile_get_profile ();
1535 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
1536 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
1537 mail_volume_int = profile_parse_int (mail_volume);
1539 if (mail_volume_int > 0)
1540 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1541 "sound-file", mail_tone);
1543 g_free (mail_volume);
1545 g_free (active_profile);
1547 /* Set the led pattern */
1548 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1550 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1552 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1555 /* Notify. We need to do this in an idle because this function
1556 could be called from a thread */
1557 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1559 /* Save id in the list */
1560 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1561 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1562 /* We don't listen for the "closed" signal, because we
1563 don't care about if the notification was removed or
1564 not to store the list in gconf */
1566 /* Free & carry on */
1567 g_free (display_address);
1570 g_object_unref (folder);
1571 g_object_unref (header);
1572 tny_iterator_next (iter);
1574 g_object_unref (iter);
1577 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1578 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1580 g_slist_free (notifications_list);
1582 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1586 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1589 #ifdef MODEST_HAVE_MCE
1590 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1594 MCE_DEACTIVATE_LED_PATTERN,
1596 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1602 #ifdef MODEST_HAVE_HILDON_NOTIFY
1603 GSList *notif_list = NULL;
1605 /* Get previous notifications ids */
1606 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1607 MODEST_CONF_NOTIFICATION_IDS,
1608 MODEST_CONF_VALUE_INT, NULL);
1610 while (notif_list) {
1612 NotifyNotification *notif;
1614 /* Nasty HACK to remove the notifications, set the id
1615 of the existing ones and then close them */
1616 notif_id = GPOINTER_TO_INT(notif_list->data);
1617 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1618 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1620 /* Close the notification, note that some ids could be
1621 already invalid, but we don't care because it does
1623 notify_notification_close(notif, NULL);
1624 g_object_unref(notif);
1626 /* Delete the link, it's like going to the next */
1627 notif_list = g_slist_delete_link (notif_list, notif_list);
1631 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1632 notif_list, MODEST_CONF_VALUE_INT, NULL);
1634 g_slist_free (notif_list);
1636 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1642 modest_platform_get_global_settings_dialog ()
1644 return modest_hildon2_global_settings_dialog_new ();
1648 modest_platform_show_help (GtkWindow *parent_window,
1649 const gchar *help_id)
1655 modest_platform_show_search_messages (GtkWindow *parent_window)
1657 osso_return_t result = OSSO_ERROR;
1659 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1660 "osso_global_search",
1661 "search_email", NULL, DBUS_TYPE_INVALID);
1663 if (result != OSSO_OK) {
1664 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1669 modest_platform_show_addressbook (GtkWindow *parent_window)
1671 osso_return_t result = OSSO_ERROR;
1673 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1675 "top_application", NULL, DBUS_TYPE_INVALID);
1677 if (result != OSSO_OK) {
1678 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1683 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1685 GtkWidget *widget = modest_folder_view_new (query);
1687 /* Show one account by default */
1688 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1689 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1691 /* Restore settings */
1692 modest_widget_memory_restore (modest_runtime_get_conf(),
1694 MODEST_CONF_FOLDER_VIEW_KEY);
1700 banner_finish (gpointer data, GObject *object)
1702 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1703 modest_window_mgr_unregister_banner (mgr);
1704 g_object_unref (mgr);
1708 modest_platform_information_banner (GtkWidget *parent,
1709 const gchar *icon_name,
1712 GtkWidget *banner, *banner_parent = NULL;
1713 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1715 if (modest_window_mgr_get_num_windows (mgr) == 0)
1718 if (parent && GTK_IS_WINDOW (parent)) {
1719 /* If the window is the active one then show the
1720 banner on top of this window */
1721 if (gtk_window_is_active (GTK_WINDOW (parent)))
1722 banner_parent = parent;
1723 /* If the window is not the topmost but it's visible
1724 (it's minimized for example) then show the banner
1726 else if (GTK_WIDGET_VISIBLE (parent))
1727 banner_parent = NULL;
1728 /* If the window is hidden (like the main window when
1729 running in the background) then do not show
1736 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1738 modest_window_mgr_register_banner (mgr);
1740 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1744 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1745 const gchar *icon_name,
1751 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1754 banner = hildon_banner_show_information (parent, icon_name, text);
1755 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1759 modest_platform_animation_banner (GtkWidget *parent,
1760 const gchar *animation_name,
1763 GtkWidget *inf_note = NULL;
1765 g_return_val_if_fail (text != NULL, NULL);
1767 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1770 /* If the parent is not visible then do not show */
1771 if (parent && !GTK_WIDGET_VISIBLE (parent))
1774 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1782 TnyAccount *account;
1785 } CheckAccountIdleData;
1787 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1790 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1792 gboolean stop_trying = FALSE;
1793 g_return_val_if_fail (data && data->account, FALSE);
1795 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1796 tny_account_get_connection_status (data->account));
1798 if (data && data->account &&
1799 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1800 * after which the account is likely to be usable, or never likely to be usable soon: */
1801 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1803 data->is_online = TRUE;
1807 /* Give up if we have tried too many times: */
1808 if (data->count_tries >= NUMBER_OF_TRIES) {
1811 /* Wait for another timeout: */
1812 ++(data->count_tries);
1817 /* Allow the function that requested this idle callback to continue: */
1819 g_main_loop_quit (data->loop);
1822 g_object_unref (data->account);
1824 return FALSE; /* Don't call this again. */
1826 return TRUE; /* Call this timeout callback again. */
1830 /* Return TRUE immediately if the account is already online,
1831 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1832 * soon as the account is online, or FALSE if the account does
1833 * not become online in the NUMBER_OF_TRIES seconds.
1834 * This is useful when the D-Bus method was run immediately after
1835 * the application was started (when using D-Bus activation),
1836 * because the account usually takes a short time to go online.
1837 * The return value is maybe not very useful.
1840 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1844 g_return_val_if_fail (account, FALSE);
1846 if (!tny_device_is_online (modest_runtime_get_device())) {
1847 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1851 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1852 * so we avoid wait unnecessarily: */
1853 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1856 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1857 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1858 * we want to avoid. */
1859 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1862 /* This blocks on the result: */
1863 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1864 data->is_online = FALSE;
1865 data->account = account;
1866 g_object_ref (data->account);
1867 data->count_tries = 0;
1869 GMainContext *context = NULL; /* g_main_context_new (); */
1870 data->loop = g_main_loop_new (context, FALSE /* not running */);
1872 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1874 /* This main loop will run until the idle handler has stopped it: */
1875 g_main_loop_run (data->loop);
1877 g_main_loop_unref (data->loop);
1878 /* g_main_context_unref (context); */
1880 is_online = data->is_online;
1881 g_slice_free (CheckAccountIdleData, data);
1889 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1891 /* GTK_RESPONSE_HELP means we need to show the certificate */
1892 if (response_id == GTK_RESPONSE_APPLY) {
1896 /* Do not close the dialog */
1897 g_signal_stop_emission_by_name (dialog, "response");
1899 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1900 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1901 gtk_dialog_run (GTK_DIALOG(note));
1902 gtk_widget_destroy (note);
1908 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1909 const gchar *certificate)
1914 HildonWindowStack *stack;
1916 stack = hildon_window_stack_get_default ();
1917 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1920 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1925 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1928 /* We use GTK_RESPONSE_APPLY because we want the button in the
1929 middle of OK and CANCEL the same as the browser does for
1930 example. With GTK_RESPONSE_HELP the view button is aligned
1931 to the left while the other two to the right */
1932 note = hildon_note_new_confirmation_add_buttons (
1935 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1936 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1937 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1940 g_signal_connect (G_OBJECT(note), "response",
1941 G_CALLBACK(on_cert_dialog_response),
1942 (gpointer) certificate);
1944 response = gtk_dialog_run(GTK_DIALOG(note));
1946 on_destroy_dialog (note);
1949 return response == GTK_RESPONSE_OK;
1953 modest_platform_run_alert_dialog (const gchar* prompt,
1954 gboolean is_question)
1956 ModestWindow *top_win;
1957 HildonWindowStack *stack;
1959 stack = hildon_window_stack_get_default ();
1960 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1963 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1968 gboolean retval = TRUE;
1970 /* The Tinymail documentation says that we should show Yes and No buttons,
1971 * when it is a question.
1972 * Obviously, we need tinymail to use more specific error codes instead,
1973 * so we know what buttons to show. */
1974 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
1976 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1977 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
1979 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1980 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1982 on_destroy_dialog (dialog);
1984 /* Just show the error text and use the default response: */
1985 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
1993 GtkWindow *parent_window;
1994 ModestConnectedPerformer callback;
1995 TnyAccount *account;
2002 on_went_online_info_free (OnWentOnlineInfo *info)
2004 /* And if we cleanup, we DO cleanup :-) */
2007 g_object_unref (info->device);
2010 if (info->parent_window)
2011 g_object_unref (info->parent_window);
2013 g_object_unref (info->account);
2015 g_slice_free (OnWentOnlineInfo, info);
2017 /* We're done ... */
2023 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
2025 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2027 /* Now it's really time to callback to the caller. If going online didn't succeed,
2028 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
2029 * canceled will be set. Etcetera etcetera. */
2031 if (info->callback) {
2032 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2035 /* This is our last call, we must cleanup here if we didn't yet do that */
2036 on_went_online_info_free (info);
2043 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2045 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2046 info->iap = g_strdup (iap_id);
2048 if (canceled || err || !info->account) {
2050 /* If there's a problem or if there's no account (then that's it for us, we callback
2051 * the caller's callback now. He'll have to handle err or canceled, of course.
2052 * We are not really online, as the account is not really online here ... */
2054 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2055 * this info. We don't cleanup err, Tinymail does that! */
2057 if (info->callback) {
2059 /* info->account can be NULL here, this means that the user did not
2060 * provide a nice account instance. We'll assume that the user knows
2061 * what he's doing and is happy with just the device going online.
2063 * We can't do magic, we don't know what account the user wants to
2064 * see going online. So just the device goes online, end of story */
2066 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2069 } else if (info->account) {
2071 /* If there's no problem and if we have an account, we'll put the account
2072 * online too. When done, the callback of bringing the account online
2073 * will callback the caller's callback. This is the most normal case. */
2075 info->device = TNY_DEVICE (g_object_ref (device));
2077 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2078 on_account_went_online, info);
2080 /* The on_account_went_online cb frees up the info, go look if you
2081 * don't believe me! (so we return here) */
2086 /* We cleanup if we are not bringing the account online too */
2087 on_went_online_info_free (info);
2093 modest_platform_connect_and_perform (GtkWindow *parent_window,
2095 TnyAccount *account,
2096 ModestConnectedPerformer callback,
2099 gboolean device_online;
2101 TnyConnectionStatus conn_status;
2102 OnWentOnlineInfo *info;
2104 device = modest_runtime_get_device();
2105 device_online = tny_device_is_online (device);
2107 /* If there is no account check only the device status */
2110 if (device_online) {
2112 /* We promise to instantly perform the callback, so ... */
2114 callback (FALSE, NULL, parent_window, account, user_data);
2119 info = g_slice_new0 (OnWentOnlineInfo);
2122 info->device = NULL;
2123 info->account = NULL;
2126 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2128 info->parent_window = NULL;
2129 info->user_data = user_data;
2130 info->callback = callback;
2132 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2133 force, on_conic_device_went_online,
2136 /* We'll cleanup in on_conic_device_went_online */
2139 /* The other code has no more reason to run. This is all that we can do for the
2140 * caller (he should have given us a nice and clean account instance!). We
2141 * can't do magic, we don't know what account he intends to bring online. So
2142 * we'll just bring the device online (and await his false bug report). */
2148 /* Return if the account is already connected */
2150 conn_status = tny_account_get_connection_status (account);
2151 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2153 /* We promise to instantly perform the callback, so ... */
2155 callback (FALSE, NULL, parent_window, account, user_data);
2161 /* Else, we are in a state that requires that we go online before we
2162 * call the caller's callback. */
2164 info = g_slice_new0 (OnWentOnlineInfo);
2166 info->device = NULL;
2168 info->account = TNY_ACCOUNT (g_object_ref (account));
2171 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2173 info->parent_window = NULL;
2175 /* So we'll put the callback away for later ... */
2177 info->user_data = user_data;
2178 info->callback = callback;
2180 if (!device_online) {
2182 /* If also the device is offline, then we connect both the device
2183 * and the account */
2185 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2186 force, on_conic_device_went_online,
2191 /* If the device is online, we'll just connect the account */
2193 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2194 on_account_went_online, info);
2197 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2198 * in both situations, go look if you don't believe me! */
2204 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2206 TnyFolderStore *folder_store,
2207 ModestConnectedPerformer callback,
2210 TnyAccount *account = NULL;
2212 if (!folder_store ||
2213 (TNY_IS_MERGE_FOLDER (folder_store) &&
2214 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2216 /* We promise to instantly perform the callback, so ... */
2218 GError *error = NULL;
2219 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2220 "Unable to move or not found folder");
2221 callback (FALSE, error, parent_window, NULL, user_data);
2222 g_error_free (error);
2226 } else if (TNY_IS_FOLDER (folder_store)) {
2227 /* Get the folder's parent account: */
2228 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2229 } else if (TNY_IS_ACCOUNT (folder_store)) {
2230 /* Use the folder store as an account: */
2231 account = TNY_ACCOUNT (g_object_ref (folder_store));
2234 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
2235 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2236 /* No need to connect a local account */
2238 callback (FALSE, NULL, parent_window, account, user_data);
2243 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2247 g_object_unref (account);
2251 src_account_connect_performer (gboolean canceled,
2253 GtkWindow *parent_window,
2254 TnyAccount *src_account,
2257 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2259 if (canceled || err) {
2260 /* If there was any error call the user callback */
2261 info->callback (canceled, err, parent_window, src_account, info->data);
2263 /* Connect the destination account */
2264 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2265 TNY_FOLDER_STORE (info->dst_account),
2266 info->callback, info->data);
2269 /* Free the info object */
2270 g_object_unref (info->dst_account);
2271 g_slice_free (DoubleConnectionInfo, info);
2276 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2278 TnyFolderStore *folder_store,
2279 DoubleConnectionInfo *connect_info)
2281 modest_platform_connect_if_remote_and_perform(parent_window,
2284 src_account_connect_performer,
2289 modest_platform_get_account_settings_wizard (void)
2291 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2293 return GTK_WIDGET (dialog);
2297 modest_platform_get_current_connection (void)
2299 TnyDevice *device = NULL;
2300 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2302 device = modest_runtime_get_device ();
2304 if (!tny_device_is_online (device))
2305 return MODEST_CONNECTED_VIA_ANY;
2307 #ifdef MODEST_HAVE_CONIC
2309 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2311 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2312 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2313 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2315 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2316 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2317 !strcmp (bearer_type, "WIMAX")) {
2318 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2320 retval = MODEST_CONNECTED_VIA_ANY;
2323 g_object_unref (iap);
2326 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2327 #endif /* MODEST_HAVE_CONIC */
2334 modest_platform_check_memory_low (ModestWindow *win,
2339 /* are we in low memory state? */
2340 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2342 if (win && lowmem && visuals)
2343 modest_platform_run_information_dialog (
2345 _KR("memr_ib_operation_disabled"),
2349 g_debug ("%s: low memory reached. disallowing some operations",
2356 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2362 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2365 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2366 GTK_WINDOW (dialog),
2368 gtk_widget_show_all (dialog);
2370 g_signal_connect_swapped (dialog, "response",
2371 G_CALLBACK (gtk_widget_destroy),
2376 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2382 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2385 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2386 GTK_WINDOW (dialog),
2388 gtk_widget_show_all (dialog);
2390 g_signal_connect_swapped (dialog, "response",
2391 G_CALLBACK (gtk_widget_destroy),
2396 modest_platform_get_osso_context (void)
2398 return modest_maemo_utils_get_osso_context ();
2402 _modest_platform_play_email_tone (void)
2404 gchar *active_profile;
2407 gint mail_volume_int;
2409 ca_context *ca_con = NULL;
2410 ca_proplist *pl = NULL;
2412 active_profile = profile_get_profile ();
2413 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2414 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2415 mail_volume_int = profile_parse_int (mail_volume);
2417 if (mail_volume_int > 0) {
2419 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2420 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2424 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2425 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2426 ca_context_destroy(ca_con);
2430 ca_proplist_create(&pl);
2431 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2432 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2434 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2435 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2437 ca_proplist_destroy(pl);
2438 ca_context_destroy(ca_con);
2441 g_free (mail_volume);
2443 g_free (active_profile);
2447 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2449 GtkTreeViewColumn *column,
2452 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_OK);
2456 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2457 GtkWidget **folder_view)
2459 GtkWidget *dialog, *folder_view_container;
2461 /* Create dialog. We cannot use a touch selector because we
2462 need to use here the folder view widget directly */
2463 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2464 GTK_WINDOW (parent_window),
2465 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2466 GTK_DIALOG_DESTROY_WITH_PARENT,
2467 _("mcen_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2470 /* Create folder view */
2471 *folder_view = modest_platform_create_folder_view (NULL);
2473 /* Simulate the behaviour of a HildonPickerDialog by emitting
2474 a response when a folder is selected */
2475 g_signal_connect (*folder_view, "row-activated",
2476 G_CALLBACK (on_move_to_dialog_folder_activated),
2479 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2480 (TnyAccountStore *) modest_runtime_get_account_store ());
2482 /* Create pannable and add it to the dialog */
2483 folder_view_container = hildon_pannable_area_new ();
2484 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), folder_view_container);
2485 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2487 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2489 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2490 gtk_widget_show (folder_view_container);
2491 gtk_widget_show (*folder_view);
2497 modest_platform_get_list_to_move (ModestWindow *window)
2499 TnyList *list = NULL;
2501 if (MODEST_IS_HEADER_WINDOW (window)) {
2502 ModestHeaderView *header_view;
2504 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2505 list = modest_header_view_get_selected_headers (header_view);
2506 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2507 ModestFolderView *folder_view;
2508 TnyFolderStore *selected_folder;
2510 list = TNY_LIST (tny_simple_list_new ());
2511 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2512 selected_folder = modest_folder_view_get_selected (folder_view);
2513 if (selected_folder) {
2514 tny_list_prepend (list, G_OBJECT (selected_folder));
2515 g_object_unref (selected_folder);
2518 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2521 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2523 list = TNY_LIST (tny_simple_list_new ());
2524 tny_list_prepend (list, G_OBJECT (header));
2525 g_object_unref (header);
2528 g_return_val_if_reached (NULL);