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>
33 #include <modest-platform.h>
34 #include <modest-defs.h>
35 #include <modest-runtime.h>
36 #include <modest-main-window.h>
37 #include <modest-header-view.h>
38 #include "modest-hildon2-global-settings-dialog.h"
39 #include "modest-widget-memory.h"
40 #include <modest-hildon-includes.h>
41 #include <modest-maemo-utils.h>
42 #include <dbus_api/modest-dbus-callbacks.h>
43 #include <modest-osso-autosave-callbacks.h>
45 #include <tny-maemo-conic-device.h>
46 #include <tny-simple-list.h>
47 #include <tny-merge-folder.h>
48 #include <tny-error.h>
49 #include <tny-folder.h>
50 #include <tny-account-store-view.h>
51 #include <gtk/gtkicontheme.h>
52 #include <gtk/gtkmenuitem.h>
53 #include <gtk/gtkmain.h>
54 #include <modest-text-utils.h>
55 #include "modest-tny-folder.h"
56 #include "modest-tny-account.h"
58 #include <libgnomevfs/gnome-vfs-mime-utils.h>
59 #include <modest-account-settings-dialog.h>
60 #include <modest-easysetup-wizard-dialog.h>
61 #include "modest-hildon2-sort-dialog.h"
62 #include <hildon/hildon.h>
64 #include "hildon2/modest-hildon2-details-dialog.h"
65 #include "hildon2/modest-hildon2-window-mgr.h"
66 #ifdef MODEST_USE_PROFILE
67 #include <keys_nokia.h>
68 #include <libprofile.h>
71 #include <modest-datetime-formatter.h>
72 #include "modest-header-window.h"
73 #include <modest-folder-window.h>
74 #include <modest-account-mgr.h>
75 #include <modest-account-mgr-helpers.h>
76 #include <modest-ui-constants.h>
77 #include <modest-selector-picker.h>
78 #include <modest-icon-names.h>
80 #ifdef MODEST_HAVE_MCE
81 #include <mce/dbus-names.h>
82 #endif /*MODEST_HAVE_MCE*/
84 #ifdef MODEST_HAVE_ABOOK
85 #include <libosso-abook/osso-abook.h>
86 #endif /*MODEST_HAVE_ABOOK*/
88 #ifdef MODEST_HAVE_LIBALARM
89 #include <alarmd/libalarm.h> /* For alarm_event_add(), etc. */
90 #endif /*MODEST_HAVE_LIBALARM*/
93 #define HILDON_OSSO_URI_ACTION "uri-action"
94 #define URI_ACTION_COPY "copy:"
95 #define MODEST_NOTIFICATION_CATEGORY "email-message"
96 #define MODEST_NEW_MAIL_LIGHTING_PATTERN "PatternCommunicationEmail"
97 #ifdef MODEST_USE_PROFILE
98 #define PROFILE_MAIL_TONE PROFILEKEY_EMAIL_ALERT_TONE
99 #define PROFILE_MAIL_VOLUME PROFILEKEY_EMAIL_ALERT_VOLUME
101 #define MAIL_TONE "message-new-email"
104 #define COMMON_FOLDER_DIALOG_ENTRY "entry"
105 #define COMMON_FOLDER_DIALOG_ACCOUNT_PICKER "account-picker"
106 #define FOLDER_PICKER_CURRENT_FOLDER "current-folder"
107 #define MODEST_ALARMD_APPID PACKAGE_NAME
110 static void _modest_platform_play_email_tone (void);
114 on_modest_conf_update_interval_changed (ModestConf* self,
116 ModestConfEvent event,
117 ModestConfNotificationId id,
120 g_return_if_fail (key);
122 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
123 const guint update_interval_minutes =
124 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
125 modest_platform_set_update_interval (update_interval_minutes);
132 check_required_files (void)
134 FILE *mcc_file = modest_maemo_open_mcc_mapping_file (NULL);
136 g_printerr ("modest: check for mcc file failed\n");
141 if (access(MODEST_PROVIDER_DATA_FILE, R_OK) != 0 &&
142 access(MODEST_MAEMO_PROVIDER_DATA_FILE, R_OK) != 0) {
143 g_printerr ("modest: cannot find providers data\n");
151 /* the gpointer here is the osso_context. */
153 modest_platform_init (int argc, char *argv[])
155 osso_context_t *osso_context;
157 osso_hw_state_t hw_state = { 0 };
161 if (!check_required_files ()) {
162 g_printerr ("modest: missing required files\n");
166 osso_context = osso_initialize(PACKAGE,PACKAGE_VERSION,
169 g_printerr ("modest: failed to acquire osso context\n");
172 modest_maemo_utils_set_osso_context (osso_context);
174 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
175 g_printerr ("modest: could not get dbus connection\n");
179 /* Add a D-Bus handler to be used when the main osso-rpc
180 * D-Bus handler has not handled something.
181 * We use this for D-Bus methods that need to use more complex types
182 * than osso-rpc supports.
184 if (!dbus_connection_add_filter (con,
185 modest_dbus_req_filter,
189 g_printerr ("modest: Could not add D-Bus filter\n");
193 /* Register our simple D-Bus callbacks, via the osso API: */
194 osso_return_t result = osso_rpc_set_cb_f(osso_context,
198 modest_dbus_req_handler, NULL /* user_data */);
199 if (result != OSSO_OK) {
200 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
204 /* Register hardware event dbus callback: */
205 hw_state.shutdown_ind = TRUE;
206 osso_hw_set_event_cb(osso_context, NULL, NULL, NULL);
208 /* Register osso auto-save callbacks: */
209 result = osso_application_set_autosave_cb (osso_context,
210 modest_on_osso_application_autosave, NULL /* user_data */);
211 if (result != OSSO_OK) {
212 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
217 /* Make sure that the update interval is changed whenever its gconf key
219 /* CAUTION: we're not using here the
220 modest_conf_listen_to_namespace because we know that there
221 are other parts of Modest listening for this namespace, so
222 we'll receive the notifications anyway. We basically do not
223 use it because there is no easy way to do the
224 modest_conf_forget_namespace */
225 ModestConf *conf = modest_runtime_get_conf ();
226 g_signal_connect (G_OBJECT(conf),
228 G_CALLBACK (on_modest_conf_update_interval_changed),
231 /* only force the setting of the default interval, if there are actually
233 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
235 /* Get the initial update interval from gconf: */
236 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
237 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
238 modest_account_mgr_free_account_names (acc_names);
242 #ifdef MODEST_HAVE_ABOOK
243 /* initialize the addressbook */
244 if (!osso_abook_init (&argc, &argv, osso_context)) {
245 g_printerr ("modest: failed to initialized addressbook\n");
248 #endif /*MODEST_HAVE_ABOOK*/
254 modest_platform_uninit (void)
256 osso_context_t *osso_context =
257 modest_maemo_utils_get_osso_context ();
259 osso_deinitialize (osso_context);
268 modest_platform_get_new_device (void)
270 return TNY_DEVICE (tny_maemo_conic_device_new ());
274 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
275 gchar **effective_mime_type)
277 GString *mime_str = NULL;
278 gchar *icon_name = NULL;
279 gchar **icons, **cursor;
281 if (!mime_type || g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0)
282 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
284 mime_str = g_string_new (mime_type);
285 g_string_ascii_down (mime_str);
288 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
290 for (cursor = icons; cursor; ++cursor) {
291 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
292 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
293 icon_name = g_strdup ("qgn_list_messagin");
295 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
296 icon_name = g_strdup (*cursor);
302 if (effective_mime_type)
303 *effective_mime_type = g_string_free (mime_str, FALSE);
305 g_string_free (mime_str, TRUE);
312 checked_hildon_uri_open (const gchar *uri, HildonURIAction *action)
317 g_return_val_if_fail (uri, FALSE);
319 result = hildon_uri_open (uri, action, &err);
321 g_printerr ("modest: hildon_uri_open ('%s', %p) failed: %s",
322 uri, action, err && err->message ? err->message : "unknown error");
332 modest_platform_activate_uri (const gchar *uri)
334 HildonURIAction *action;
335 gboolean result = FALSE;
336 GSList *actions, *iter = NULL;
338 g_return_val_if_fail (uri, FALSE);
342 /* don't try to activate file: uri's -- they might confuse the user,
343 * and/or might have security implications */
344 if (!g_str_has_prefix (uri, "file:")) {
346 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
348 for (iter = actions; iter; iter = g_slist_next (iter)) {
349 action = (HildonURIAction*) iter->data;
350 if (action && strcmp (hildon_uri_action_get_service (action),
351 "com.nokia.modest") == 0) {
352 result = checked_hildon_uri_open (uri, action);
357 /* if we could not open it with email, try something else */
359 result = checked_hildon_uri_open (uri, NULL);
363 ModestWindow *parent =
364 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
365 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
366 _("mcen_ib_unsupported_link"));
367 g_warning ("%s: cannot open uri '%s'", __FUNCTION__,uri);
374 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
378 gchar *uri_path = NULL;
380 uri_path = gnome_vfs_get_uri_from_local_path (path);
381 con = osso_get_dbus_connection (modest_maemo_utils_get_osso_context());
384 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
386 result = hildon_mime_open_file (con, uri_path);
388 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"), FALSE);
396 } ModestPlatformPopupInfo;
399 delete_uri_popup (GtkWidget *menu,
403 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
405 g_free (popup_info->uri);
406 hildon_uri_free_actions (popup_info->actions);
412 activate_uri_popup_item (GtkMenuItem *menu_item,
416 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
417 const gchar* action_name;
419 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
421 g_printerr ("modest: no action name defined\n");
425 /* special handling for the copy menu item -- copy the uri to the clipboard */
426 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
427 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
428 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
429 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
431 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
432 action_name += strlen ("mailto:");
434 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
435 modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
436 return; /* we're done */
439 /* now, the real uri-actions... */
440 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
441 HildonURIAction *action = (HildonURIAction *) node->data;
442 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
443 if (!checked_hildon_uri_open (popup_info->uri, action)) {
444 ModestWindow *parent =
445 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
446 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
447 _("mcen_ib_unsupported_link"));
455 modest_platform_show_uri_popup (const gchar *uri)
457 GSList *actions_list;
462 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
465 GtkWidget *menu = gtk_menu_new ();
466 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
468 /* don't add actions for file: uri's -- they might confuse the user,
469 * and/or might have security implications
470 * we still allow to copy the url though
472 if (!g_str_has_prefix (uri, "file:")) {
475 popup_info->actions = actions_list;
476 popup_info->uri = g_strdup (uri);
478 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
479 GtkWidget *menu_item;
480 const gchar *action_name;
481 const gchar *translation_domain;
482 HildonURIAction *action = (HildonURIAction *) node->data;
483 action_name = hildon_uri_action_get_name (action);
484 translation_domain = hildon_uri_action_get_translation_domain (action);
485 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
486 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
487 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
490 if (hildon_uri_is_default_action (action, NULL)) {
491 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
493 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
495 gtk_widget_show (menu_item);
500 /* and what to do when the link is deleted */
501 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
502 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
505 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
513 modest_platform_get_icon (const gchar *name, guint icon_size)
516 GdkPixbuf* pixbuf = NULL;
517 GtkIconTheme *current_theme = NULL;
519 g_return_val_if_fail (name, NULL);
521 /* strlen == 0 is not really an error; it just
522 * means the icon is not available
524 if (!name || strlen(name) == 0)
527 current_theme = gtk_icon_theme_get_default ();
528 pixbuf = gtk_icon_theme_load_icon (current_theme, name, icon_size,
529 GTK_ICON_LOOKUP_NO_SVG,
532 g_printerr ("modest: error loading theme icon '%s': %s\n",
540 modest_platform_get_app_name (void)
542 return _("mcen_ap_name");
546 entry_insert_text (GtkEditable *editable,
555 chars = gtk_editable_get_chars (editable, 0, -1);
556 chars_length = g_utf8_strlen (chars, -1);
559 /* Show WID-INF036 */
560 if (chars_length >= 20) {
561 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
562 _CS("ckdg_ib_maximum_characters_reached"));
564 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
568 tmp = g_strndup (folder_name_forbidden_chars,
569 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
570 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
571 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
577 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
578 _CS("ckdg_ib_maximum_characters_reached"));
580 /* Write the text in the entry if it's valid */
581 g_signal_handlers_block_by_func (editable,
582 (gpointer) entry_insert_text, data);
583 gtk_editable_insert_text (editable, text, length, position);
584 g_signal_handlers_unblock_by_func (editable,
585 (gpointer) entry_insert_text, data);
588 /* Do not allow further processing */
589 g_signal_stop_emission_by_name (editable, "insert_text");
593 entry_changed (GtkEditable *editable,
597 GtkWidget *ok_button;
600 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
601 ok_button = GTK_WIDGET (buttons->data);
603 chars = gtk_editable_get_chars (editable, 0, -1);
604 g_return_if_fail (chars != NULL);
607 if (g_utf8_strlen (chars,-1) >= 20) {
608 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
609 _CS("ckdg_ib_maximum_characters_reached"));
611 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
614 g_list_free (buttons);
621 on_response (GtkDialog *dialog,
625 GtkWidget *entry, *picker;
626 TnyFolderStore *parent;
627 const gchar *new_name;
630 if (response != GTK_RESPONSE_ACCEPT)
634 entry = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY);
635 picker = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER);
637 parent = TNY_FOLDER_STORE (user_data);
638 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
641 if (picker != NULL) {
643 parent = g_object_get_data (G_OBJECT (picker), FOLDER_PICKER_CURRENT_FOLDER);
646 /* Look for another folder with the same name */
647 if (modest_tny_folder_has_subfolder_with_name (parent,
654 if (TNY_IS_ACCOUNT (parent) &&
655 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
656 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
665 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
666 NULL, _CS("ckdg_ib_folder_already_exists"));
667 /* Select the text */
668 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
669 gtk_widget_grab_focus (entry);
670 /* Do not close the dialog */
671 g_signal_stop_emission_by_name (dialog, "response");
676 typedef struct _FolderChooserData {
677 TnyFolderStore *store;
682 folder_chooser_activated (ModestFolderView *folder_view,
683 TnyFolderStore *folder,
684 FolderChooserData *userdata)
686 userdata->store = folder;
687 gtk_dialog_response (GTK_DIALOG (userdata->dialog), GTK_RESPONSE_OK);
690 static TnyFolderStore *
691 folder_chooser_dialog_run (ModestFolderView *original)
693 GtkWidget *folder_view;
694 FolderChooserData userdata = {NULL, NULL};
696 const gchar *visible_id = NULL;
698 userdata.dialog = hildon_dialog_new ();
699 pannable = hildon_pannable_area_new ();
700 folder_view = modest_platform_create_folder_view (NULL);
702 gtk_window_set_title (GTK_WINDOW (userdata.dialog), _FM("ckdg_ti_change_folder"));
704 modest_folder_view_copy_model (MODEST_FOLDER_VIEW (original),
705 MODEST_FOLDER_VIEW (folder_view));
708 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(original));
709 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view),
712 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (userdata.dialog)->vbox), pannable);
713 gtk_container_add (GTK_CONTAINER (pannable), folder_view);
714 gtk_widget_set_size_request (pannable, -1, 320);
716 gtk_widget_show (folder_view);
717 gtk_widget_show (pannable);
718 gtk_widget_show (userdata.dialog);
719 g_signal_connect (G_OBJECT (folder_view), "folder-activated",
720 G_CALLBACK (folder_chooser_activated),
721 (gpointer) &userdata);
723 gtk_dialog_run (GTK_DIALOG (userdata.dialog));
724 gtk_widget_destroy (userdata.dialog);
726 return userdata.store;
730 folder_store_get_display_name (TnyFolderStore *store)
732 if (TNY_IS_ACCOUNT (store)) {
733 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
734 return modest_conf_get_string (modest_runtime_get_conf(),
735 MODEST_CONF_DEVICE_NAME, NULL);
737 return g_strdup (tny_account_get_name (TNY_ACCOUNT (store)));
740 TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
742 fname = g_strdup (tny_folder_get_name (TNY_FOLDER (store)));
743 type = tny_folder_get_folder_type (TNY_FOLDER (store));
744 if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)) ||
745 modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
746 type = modest_tny_folder_get_local_or_mmc_folder_type (TNY_FOLDER (store));
747 if (type != TNY_FOLDER_TYPE_UNKNOWN) {
749 fname = g_strdup (modest_local_folder_info_get_type_display_name (type));
752 /* Sometimes an special folder is reported by the server as
753 NORMAL, like some versions of Dovecot */
754 if (type == TNY_FOLDER_TYPE_NORMAL ||
755 type == TNY_FOLDER_TYPE_UNKNOWN) {
756 type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
760 if (type == TNY_FOLDER_TYPE_INBOX) {
762 fname = g_strdup (_("mcen_me_folder_inbox"));
769 folder_picker_set_store (GtkButton *button, TnyFolderStore *store)
774 g_object_set_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER, NULL);
777 const gchar *icon_name = NULL;
779 g_object_ref (store);
780 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
781 store, (GDestroyNotify) g_object_unref);
782 name = folder_store_get_display_name (store);
783 hildon_button_set_value (HILDON_BUTTON (button), name);
787 if (TNY_IS_ACCOUNT (store)) {
788 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
789 icon_name = MODEST_FOLDER_ICON_LOCAL_FOLDERS;
790 else if (modest_tny_account_is_memory_card_account (TNY_ACCOUNT (store)))
791 icon_name = MODEST_FOLDER_ICON_MMC;
793 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
795 TnyFolderType type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
796 if (modest_tny_folder_is_remote_folder (TNY_FOLDER (store))) {
798 case TNY_FOLDER_TYPE_INBOX:
799 icon_name = MODEST_FOLDER_ICON_INBOX;
802 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
804 } else if (modest_tny_folder_is_local_folder (TNY_FOLDER (store))) {
806 case TNY_FOLDER_TYPE_OUTBOX:
807 icon_name = MODEST_FOLDER_ICON_OUTBOX;
809 case TNY_FOLDER_TYPE_DRAFTS:
810 icon_name = MODEST_FOLDER_ICON_DRAFTS;
812 case TNY_FOLDER_TYPE_SENT:
813 icon_name = MODEST_FOLDER_ICON_SENT;
816 icon_name = MODEST_FOLDER_ICON_NORMAL;
818 } else if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
819 icon_name = MODEST_FOLDER_ICON_MMC_FOLDER;
824 pixbuf = modest_platform_get_icon (icon_name, MODEST_ICON_SIZE_SMALL);
827 hildon_button_set_image (HILDON_BUTTON (button),
828 gtk_image_new_from_pixbuf (pixbuf));
829 g_object_unref (pixbuf);
834 /* Always returns DUPs so you must free the returned value */
836 get_next_folder_name (const gchar *suggested_name,
837 TnyFolderStore *suggested_folder)
839 const gchar *default_name = _FM("ckdg_va_new_folder_name_stub");
841 gchar *real_suggested_name;
843 if (suggested_name !=NULL) {
844 return g_strdup (suggested_name);
847 for(i = 0; i < 100; ++ i) {
848 gboolean exists = FALSE;
851 real_suggested_name = g_strdup (default_name);
853 real_suggested_name = g_strdup_printf ("%s(%d)",
854 _FM("ckdg_va_new_folder_name_stub"),
856 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
863 g_free (real_suggested_name);
866 /* Didn't find a free number */
868 real_suggested_name = g_strdup (default_name);
870 return real_suggested_name;
874 ModestFolderView *folder_view;
876 } FolderPickerHelper;
879 folder_picker_clicked (GtkButton *button,
880 FolderPickerHelper *helper)
882 TnyFolderStore *store;
884 store = folder_chooser_dialog_run (helper->folder_view);
886 const gchar *current_name;
889 folder_picker_set_store (GTK_BUTTON (button), store);
891 /* Update the name of the folder */
892 current_name = gtk_entry_get_text (helper->entry);
893 exists = modest_tny_folder_has_subfolder_with_name (store,
897 gchar *new_name = get_next_folder_name (NULL, store);
898 gtk_entry_set_text (helper->entry, new_name);
905 folder_picker_new (TnyFolderStore *suggested, FolderPickerHelper *helper)
909 button = hildon_button_new (MODEST_EDITABLE_SIZE,
910 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
912 hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 1.0);
915 folder_picker_set_store (GTK_BUTTON (button), suggested);
918 g_signal_connect (G_OBJECT (button), "clicked",
919 G_CALLBACK (folder_picker_clicked),
927 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
928 TnyFolderStore *suggested_parent,
929 const gchar *dialog_title,
930 const gchar *label_text,
931 const gchar *suggested_name,
933 gboolean show_parent,
935 TnyFolderStore **parent)
937 GtkWidget *accept_btn = NULL;
938 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
939 GtkWidget *account_picker = NULL;
940 GList *buttons = NULL;
942 GtkSizeGroup *sizegroup;
943 ModestFolderView *folder_view;
944 ModestWindow *folder_window;
945 ModestHildon2WindowMgr *window_mgr;
946 FolderPickerHelper *helper = NULL;
947 GtkWidget *top_vbox, *top_align;
949 window_mgr = (ModestHildon2WindowMgr *) modest_runtime_get_window_mgr ();
950 folder_window = modest_hildon2_window_mgr_get_folder_window (window_mgr);
951 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
953 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
955 top_vbox = gtk_vbox_new (FALSE, 0);
956 top_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
957 gtk_alignment_set_padding (GTK_ALIGNMENT (top_align), 0, 0, MODEST_MARGIN_DOUBLE, 0);
959 /* Ask the user for the folder name */
960 dialog = gtk_dialog_new_with_buttons (dialog_title,
962 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
963 _FM("ckdg_bd_new_folder_dialog_ok"),
967 /* Add accept button (with unsensitive handler) */
968 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
969 accept_btn = GTK_WIDGET (buttons->data);
971 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
974 label_entry = gtk_label_new (label_text);
975 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
976 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
978 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
979 gtk_size_group_add_widget (sizegroup, label_entry);
982 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
984 gtk_entry_set_text (GTK_ENTRY (entry), _FM("ckdg_va_new_folder_name_stub"));
985 gtk_entry_set_width_chars (GTK_ENTRY (entry),
986 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
987 g_utf8_strlen (_FM("ckdg_va_new_folder_name_stub"), -1)));
988 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
993 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
995 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
996 gtk_size_group_add_widget (sizegroup, label_location);
998 helper = g_slice_new0 (FolderPickerHelper);
999 helper->folder_view = folder_view;
1000 helper->entry = (GtkEntry *) entry;
1002 account_picker = folder_picker_new (suggested_parent, helper);
1005 g_object_unref (sizegroup);
1007 /* Connect to the response method to avoid closing the dialog
1008 when an invalid name is selected*/
1009 g_signal_connect (dialog,
1011 G_CALLBACK (on_response),
1015 /* Track entry changes */
1016 g_signal_connect (entry,
1018 G_CALLBACK (entry_insert_text),
1020 g_signal_connect (entry,
1022 G_CALLBACK (entry_changed),
1027 /* Some locales like pt_BR need this to get the full window
1029 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
1031 /* Create the hbox */
1033 hbox = gtk_hbox_new (FALSE, 12);
1034 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
1035 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
1037 /* Add hbox to dialog */
1038 gtk_box_pack_start (GTK_BOX (top_vbox),
1039 hbox, FALSE, FALSE, 0);
1040 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
1044 hbox = gtk_hbox_new (FALSE, 12);
1045 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
1046 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
1048 /* Add hbox to dialog */
1049 gtk_box_pack_start (GTK_BOX (top_vbox),
1050 hbox, FALSE, FALSE, 0);
1051 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
1053 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1054 GTK_WINDOW (dialog), parent_window);
1056 gtk_container_add (GTK_CONTAINER (top_align), top_vbox);
1057 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), top_align, TRUE, TRUE, 0);
1059 gtk_widget_show_all (GTK_WIDGET(dialog));
1061 result = gtk_dialog_run (GTK_DIALOG(dialog));
1062 if (result == GTK_RESPONSE_ACCEPT) {
1064 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1066 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
1068 g_object_ref (*parent);
1072 gtk_widget_destroy (dialog);
1075 g_slice_free (FolderPickerHelper, helper);
1077 while (gtk_events_pending ())
1078 gtk_main_iteration ();
1084 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
1085 TnyFolderStore *suggested_folder,
1086 gchar *suggested_name,
1087 gchar **folder_name,
1088 TnyFolderStore **parent_folder)
1090 gchar *real_suggested_name = NULL;
1092 ModestTnyAccountStore *acc_store;
1093 TnyAccount *account;
1095 real_suggested_name = get_next_folder_name ((const gchar *) suggested_name,
1098 /* In hildon 2.2 we always suggest the archive folder as parent */
1099 acc_store = modest_runtime_get_account_store ();
1100 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
1102 suggested_folder = (TnyFolderStore *)
1103 modest_tny_account_get_special_folder (account,
1104 TNY_FOLDER_TYPE_ARCHIVE);
1105 g_object_unref (account);
1109 /* If there is not archive folder then fallback to local folders account */
1110 if (!suggested_folder)
1111 suggested_folder = (TnyFolderStore *)
1112 modest_tny_account_store_get_local_folders_account (acc_store);
1114 result = modest_platform_run_folder_common_dialog (parent_window,
1116 _HL("ckdg_ti_new_folder"),
1117 _FM("ckdg_fi_new_folder_name"),
1118 real_suggested_name,
1124 g_free(real_suggested_name);
1130 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1131 TnyFolderStore *parent_folder,
1132 const gchar *suggested_name,
1133 gchar **folder_name)
1135 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1137 return modest_platform_run_folder_common_dialog (parent_window,
1139 _HL("ckdg_ti_rename_folder"),
1140 _HL("ckdg_fi_rename_name"),
1151 on_destroy_dialog (GtkWidget *dialog)
1153 /* This could happen when the dialogs get programatically
1154 hidden or destroyed (for example when closing the
1155 application while a dialog is being shown) */
1156 if (!GTK_IS_WIDGET (dialog))
1159 gtk_widget_destroy (dialog);
1161 if (gtk_events_pending ())
1162 gtk_main_iteration ();
1166 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1167 const gchar *message)
1172 dialog = hildon_note_new_confirmation (parent_window, message);
1173 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1174 GTK_WINDOW (dialog), parent_window);
1176 response = gtk_dialog_run (GTK_DIALOG (dialog));
1178 on_destroy_dialog (dialog);
1184 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1185 const gchar *message,
1186 const gchar *button_accept,
1187 const gchar *button_cancel)
1192 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1193 button_accept, GTK_RESPONSE_ACCEPT,
1194 button_cancel, GTK_RESPONSE_CANCEL,
1197 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1198 GTK_WINDOW (dialog), parent_window);
1200 response = gtk_dialog_run (GTK_DIALOG (dialog));
1202 on_destroy_dialog (dialog);
1208 modest_platform_run_information_dialog (GtkWindow *parent_window,
1209 const gchar *message,
1214 note = hildon_note_new_information (parent_window, message);
1216 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1217 GTK_WINDOW (note), parent_window);
1220 gtk_dialog_run (GTK_DIALOG (note));
1222 on_destroy_dialog (note);
1224 g_signal_connect_swapped (note,
1226 G_CALLBACK (on_destroy_dialog),
1229 gtk_widget_show_all (note);
1233 typedef struct _ConnectAndWaitData {
1235 GMainLoop *wait_loop;
1236 gboolean has_callback;
1238 } ConnectAndWaitData;
1242 quit_wait_loop (TnyAccount *account,
1243 ConnectAndWaitData *data)
1245 /* Set the has_callback to TRUE (means that the callback was
1246 executed and wake up every code waiting for cond to be
1248 g_mutex_lock (data->mutex);
1249 data->has_callback = TRUE;
1250 if (data->wait_loop)
1251 g_main_loop_quit (data->wait_loop);
1252 g_mutex_unlock (data->mutex);
1256 on_connection_status_changed (TnyAccount *account,
1257 TnyConnectionStatus status,
1260 TnyConnectionStatus conn_status;
1261 ConnectAndWaitData *data;
1263 /* Ignore if reconnecting or disconnected */
1264 conn_status = tny_account_get_connection_status (account);
1265 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1266 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1269 /* Remove the handler */
1270 data = (ConnectAndWaitData *) user_data;
1271 g_signal_handler_disconnect (account, data->handler);
1273 /* Quit from wait loop */
1274 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1278 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1283 /* Quit from wait loop */
1284 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1288 modest_platform_connect_and_wait (GtkWindow *parent_window,
1289 TnyAccount *account)
1291 ConnectAndWaitData *data = NULL;
1292 gboolean device_online;
1294 TnyConnectionStatus conn_status;
1295 gboolean user_requested;
1297 device = modest_runtime_get_device();
1298 device_online = tny_device_is_online (device);
1300 /* Whether the connection is user requested or automatically
1301 requested, for example via D-Bus */
1302 user_requested = (parent_window) ? TRUE : FALSE;
1304 /* If there is no account check only the device status */
1309 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1310 NULL, user_requested);
1313 /* Return if the account is already connected */
1314 conn_status = tny_account_get_connection_status (account);
1315 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1318 /* Create the helper */
1319 data = g_slice_new0 (ConnectAndWaitData);
1320 data->mutex = g_mutex_new ();
1321 data->has_callback = FALSE;
1323 /* Connect the device */
1324 if (!device_online) {
1325 /* Track account connection status changes */
1326 data->handler = g_signal_connect (account, "connection-status-changed",
1327 G_CALLBACK (on_connection_status_changed),
1329 /* Try to connect the device */
1330 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1331 NULL, user_requested);
1333 /* If the device connection failed then exit */
1334 if (!device_online && data->handler)
1337 /* Force a reconnection of the account */
1338 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1339 on_tny_camel_account_set_online_cb, data);
1342 /* Wait until the callback is executed */
1343 g_mutex_lock (data->mutex);
1344 if (!data->has_callback) {
1345 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1346 gdk_threads_leave ();
1347 g_mutex_unlock (data->mutex);
1348 g_main_loop_run (data->wait_loop);
1349 g_mutex_lock (data->mutex);
1350 gdk_threads_enter ();
1352 g_mutex_unlock (data->mutex);
1355 if (g_signal_handler_is_connected (account, data->handler))
1356 g_signal_handler_disconnect (account, data->handler);
1357 g_mutex_free (data->mutex);
1358 g_main_loop_unref (data->wait_loop);
1359 g_slice_free (ConnectAndWaitData, data);
1361 conn_status = tny_account_get_connection_status (account);
1362 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1366 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1368 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1369 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1370 /* This must be a maildir account, which does not require a connection: */
1375 return modest_platform_connect_and_wait (parent_window, account);
1379 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1382 return TRUE; /* Maybe it is something local. */
1384 gboolean result = TRUE;
1385 if (TNY_IS_FOLDER (folder_store)) {
1386 /* Get the folder's parent account: */
1387 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1388 if (account != NULL) {
1389 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1390 g_object_unref (account);
1392 } else if (TNY_IS_ACCOUNT (folder_store)) {
1393 /* Use the folder store as an account: */
1394 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1401 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1405 dialog = modest_hildon2_sort_dialog_new (parent_window);
1412 modest_platform_set_update_interval (guint minutes)
1414 #ifdef MODEST_HAVE_LIBALARM
1416 ModestConf *conf = modest_runtime_get_conf ();
1420 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1422 /* Delete any existing alarm,
1423 * because we will replace it: */
1425 if (alarmd_event_del(alarm_cookie) != 0)
1426 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1428 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1431 /* 0 means no updates: */
1436 /* Register alarm: */
1438 /* Set the interval in alarm_event_t structure: */
1439 alarm_event_t *event = alarm_event_create ();
1440 alarm_event_add_actions (event, 1);
1441 alarm_action_t *action = alarm_event_get_action (event, 0);
1442 alarm_event_set_alarm_appid (event, MODEST_ALARMD_APPID);
1443 event->alarm_time = minutes * 60; /* seconds */
1445 /* Set recurrence every few minutes: */
1446 event->recur_secs = minutes*60;
1447 event->recur_count = -1; /* Means infinite */
1449 /* Specify what should happen when the alarm happens:
1450 * It should call this D-Bus method: */
1452 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1453 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1454 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1455 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1456 action->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1458 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1459 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1460 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1461 * This is why we want to use the Alarm API instead of just g_timeout_add().
1462 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1463 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1465 event->flags = ALARM_EVENT_CONNECTED;
1467 alarm_cookie = alarmd_event_add (event);
1470 alarm_event_delete (event);
1472 /* Store the alarm ID in GConf, so we can remove it later:
1473 * This is apparently valid between application instances. */
1474 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1476 if (!alarm_cookie) {
1478 g_debug ("Error setting alarm event. \n");
1482 #endif /* MODEST_HAVE_LIBALARM */
1487 modest_platform_push_email_notification(void)
1489 gboolean screen_on, app_in_foreground;
1491 /* Get the window status */
1492 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1494 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1496 /* If the screen is on and the app is in the
1497 foreground we don't show anything */
1498 if (!(screen_on && app_in_foreground)) {
1500 _modest_platform_play_email_tone ();
1502 /* Activate LED. This must be deactivated by
1503 modest_platform_remove_new_mail_notifications */
1504 #ifdef MODEST_HAVE_MCE
1505 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1509 MCE_ACTIVATE_LED_PATTERN,
1511 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1518 modest_platform_on_new_headers_received (TnyList *header_list,
1519 gboolean show_visual)
1521 g_return_if_fail (TNY_IS_LIST(header_list));
1523 if (tny_list_get_length(header_list) == 0) {
1524 g_warning ("%s: header list is empty", __FUNCTION__);
1529 modest_platform_push_email_notification ();
1530 /* We do a return here to avoid indentation with an else */
1534 #ifdef MODEST_HAVE_HILDON_NOTIFY
1535 HildonNotification *notification;
1537 GSList *notifications_list = NULL;
1539 /* Get previous notifications ids */
1540 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1541 MODEST_CONF_NOTIFICATION_IDS,
1542 MODEST_CONF_VALUE_INT, NULL);
1544 iter = tny_list_create_iterator (header_list);
1545 while (!tny_iterator_is_done (iter)) {
1546 gchar *url = NULL, *display_address = NULL;
1547 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1548 TnyFolder *folder = tny_header_get_folder (header);
1549 gboolean first_notification = TRUE;
1553 display_address = tny_header_dup_from (header);
1554 /* string is changed in-place */
1555 modest_text_utils_get_display_address (display_address);
1557 str = tny_header_dup_subject (header);
1558 notification = hildon_notification_new (display_address,
1560 "qgn_list_messagin",
1561 MODEST_NOTIFICATION_CATEGORY);
1563 /* Create the message URL */
1564 str = tny_header_dup_uid (header);
1565 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1569 hildon_notification_add_dbus_action(notification,
1572 MODEST_DBUS_SERVICE,
1575 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1579 /* Play sound if the user wants. Show the LED
1580 pattern. Show and play just one */
1581 if (G_UNLIKELY (first_notification)) {
1582 TnyAccount *account;
1584 first_notification = FALSE;
1586 /* Set the led pattern */
1587 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1589 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1591 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1593 /* Set the account of the headers */
1594 account = tny_folder_get_account (folder);
1596 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1598 tny_account_get_id (account));
1599 g_object_unref (account);
1603 /* Notify. We need to do this in an idle because this function
1604 could be called from a thread */
1605 if (!notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL)) {
1606 g_warning ("Failed to send notification");
1609 /* Save id in the list */
1610 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1611 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1612 /* We don't listen for the "closed" signal, because we
1613 don't care about if the notification was removed or
1614 not to store the list in gconf */
1616 /* Free & carry on */
1617 g_free (display_address);
1619 g_object_unref (folder);
1620 g_object_unref (header);
1621 tny_iterator_next (iter);
1623 g_object_unref (iter);
1626 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1627 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1629 g_slist_free (notifications_list);
1631 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1635 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1638 #ifdef MODEST_HAVE_MCE
1639 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1643 MCE_DEACTIVATE_LED_PATTERN,
1645 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1651 #ifdef MODEST_HAVE_HILDON_NOTIFY
1652 GSList *notif_list = NULL;
1654 /* Get previous notifications ids */
1655 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1656 MODEST_CONF_NOTIFICATION_IDS,
1657 MODEST_CONF_VALUE_INT, NULL);
1659 while (notif_list) {
1661 NotifyNotification *notif;
1663 /* Nasty HACK to remove the notifications, set the id
1664 of the existing ones and then close them */
1665 notif_id = GPOINTER_TO_INT(notif_list->data);
1666 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1667 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1669 /* Close the notification, note that some ids could be
1670 already invalid, but we don't care because it does
1672 notify_notification_close(notif, NULL);
1673 g_object_unref(notif);
1675 /* Delete the link, it's like going to the next */
1676 notif_list = g_slist_delete_link (notif_list, notif_list);
1680 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1681 notif_list, MODEST_CONF_VALUE_INT, NULL);
1683 g_slist_free (notif_list);
1685 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1691 modest_platform_get_global_settings_dialog ()
1693 return modest_hildon2_global_settings_dialog_new ();
1697 modest_platform_show_help (GtkWindow *parent_window,
1698 const gchar *help_id)
1704 modest_platform_show_search_messages (GtkWindow *parent_window)
1706 osso_return_t result = OSSO_ERROR;
1708 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1709 "osso_global_search",
1710 "search_email", NULL, DBUS_TYPE_INVALID);
1712 if (result != OSSO_OK) {
1713 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1718 modest_platform_show_addressbook (GtkWindow *parent_window)
1720 osso_return_t result = OSSO_ERROR;
1722 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1724 "top_application", NULL, DBUS_TYPE_INVALID);
1726 if (result != OSSO_OK) {
1727 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1732 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1734 GtkWidget *widget = modest_folder_view_new (query);
1736 /* Show one account by default */
1737 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1738 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1740 /* Restore settings */
1741 modest_widget_memory_restore (modest_runtime_get_conf(),
1743 MODEST_CONF_FOLDER_VIEW_KEY);
1749 banner_finish (gpointer data, GObject *object)
1751 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1752 modest_window_mgr_unregister_banner (mgr);
1753 g_object_unref (mgr);
1757 modest_platform_information_banner (GtkWidget *parent,
1758 const gchar *icon_name,
1761 GtkWidget *banner, *banner_parent = NULL;
1762 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1764 if (modest_window_mgr_get_num_windows (mgr) == 0)
1767 if (parent && GTK_IS_WINDOW (parent)) {
1768 /* If the window is the active one then show the
1769 banner on top of this window */
1770 if (gtk_window_is_active (GTK_WINDOW (parent)))
1771 banner_parent = parent;
1772 /* If the window is not the topmost but it's visible
1773 (it's minimized for example) then show the banner
1775 else if (GTK_WIDGET_VISIBLE (parent))
1776 banner_parent = NULL;
1777 /* If the window is hidden (like the main window when
1778 running in the background) then do not show
1785 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1787 modest_window_mgr_register_banner (mgr);
1789 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1793 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1794 const gchar *icon_name,
1800 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1803 banner = hildon_banner_show_information (parent, icon_name, text);
1804 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1808 modest_platform_animation_banner (GtkWidget *parent,
1809 const gchar *animation_name,
1812 GtkWidget *inf_note = NULL;
1814 g_return_val_if_fail (text != NULL, NULL);
1816 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1819 /* If the parent is not visible then do not show */
1820 if (parent && !GTK_WIDGET_VISIBLE (parent))
1823 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1831 TnyAccount *account;
1834 } CheckAccountIdleData;
1836 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1839 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1841 gboolean stop_trying = FALSE;
1842 g_return_val_if_fail (data && data->account, FALSE);
1844 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1845 tny_account_get_connection_status (data->account));
1847 if (data && data->account &&
1848 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1849 * after which the account is likely to be usable, or never likely to be usable soon: */
1850 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1852 data->is_online = TRUE;
1856 /* Give up if we have tried too many times: */
1857 if (data->count_tries >= NUMBER_OF_TRIES) {
1860 /* Wait for another timeout: */
1861 ++(data->count_tries);
1866 /* Allow the function that requested this idle callback to continue: */
1868 g_main_loop_quit (data->loop);
1871 g_object_unref (data->account);
1873 return FALSE; /* Don't call this again. */
1875 return TRUE; /* Call this timeout callback again. */
1879 /* Return TRUE immediately if the account is already online,
1880 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1881 * soon as the account is online, or FALSE if the account does
1882 * not become online in the NUMBER_OF_TRIES seconds.
1883 * This is useful when the D-Bus method was run immediately after
1884 * the application was started (when using D-Bus activation),
1885 * because the account usually takes a short time to go online.
1886 * The return value is maybe not very useful.
1889 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1893 g_return_val_if_fail (account, FALSE);
1895 if (!tny_device_is_online (modest_runtime_get_device())) {
1896 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1900 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1901 * so we avoid wait unnecessarily: */
1902 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1905 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1906 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1907 * we want to avoid. */
1908 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1911 /* This blocks on the result: */
1912 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1913 data->is_online = FALSE;
1914 data->account = account;
1915 g_object_ref (data->account);
1916 data->count_tries = 0;
1918 GMainContext *context = NULL; /* g_main_context_new (); */
1919 data->loop = g_main_loop_new (context, FALSE /* not running */);
1921 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1923 /* This main loop will run until the idle handler has stopped it: */
1924 g_main_loop_run (data->loop);
1926 g_main_loop_unref (data->loop);
1927 /* g_main_context_unref (context); */
1929 is_online = data->is_online;
1930 g_slice_free (CheckAccountIdleData, data);
1938 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1940 /* GTK_RESPONSE_HELP means we need to show the certificate */
1941 if (response_id == GTK_RESPONSE_APPLY) {
1945 /* Do not close the dialog */
1946 g_signal_stop_emission_by_name (dialog, "response");
1948 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1949 note = hildon_note_new_information (NULL, msg);
1950 gtk_dialog_run (GTK_DIALOG(note));
1951 gtk_widget_destroy (note);
1957 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1958 const gchar *certificate)
1963 HildonWindowStack *stack;
1965 stack = hildon_window_stack_get_default ();
1966 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1969 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1974 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1977 /* We use GTK_RESPONSE_APPLY because we want the button in the
1978 middle of OK and CANCEL the same as the browser does for
1979 example. With GTK_RESPONSE_HELP the view button is aligned
1980 to the left while the other two to the right */
1981 note = hildon_note_new_confirmation_add_buttons (
1984 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1985 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1986 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1989 g_signal_connect (G_OBJECT(note), "response",
1990 G_CALLBACK(on_cert_dialog_response),
1991 (gpointer) certificate);
1993 response = gtk_dialog_run(GTK_DIALOG(note));
1995 on_destroy_dialog (note);
1998 return response == GTK_RESPONSE_OK;
2002 modest_platform_run_alert_dialog (const gchar* prompt,
2003 gboolean is_question)
2005 ModestWindow *top_win;
2006 HildonWindowStack *stack;
2008 stack = hildon_window_stack_get_default ();
2009 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
2012 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
2017 gboolean retval = TRUE;
2019 /* The Tinymail documentation says that we should show Yes and No buttons,
2020 * when it is a question.
2021 * Obviously, we need tinymail to use more specific error codes instead,
2022 * so we know what buttons to show. */
2023 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
2025 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2026 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
2028 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
2029 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
2031 on_destroy_dialog (dialog);
2033 /* Just show the error text and use the default response: */
2034 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
2042 GtkWindow *parent_window;
2043 ModestConnectedPerformer callback;
2044 TnyAccount *account;
2051 on_went_online_info_free (OnWentOnlineInfo *info)
2053 /* And if we cleanup, we DO cleanup :-) */
2056 g_object_unref (info->device);
2059 if (info->parent_window)
2060 g_object_unref (info->parent_window);
2062 g_object_unref (info->account);
2064 g_slice_free (OnWentOnlineInfo, info);
2066 /* We're done ... */
2072 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
2074 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2076 /* Now it's really time to callback to the caller. If going online didn't succeed,
2077 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
2078 * canceled will be set. Etcetera etcetera. */
2080 if (info->callback) {
2081 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2084 /* This is our last call, we must cleanup here if we didn't yet do that */
2085 on_went_online_info_free (info);
2092 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2094 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2095 info->iap = g_strdup (iap_id);
2097 if (canceled || err || !info->account) {
2099 /* If there's a problem or if there's no account (then that's it for us, we callback
2100 * the caller's callback now. He'll have to handle err or canceled, of course.
2101 * We are not really online, as the account is not really online here ... */
2103 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2104 * this info. We don't cleanup err, Tinymail does that! */
2106 if (info->callback) {
2108 /* info->account can be NULL here, this means that the user did not
2109 * provide a nice account instance. We'll assume that the user knows
2110 * what he's doing and is happy with just the device going online.
2112 * We can't do magic, we don't know what account the user wants to
2113 * see going online. So just the device goes online, end of story */
2115 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2118 } else if (info->account) {
2120 /* If there's no problem and if we have an account, we'll put the account
2121 * online too. When done, the callback of bringing the account online
2122 * will callback the caller's callback. This is the most normal case. */
2124 info->device = TNY_DEVICE (g_object_ref (device));
2126 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2127 on_account_went_online, info);
2129 /* The on_account_went_online cb frees up the info, go look if you
2130 * don't believe me! (so we return here) */
2135 /* We cleanup if we are not bringing the account online too */
2136 on_went_online_info_free (info);
2142 modest_platform_connect_and_perform (GtkWindow *parent_window,
2144 TnyAccount *account,
2145 ModestConnectedPerformer callback,
2148 gboolean device_online;
2150 TnyConnectionStatus conn_status;
2151 OnWentOnlineInfo *info;
2153 device = modest_runtime_get_device();
2154 device_online = tny_device_is_online (device);
2156 /* If there is no account check only the device status */
2159 if (device_online) {
2161 /* We promise to instantly perform the callback, so ... */
2163 callback (FALSE, NULL, parent_window, account, user_data);
2168 info = g_slice_new0 (OnWentOnlineInfo);
2171 info->device = NULL;
2172 info->account = NULL;
2175 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2177 info->parent_window = NULL;
2178 info->user_data = user_data;
2179 info->callback = callback;
2181 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2182 force, on_conic_device_went_online,
2185 /* We'll cleanup in on_conic_device_went_online */
2188 /* The other code has no more reason to run. This is all that we can do for the
2189 * caller (he should have given us a nice and clean account instance!). We
2190 * can't do magic, we don't know what account he intends to bring online. So
2191 * we'll just bring the device online (and await his false bug report). */
2197 /* Return if the account is already connected */
2199 conn_status = tny_account_get_connection_status (account);
2200 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2202 /* We promise to instantly perform the callback, so ... */
2204 callback (FALSE, NULL, parent_window, account, user_data);
2210 /* Else, we are in a state that requires that we go online before we
2211 * call the caller's callback. */
2213 info = g_slice_new0 (OnWentOnlineInfo);
2215 info->device = NULL;
2217 info->account = TNY_ACCOUNT (g_object_ref (account));
2220 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2222 info->parent_window = NULL;
2224 /* So we'll put the callback away for later ... */
2226 info->user_data = user_data;
2227 info->callback = callback;
2229 if (!device_online) {
2231 /* If also the device is offline, then we connect both the device
2232 * and the account */
2234 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2235 force, on_conic_device_went_online,
2240 /* If the device is online, we'll just connect the account */
2242 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2243 on_account_went_online, info);
2246 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2247 * in both situations, go look if you don't believe me! */
2253 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2255 TnyFolderStore *folder_store,
2256 ModestConnectedPerformer callback,
2259 TnyAccount *account = NULL;
2261 if (!folder_store ||
2262 (TNY_IS_MERGE_FOLDER (folder_store) &&
2263 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2265 /* We promise to instantly perform the callback, so ... */
2267 GError *error = NULL;
2268 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2269 "Unable to move or not found folder");
2270 callback (FALSE, error, parent_window, NULL, user_data);
2271 g_error_free (error);
2275 } else if (TNY_IS_FOLDER (folder_store)) {
2276 /* Get the folder's parent account: */
2277 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2278 } else if (TNY_IS_ACCOUNT (folder_store)) {
2279 /* Use the folder store as an account: */
2280 account = TNY_ACCOUNT (g_object_ref (folder_store));
2283 if (account && (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE)) {
2284 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2285 /* No need to connect a local account */
2287 callback (FALSE, NULL, parent_window, account, user_data);
2292 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2296 g_object_unref (account);
2300 src_account_connect_performer (gboolean canceled,
2302 GtkWindow *parent_window,
2303 TnyAccount *src_account,
2306 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2308 if (canceled || err) {
2309 /* If there was any error call the user callback */
2310 info->callback (canceled, err, parent_window, src_account, info->data);
2312 /* Connect the destination account */
2313 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2314 TNY_FOLDER_STORE (info->dst_account),
2315 info->callback, info->data);
2318 /* Free the info object */
2319 g_object_unref (info->dst_account);
2320 g_slice_free (DoubleConnectionInfo, info);
2325 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2327 TnyFolderStore *folder_store,
2328 DoubleConnectionInfo *connect_info)
2330 modest_platform_connect_if_remote_and_perform(parent_window,
2333 src_account_connect_performer,
2338 modest_platform_get_account_settings_wizard (void)
2340 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2342 return GTK_WIDGET (dialog);
2346 modest_platform_get_current_connection (void)
2348 TnyDevice *device = NULL;
2349 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2351 device = modest_runtime_get_device ();
2353 if (!tny_device_is_online (device))
2354 return MODEST_CONNECTED_VIA_ANY;
2356 #ifdef MODEST_HAVE_CONIC
2358 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2360 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2361 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2362 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2364 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2365 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2366 !strcmp (bearer_type, "WIMAX")) {
2367 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2369 retval = MODEST_CONNECTED_VIA_ANY;
2372 g_object_unref (iap);
2375 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2376 #endif /* MODEST_HAVE_CONIC */
2383 modest_platform_check_memory_low (ModestWindow *win,
2388 /* are we in low memory state? */
2389 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2391 if (win && lowmem && visuals)
2392 modest_platform_run_information_dialog (
2394 _KR("memr_ib_operation_disabled"),
2398 g_debug ("%s: low memory reached. disallowing some operations",
2405 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2411 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2414 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2415 GTK_WINDOW (dialog),
2417 gtk_widget_show_all (dialog);
2419 g_signal_connect_swapped (dialog, "response",
2420 G_CALLBACK (gtk_widget_destroy),
2425 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2431 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2434 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2435 GTK_WINDOW (dialog),
2437 gtk_widget_show_all (dialog);
2439 g_signal_connect_swapped (dialog, "response",
2440 G_CALLBACK (gtk_widget_destroy),
2445 modest_platform_get_osso_context (void)
2447 return modest_maemo_utils_get_osso_context ();
2451 _modest_platform_play_email_tone (void)
2454 gint mail_volume_int;
2456 ca_context *ca_con = NULL;
2457 ca_proplist *pl = NULL;
2459 #ifdef MODEST_USE_PROFILE
2460 gchar *active_profile;
2463 active_profile = profile_get_profile ();
2464 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2465 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2466 mail_volume_int = profile_parse_int (mail_volume);
2467 g_free (mail_volume);
2468 g_free (active_profile);
2470 mail_tone = MAIL_TONE;
2471 mail_volume_int = 100;
2474 if (mail_tone && !strstr (mail_tone, "/")) {
2477 tmp = g_strconcat ("/usr/share/sounds", mail_tone, NULL);
2482 if (mail_volume_int > 0) {
2484 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2485 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2489 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2490 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2491 ca_context_destroy(ca_con);
2495 ca_proplist_create(&pl);
2496 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2497 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2499 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2500 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2502 ca_proplist_destroy(pl);
2503 ca_context_destroy(ca_con);
2509 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
2510 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
2511 #define MOVE_TO_DIALOG_ACTION_BUTTON "action-button"
2512 #define MOVE_TO_DIALOG_SELECTION_LABEL "selection-label"
2513 #define MOVE_TO_DIALOG_SHOWING_FOLDERS "showing-folders"
2514 #define MOVE_TO_DIALOG_PANNABLE "pannable"
2517 move_to_dialog_show_accounts (GtkWidget *dialog)
2519 GtkWidget *selection_label;
2520 GtkWidget *back_button;
2521 GtkWidget *folder_view;
2522 GtkWidget *pannable;
2523 GtkWidget *action_button;
2525 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2526 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2527 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2528 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2529 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2531 gtk_widget_set_sensitive (back_button, FALSE);
2532 gtk_widget_set_sensitive (action_button, FALSE);
2534 /* Need to set this here, otherwise callbacks called because
2535 of filtering won't perform correctly */
2536 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (FALSE));
2538 gtk_label_set_text (GTK_LABEL (selection_label), "");
2539 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2540 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
2541 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2542 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2544 g_object_set (G_OBJECT (folder_view),
2545 "hildon-ui-mode", HILDON_UI_MODE_NORMAL,
2550 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
2552 GtkWidget *selection_label;
2553 GtkWidget *back_button;
2554 GtkWidget *folder_view;
2555 TnyAccount *account;
2556 const gchar *account_id;
2557 gchar *selection_label_text;
2558 GtkWidget *pannable;
2559 GtkWidget *action_button;
2561 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2562 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2563 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2564 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2565 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2567 gtk_widget_set_sensitive (back_button, TRUE);
2568 gtk_widget_set_sensitive (action_button, FALSE);
2570 /* Need to set this here, otherwise callbacks called because
2571 of filtering won't perform correctly */
2572 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (TRUE));
2574 g_object_set (G_OBJECT (folder_view),
2575 "hildon-ui-mode", HILDON_UI_MODE_EDIT,
2578 account = TNY_ACCOUNT (folder_store);
2579 if (modest_tny_account_is_virtual_local_folders (account)) {
2581 account_id = tny_account_get_id (account);
2582 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2583 MODEST_CONF_DEVICE_NAME, NULL);
2585 selection_label_text = g_strconcat (device_name, "/", NULL);
2586 g_free (device_name);
2588 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2590 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2591 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2592 } else if (modest_tny_account_is_memory_card_account (account)) {
2593 account_id = tny_account_get_id (account);
2594 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2595 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2596 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2598 account_id = tny_account_get_id (account);
2600 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2601 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2602 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2603 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2604 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2606 gtk_label_set_text (GTK_LABEL (selection_label), selection_label_text);
2607 g_free (selection_label_text);
2609 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
2612 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
2613 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
2614 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2615 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2619 move_to_dialog_set_selected_folder (GtkWidget *dialog, TnyFolderStore *folder_store)
2621 GtkWidget *selection_label;
2622 GtkWidget *action_button;
2625 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2626 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2628 gtk_widget_set_sensitive (action_button, TRUE);
2630 if (TNY_IS_FOLDER (folder_store)) {
2631 folder_name = modest_tny_folder_get_display_name (TNY_FOLDER (folder_store));
2632 } else if (TNY_IS_ACCOUNT (folder_store)) {
2633 folder_name = g_strdup (tny_account_get_name (TNY_ACCOUNT (folder_store)));
2635 folder_name = g_strdup ("");
2638 gtk_label_set_text (GTK_LABEL (selection_label), folder_name);
2639 g_free (folder_name);
2644 on_move_to_dialog_back_clicked (GtkButton *button,
2647 GtkWidget *dialog = (GtkWidget *) userdata;
2648 ModestFolderView *folder_view;
2650 /* Revert the effect of show_folders filters */
2651 folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2652 modest_folder_view_set_account_id_of_visible_server_account (folder_view, NULL);
2653 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2654 modest_folder_view_unset_filter (folder_view, MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2655 modest_folder_view_unset_filter (folder_view, MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2657 /* Back to show accounts */
2658 move_to_dialog_show_accounts (dialog);
2662 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2664 GtkTreeViewColumn *column,
2667 TnyFolderStore *selected;
2669 GtkWidget *folder_view;
2670 gboolean showing_folders;
2672 dialog = (GtkWidget *) user_data;
2673 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2674 if (!showing_folders) {
2675 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2677 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2679 move_to_dialog_show_folders (dialog, selected);
2685 on_move_to_dialog_selection_changed (GtkTreeSelection *selection,
2688 gboolean showing_folders;
2691 dialog = (GtkWidget *) user_data;
2692 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2693 if (showing_folders) {
2694 TnyFolderStore *selected;
2695 GtkWidget *folder_view;
2697 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2698 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2701 move_to_dialog_set_selected_folder (dialog, selected);
2702 g_object_unref (selected);
2708 on_move_to_dialog_action_clicked (GtkButton *selection,
2711 TnyFolderStore *selected;
2713 GtkWidget *folder_view;
2714 gboolean showing_folders;
2716 dialog = (GtkWidget *) user_data;
2717 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2718 if (showing_folders) {
2719 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2720 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2723 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
2728 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2729 GtkWidget **folder_view)
2731 GtkWidget *dialog, *folder_view_container;
2733 GtkWidget *buttons_hbox;
2734 GtkWidget *back_button, *selection_label;
2735 GdkPixbuf *back_pixbuf;
2736 GtkWidget *top_vbox;
2737 GtkWidget *action_button;
2738 GtkTreeSelection *selection;
2740 /* Create dialog. We cannot use a touch selector because we
2741 need to use here the folder view widget directly */
2742 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2743 GTK_WINDOW (parent_window),
2744 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2745 GTK_DIALOG_DESTROY_WITH_PARENT,
2746 _HL("wdgt_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2749 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
2750 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_NONE);
2751 top_vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
2753 /* Create folder view */
2754 *folder_view = modest_platform_create_folder_view (NULL);
2756 modest_folder_view_set_cell_style (MODEST_FOLDER_VIEW (*folder_view),
2757 MODEST_FOLDER_VIEW_CELL_STYLE_COMPACT);
2758 modest_folder_view_show_message_count (MODEST_FOLDER_VIEW (*folder_view),
2760 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2761 (TnyAccountStore *) modest_runtime_get_account_store ());
2763 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
2764 back_button = gtk_button_new ();
2765 back_pixbuf = modest_platform_get_icon (_FM("filemanager_folder_up"), MODEST_ICON_SIZE_BIG);
2767 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
2768 g_object_unref (back_pixbuf);
2770 selection_label = gtk_label_new ("");
2771 gtk_misc_set_alignment (GTK_MISC (selection_label), 0.0, 0.5);
2773 action_button = gtk_button_new ();
2774 gtk_container_add (GTK_CONTAINER (action_button), selection_label);
2776 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
2777 gtk_box_pack_start (GTK_BOX (buttons_hbox), action_button, TRUE, TRUE, 0);
2778 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
2779 gtk_widget_set_sensitive (GTK_WIDGET (action_button), FALSE);
2780 gtk_box_pack_start (GTK_BOX (top_vbox), buttons_hbox, FALSE, FALSE, 0);
2782 /* Create pannable and add it to the dialog */
2783 folder_view_container = hildon_pannable_area_new ();
2784 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2785 gtk_box_pack_start (GTK_BOX (top_vbox), folder_view_container, TRUE, TRUE, 0);
2787 gtk_container_add (GTK_CONTAINER (align), top_vbox);
2788 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), align, TRUE, TRUE, 0);
2790 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2792 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2793 gtk_widget_show (folder_view_container);
2794 gtk_widget_show (align);
2795 gtk_widget_show (top_vbox);
2796 gtk_widget_show (*folder_view);
2797 gtk_widget_show_all (back_button);
2798 gtk_widget_show (selection_label);
2799 gtk_widget_show (action_button);
2800 gtk_widget_show (buttons_hbox);
2801 gtk_widget_show (dialog);
2803 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
2804 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
2805 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON, action_button);
2806 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL, selection_label);
2807 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE, folder_view_container);
2809 /* Simulate the behaviour of a HildonPickerDialog by emitting
2810 a response when a folder is selected */
2811 g_signal_connect (*folder_view, "row-activated",
2812 G_CALLBACK (on_move_to_dialog_folder_activated),
2815 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (*folder_view));
2816 g_signal_connect (selection, "changed",
2817 G_CALLBACK (on_move_to_dialog_selection_changed),
2820 g_signal_connect (action_button, "clicked",
2821 G_CALLBACK (on_move_to_dialog_action_clicked),
2824 g_signal_connect (back_button, "clicked",
2825 G_CALLBACK (on_move_to_dialog_back_clicked),
2828 move_to_dialog_show_accounts (dialog);
2834 modest_platform_get_list_to_move (ModestWindow *window)
2836 TnyList *list = NULL;
2838 if (MODEST_IS_HEADER_WINDOW (window)) {
2839 ModestHeaderView *header_view;
2841 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2842 list = modest_header_view_get_selected_headers (header_view);
2843 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2844 ModestFolderView *folder_view;
2845 TnyFolderStore *selected_folder;
2847 list = TNY_LIST (tny_simple_list_new ());
2848 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2849 selected_folder = modest_folder_view_get_selected (folder_view);
2850 if (selected_folder) {
2851 tny_list_prepend (list, G_OBJECT (selected_folder));
2852 g_object_unref (selected_folder);
2855 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2858 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2860 list = TNY_LIST (tny_simple_list_new ());
2861 tny_list_prepend (list, G_OBJECT (header));
2862 g_object_unref (header);
2865 g_return_val_if_reached (NULL);