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 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1607 /* Save id in the list */
1608 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1609 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1610 /* We don't listen for the "closed" signal, because we
1611 don't care about if the notification was removed or
1612 not to store the list in gconf */
1614 /* Free & carry on */
1615 g_free (display_address);
1617 g_object_unref (folder);
1618 g_object_unref (header);
1619 tny_iterator_next (iter);
1621 g_object_unref (iter);
1624 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1625 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1627 g_slist_free (notifications_list);
1629 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1633 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1636 #ifdef MODEST_HAVE_MCE
1637 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1641 MCE_DEACTIVATE_LED_PATTERN,
1643 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1649 #ifdef MODEST_HAVE_HILDON_NOTIFY
1650 GSList *notif_list = NULL;
1652 /* Get previous notifications ids */
1653 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1654 MODEST_CONF_NOTIFICATION_IDS,
1655 MODEST_CONF_VALUE_INT, NULL);
1657 while (notif_list) {
1659 NotifyNotification *notif;
1661 /* Nasty HACK to remove the notifications, set the id
1662 of the existing ones and then close them */
1663 notif_id = GPOINTER_TO_INT(notif_list->data);
1664 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1665 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1667 /* Close the notification, note that some ids could be
1668 already invalid, but we don't care because it does
1670 notify_notification_close(notif, NULL);
1671 g_object_unref(notif);
1673 /* Delete the link, it's like going to the next */
1674 notif_list = g_slist_delete_link (notif_list, notif_list);
1678 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1679 notif_list, MODEST_CONF_VALUE_INT, NULL);
1681 g_slist_free (notif_list);
1683 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1689 modest_platform_get_global_settings_dialog ()
1691 return modest_hildon2_global_settings_dialog_new ();
1695 modest_platform_show_help (GtkWindow *parent_window,
1696 const gchar *help_id)
1702 modest_platform_show_search_messages (GtkWindow *parent_window)
1704 osso_return_t result = OSSO_ERROR;
1706 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1707 "osso_global_search",
1708 "search_email", NULL, DBUS_TYPE_INVALID);
1710 if (result != OSSO_OK) {
1711 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1716 modest_platform_show_addressbook (GtkWindow *parent_window)
1718 osso_return_t result = OSSO_ERROR;
1720 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1722 "top_application", NULL, DBUS_TYPE_INVALID);
1724 if (result != OSSO_OK) {
1725 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1730 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1732 GtkWidget *widget = modest_folder_view_new (query);
1734 /* Show one account by default */
1735 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1736 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1738 /* Restore settings */
1739 modest_widget_memory_restore (modest_runtime_get_conf(),
1741 MODEST_CONF_FOLDER_VIEW_KEY);
1747 banner_finish (gpointer data, GObject *object)
1749 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1750 modest_window_mgr_unregister_banner (mgr);
1751 g_object_unref (mgr);
1755 modest_platform_information_banner (GtkWidget *parent,
1756 const gchar *icon_name,
1759 GtkWidget *banner, *banner_parent = NULL;
1760 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1762 if (modest_window_mgr_get_num_windows (mgr) == 0)
1765 if (parent && GTK_IS_WINDOW (parent)) {
1766 /* If the window is the active one then show the
1767 banner on top of this window */
1768 if (gtk_window_is_active (GTK_WINDOW (parent)))
1769 banner_parent = parent;
1770 /* If the window is not the topmost but it's visible
1771 (it's minimized for example) then show the banner
1773 else if (GTK_WIDGET_VISIBLE (parent))
1774 banner_parent = NULL;
1775 /* If the window is hidden (like the main window when
1776 running in the background) then do not show
1783 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1785 modest_window_mgr_register_banner (mgr);
1787 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1791 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1792 const gchar *icon_name,
1798 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1801 banner = hildon_banner_show_information (parent, icon_name, text);
1802 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1806 modest_platform_animation_banner (GtkWidget *parent,
1807 const gchar *animation_name,
1810 GtkWidget *inf_note = NULL;
1812 g_return_val_if_fail (text != NULL, NULL);
1814 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1817 /* If the parent is not visible then do not show */
1818 if (parent && !GTK_WIDGET_VISIBLE (parent))
1821 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1829 TnyAccount *account;
1832 } CheckAccountIdleData;
1834 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1837 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1839 gboolean stop_trying = FALSE;
1840 g_return_val_if_fail (data && data->account, FALSE);
1842 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1843 tny_account_get_connection_status (data->account));
1845 if (data && data->account &&
1846 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1847 * after which the account is likely to be usable, or never likely to be usable soon: */
1848 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1850 data->is_online = TRUE;
1854 /* Give up if we have tried too many times: */
1855 if (data->count_tries >= NUMBER_OF_TRIES) {
1858 /* Wait for another timeout: */
1859 ++(data->count_tries);
1864 /* Allow the function that requested this idle callback to continue: */
1866 g_main_loop_quit (data->loop);
1869 g_object_unref (data->account);
1871 return FALSE; /* Don't call this again. */
1873 return TRUE; /* Call this timeout callback again. */
1877 /* Return TRUE immediately if the account is already online,
1878 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1879 * soon as the account is online, or FALSE if the account does
1880 * not become online in the NUMBER_OF_TRIES seconds.
1881 * This is useful when the D-Bus method was run immediately after
1882 * the application was started (when using D-Bus activation),
1883 * because the account usually takes a short time to go online.
1884 * The return value is maybe not very useful.
1887 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1891 g_return_val_if_fail (account, FALSE);
1893 if (!tny_device_is_online (modest_runtime_get_device())) {
1894 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1898 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1899 * so we avoid wait unnecessarily: */
1900 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1903 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1904 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1905 * we want to avoid. */
1906 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1909 /* This blocks on the result: */
1910 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1911 data->is_online = FALSE;
1912 data->account = account;
1913 g_object_ref (data->account);
1914 data->count_tries = 0;
1916 GMainContext *context = NULL; /* g_main_context_new (); */
1917 data->loop = g_main_loop_new (context, FALSE /* not running */);
1919 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1921 /* This main loop will run until the idle handler has stopped it: */
1922 g_main_loop_run (data->loop);
1924 g_main_loop_unref (data->loop);
1925 /* g_main_context_unref (context); */
1927 is_online = data->is_online;
1928 g_slice_free (CheckAccountIdleData, data);
1936 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1938 /* GTK_RESPONSE_HELP means we need to show the certificate */
1939 if (response_id == GTK_RESPONSE_APPLY) {
1943 /* Do not close the dialog */
1944 g_signal_stop_emission_by_name (dialog, "response");
1946 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1947 note = hildon_note_new_information (NULL, msg);
1948 gtk_dialog_run (GTK_DIALOG(note));
1949 gtk_widget_destroy (note);
1955 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1956 const gchar *certificate)
1961 HildonWindowStack *stack;
1963 stack = hildon_window_stack_get_default ();
1964 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1967 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1972 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1975 /* We use GTK_RESPONSE_APPLY because we want the button in the
1976 middle of OK and CANCEL the same as the browser does for
1977 example. With GTK_RESPONSE_HELP the view button is aligned
1978 to the left while the other two to the right */
1979 note = hildon_note_new_confirmation_add_buttons (
1982 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1983 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1984 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1987 g_signal_connect (G_OBJECT(note), "response",
1988 G_CALLBACK(on_cert_dialog_response),
1989 (gpointer) certificate);
1991 response = gtk_dialog_run(GTK_DIALOG(note));
1993 on_destroy_dialog (note);
1996 return response == GTK_RESPONSE_OK;
2000 modest_platform_run_alert_dialog (const gchar* prompt,
2001 gboolean is_question)
2003 ModestWindow *top_win;
2004 HildonWindowStack *stack;
2006 stack = hildon_window_stack_get_default ();
2007 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
2010 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
2015 gboolean retval = TRUE;
2017 /* The Tinymail documentation says that we should show Yes and No buttons,
2018 * when it is a question.
2019 * Obviously, we need tinymail to use more specific error codes instead,
2020 * so we know what buttons to show. */
2021 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
2023 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2024 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
2026 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
2027 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
2029 on_destroy_dialog (dialog);
2031 /* Just show the error text and use the default response: */
2032 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
2040 GtkWindow *parent_window;
2041 ModestConnectedPerformer callback;
2042 TnyAccount *account;
2049 on_went_online_info_free (OnWentOnlineInfo *info)
2051 /* And if we cleanup, we DO cleanup :-) */
2054 g_object_unref (info->device);
2057 if (info->parent_window)
2058 g_object_unref (info->parent_window);
2060 g_object_unref (info->account);
2062 g_slice_free (OnWentOnlineInfo, info);
2064 /* We're done ... */
2070 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
2072 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2074 /* Now it's really time to callback to the caller. If going online didn't succeed,
2075 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
2076 * canceled will be set. Etcetera etcetera. */
2078 if (info->callback) {
2079 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2082 /* This is our last call, we must cleanup here if we didn't yet do that */
2083 on_went_online_info_free (info);
2090 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2092 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2093 info->iap = g_strdup (iap_id);
2095 if (canceled || err || !info->account) {
2097 /* If there's a problem or if there's no account (then that's it for us, we callback
2098 * the caller's callback now. He'll have to handle err or canceled, of course.
2099 * We are not really online, as the account is not really online here ... */
2101 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2102 * this info. We don't cleanup err, Tinymail does that! */
2104 if (info->callback) {
2106 /* info->account can be NULL here, this means that the user did not
2107 * provide a nice account instance. We'll assume that the user knows
2108 * what he's doing and is happy with just the device going online.
2110 * We can't do magic, we don't know what account the user wants to
2111 * see going online. So just the device goes online, end of story */
2113 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2116 } else if (info->account) {
2118 /* If there's no problem and if we have an account, we'll put the account
2119 * online too. When done, the callback of bringing the account online
2120 * will callback the caller's callback. This is the most normal case. */
2122 info->device = TNY_DEVICE (g_object_ref (device));
2124 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2125 on_account_went_online, info);
2127 /* The on_account_went_online cb frees up the info, go look if you
2128 * don't believe me! (so we return here) */
2133 /* We cleanup if we are not bringing the account online too */
2134 on_went_online_info_free (info);
2140 modest_platform_connect_and_perform (GtkWindow *parent_window,
2142 TnyAccount *account,
2143 ModestConnectedPerformer callback,
2146 gboolean device_online;
2148 TnyConnectionStatus conn_status;
2149 OnWentOnlineInfo *info;
2151 device = modest_runtime_get_device();
2152 device_online = tny_device_is_online (device);
2154 /* If there is no account check only the device status */
2157 if (device_online) {
2159 /* We promise to instantly perform the callback, so ... */
2161 callback (FALSE, NULL, parent_window, account, user_data);
2166 info = g_slice_new0 (OnWentOnlineInfo);
2169 info->device = NULL;
2170 info->account = NULL;
2173 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2175 info->parent_window = NULL;
2176 info->user_data = user_data;
2177 info->callback = callback;
2179 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2180 force, on_conic_device_went_online,
2183 /* We'll cleanup in on_conic_device_went_online */
2186 /* The other code has no more reason to run. This is all that we can do for the
2187 * caller (he should have given us a nice and clean account instance!). We
2188 * can't do magic, we don't know what account he intends to bring online. So
2189 * we'll just bring the device online (and await his false bug report). */
2195 /* Return if the account is already connected */
2197 conn_status = tny_account_get_connection_status (account);
2198 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2200 /* We promise to instantly perform the callback, so ... */
2202 callback (FALSE, NULL, parent_window, account, user_data);
2208 /* Else, we are in a state that requires that we go online before we
2209 * call the caller's callback. */
2211 info = g_slice_new0 (OnWentOnlineInfo);
2213 info->device = NULL;
2215 info->account = TNY_ACCOUNT (g_object_ref (account));
2218 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2220 info->parent_window = NULL;
2222 /* So we'll put the callback away for later ... */
2224 info->user_data = user_data;
2225 info->callback = callback;
2227 if (!device_online) {
2229 /* If also the device is offline, then we connect both the device
2230 * and the account */
2232 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2233 force, on_conic_device_went_online,
2238 /* If the device is online, we'll just connect the account */
2240 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2241 on_account_went_online, info);
2244 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2245 * in both situations, go look if you don't believe me! */
2251 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2253 TnyFolderStore *folder_store,
2254 ModestConnectedPerformer callback,
2257 TnyAccount *account = NULL;
2259 if (!folder_store ||
2260 (TNY_IS_MERGE_FOLDER (folder_store) &&
2261 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2263 /* We promise to instantly perform the callback, so ... */
2265 GError *error = NULL;
2266 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2267 "Unable to move or not found folder");
2268 callback (FALSE, error, parent_window, NULL, user_data);
2269 g_error_free (error);
2273 } else if (TNY_IS_FOLDER (folder_store)) {
2274 /* Get the folder's parent account: */
2275 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2276 } else if (TNY_IS_ACCOUNT (folder_store)) {
2277 /* Use the folder store as an account: */
2278 account = TNY_ACCOUNT (g_object_ref (folder_store));
2281 if (account && (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE)) {
2282 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2283 /* No need to connect a local account */
2285 callback (FALSE, NULL, parent_window, account, user_data);
2290 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2294 g_object_unref (account);
2298 src_account_connect_performer (gboolean canceled,
2300 GtkWindow *parent_window,
2301 TnyAccount *src_account,
2304 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2306 if (canceled || err) {
2307 /* If there was any error call the user callback */
2308 info->callback (canceled, err, parent_window, src_account, info->data);
2310 /* Connect the destination account */
2311 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2312 TNY_FOLDER_STORE (info->dst_account),
2313 info->callback, info->data);
2316 /* Free the info object */
2317 g_object_unref (info->dst_account);
2318 g_slice_free (DoubleConnectionInfo, info);
2323 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2325 TnyFolderStore *folder_store,
2326 DoubleConnectionInfo *connect_info)
2328 modest_platform_connect_if_remote_and_perform(parent_window,
2331 src_account_connect_performer,
2336 modest_platform_get_account_settings_wizard (void)
2338 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2340 return GTK_WIDGET (dialog);
2344 modest_platform_get_current_connection (void)
2346 TnyDevice *device = NULL;
2347 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2349 device = modest_runtime_get_device ();
2351 if (!tny_device_is_online (device))
2352 return MODEST_CONNECTED_VIA_ANY;
2354 #ifdef MODEST_HAVE_CONIC
2356 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2358 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2359 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2360 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2362 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2363 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2364 !strcmp (bearer_type, "WIMAX")) {
2365 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2367 retval = MODEST_CONNECTED_VIA_ANY;
2370 g_object_unref (iap);
2373 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2374 #endif /* MODEST_HAVE_CONIC */
2381 modest_platform_check_memory_low (ModestWindow *win,
2386 /* are we in low memory state? */
2387 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2389 if (win && lowmem && visuals)
2390 modest_platform_run_information_dialog (
2392 _KR("memr_ib_operation_disabled"),
2396 g_debug ("%s: low memory reached. disallowing some operations",
2403 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2409 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2412 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2413 GTK_WINDOW (dialog),
2415 gtk_widget_show_all (dialog);
2417 g_signal_connect_swapped (dialog, "response",
2418 G_CALLBACK (gtk_widget_destroy),
2423 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2429 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2432 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2433 GTK_WINDOW (dialog),
2435 gtk_widget_show_all (dialog);
2437 g_signal_connect_swapped (dialog, "response",
2438 G_CALLBACK (gtk_widget_destroy),
2443 modest_platform_get_osso_context (void)
2445 return modest_maemo_utils_get_osso_context ();
2449 _modest_platform_play_email_tone (void)
2452 gint mail_volume_int;
2454 ca_context *ca_con = NULL;
2455 ca_proplist *pl = NULL;
2457 #ifdef MODEST_USE_PROFILE
2458 gchar *active_profile;
2461 active_profile = profile_get_profile ();
2462 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2463 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2464 mail_volume_int = profile_parse_int (mail_volume);
2465 g_free (mail_volume);
2466 g_free (active_profile);
2468 mail_tone = MAIL_TONE;
2469 mail_volume_int = 100;
2472 if (mail_tone && !strstr (mail_tone, "/")) {
2475 tmp = g_strconcat ("/usr/share/sounds", mail_tone, NULL);
2480 if (mail_volume_int > 0) {
2482 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2483 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2487 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2488 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2489 ca_context_destroy(ca_con);
2493 ca_proplist_create(&pl);
2494 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2495 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2497 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2498 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2500 ca_proplist_destroy(pl);
2501 ca_context_destroy(ca_con);
2507 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
2508 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
2509 #define MOVE_TO_DIALOG_ACTION_BUTTON "action-button"
2510 #define MOVE_TO_DIALOG_SELECTION_LABEL "selection-label"
2511 #define MOVE_TO_DIALOG_SHOWING_FOLDERS "showing-folders"
2512 #define MOVE_TO_DIALOG_PANNABLE "pannable"
2515 move_to_dialog_show_accounts (GtkWidget *dialog)
2517 GtkWidget *selection_label;
2518 GtkWidget *back_button;
2519 GtkWidget *folder_view;
2520 GtkWidget *pannable;
2521 GtkWidget *action_button;
2523 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2524 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2525 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2526 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2527 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2529 gtk_widget_set_sensitive (back_button, FALSE);
2530 gtk_widget_set_sensitive (action_button, FALSE);
2532 /* Need to set this here, otherwise callbacks called because
2533 of filtering won't perform correctly */
2534 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (FALSE));
2536 gtk_label_set_text (GTK_LABEL (selection_label), "");
2537 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2538 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
2539 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2540 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2542 g_object_set (G_OBJECT (folder_view),
2543 "hildon-ui-mode", HILDON_UI_MODE_NORMAL,
2548 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
2550 GtkWidget *selection_label;
2551 GtkWidget *back_button;
2552 GtkWidget *folder_view;
2553 TnyAccount *account;
2554 const gchar *account_id;
2555 gchar *selection_label_text;
2556 GtkWidget *pannable;
2557 GtkWidget *action_button;
2559 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2560 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2561 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2562 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2563 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2565 gtk_widget_set_sensitive (back_button, TRUE);
2566 gtk_widget_set_sensitive (action_button, FALSE);
2568 /* Need to set this here, otherwise callbacks called because
2569 of filtering won't perform correctly */
2570 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (TRUE));
2572 g_object_set (G_OBJECT (folder_view),
2573 "hildon-ui-mode", HILDON_UI_MODE_EDIT,
2576 account = TNY_ACCOUNT (folder_store);
2577 if (modest_tny_account_is_virtual_local_folders (account)) {
2579 account_id = tny_account_get_id (account);
2580 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2581 MODEST_CONF_DEVICE_NAME, NULL);
2583 selection_label_text = g_strconcat (device_name, "/", NULL);
2584 g_free (device_name);
2586 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2588 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2589 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2590 } else if (modest_tny_account_is_memory_card_account (account)) {
2591 account_id = tny_account_get_id (account);
2592 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2593 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2594 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2596 account_id = tny_account_get_id (account);
2598 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2599 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2600 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2601 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2602 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2604 gtk_label_set_text (GTK_LABEL (selection_label), selection_label_text);
2605 g_free (selection_label_text);
2607 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
2610 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
2611 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
2612 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2613 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2617 move_to_dialog_set_selected_folder (GtkWidget *dialog, TnyFolderStore *folder_store)
2619 GtkWidget *selection_label;
2620 GtkWidget *action_button;
2623 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2624 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2626 gtk_widget_set_sensitive (action_button, TRUE);
2628 if (TNY_IS_FOLDER (folder_store)) {
2629 folder_name = modest_tny_folder_get_display_name (TNY_FOLDER (folder_store));
2630 } else if (TNY_IS_ACCOUNT (folder_store)) {
2631 folder_name = g_strdup (tny_account_get_name (TNY_ACCOUNT (folder_store)));
2633 folder_name = g_strdup ("");
2636 gtk_label_set_text (GTK_LABEL (selection_label), folder_name);
2637 g_free (folder_name);
2642 on_move_to_dialog_back_clicked (GtkButton *button,
2645 GtkWidget *dialog = (GtkWidget *) userdata;
2646 ModestFolderView *folder_view;
2648 /* Revert the effect of show_folders filters */
2649 folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2650 modest_folder_view_set_account_id_of_visible_server_account (folder_view, NULL);
2651 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2652 modest_folder_view_unset_filter (folder_view, MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2653 modest_folder_view_unset_filter (folder_view, MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2655 /* Back to show accounts */
2656 move_to_dialog_show_accounts (dialog);
2660 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2662 GtkTreeViewColumn *column,
2665 TnyFolderStore *selected;
2667 GtkWidget *folder_view;
2668 gboolean showing_folders;
2670 dialog = (GtkWidget *) user_data;
2671 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2672 if (!showing_folders) {
2673 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2675 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2677 move_to_dialog_show_folders (dialog, selected);
2683 on_move_to_dialog_selection_changed (GtkTreeSelection *selection,
2686 gboolean showing_folders;
2689 dialog = (GtkWidget *) user_data;
2690 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2691 if (showing_folders) {
2692 TnyFolderStore *selected;
2693 GtkWidget *folder_view;
2695 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2696 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2699 move_to_dialog_set_selected_folder (dialog, selected);
2700 g_object_unref (selected);
2706 on_move_to_dialog_action_clicked (GtkButton *selection,
2709 TnyFolderStore *selected;
2711 GtkWidget *folder_view;
2712 gboolean showing_folders;
2714 dialog = (GtkWidget *) user_data;
2715 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2716 if (showing_folders) {
2717 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2718 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2721 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
2726 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2727 GtkWidget **folder_view)
2729 GtkWidget *dialog, *folder_view_container;
2731 GtkWidget *buttons_hbox;
2732 GtkWidget *back_button, *selection_label;
2733 GdkPixbuf *back_pixbuf;
2734 GtkWidget *top_vbox;
2735 GtkWidget *action_button;
2736 GtkTreeSelection *selection;
2738 /* Create dialog. We cannot use a touch selector because we
2739 need to use here the folder view widget directly */
2740 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2741 GTK_WINDOW (parent_window),
2742 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2743 GTK_DIALOG_DESTROY_WITH_PARENT,
2744 _HL("wdgt_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2747 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
2748 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_NONE);
2749 top_vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
2751 /* Create folder view */
2752 *folder_view = modest_platform_create_folder_view (NULL);
2754 modest_folder_view_set_cell_style (MODEST_FOLDER_VIEW (*folder_view),
2755 MODEST_FOLDER_VIEW_CELL_STYLE_COMPACT);
2756 modest_folder_view_show_message_count (MODEST_FOLDER_VIEW (*folder_view),
2758 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2759 (TnyAccountStore *) modest_runtime_get_account_store ());
2761 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
2762 back_button = gtk_button_new ();
2763 back_pixbuf = modest_platform_get_icon (_FM("filemanager_folder_up"), MODEST_ICON_SIZE_BIG);
2765 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
2766 g_object_unref (back_pixbuf);
2768 selection_label = gtk_label_new ("");
2769 gtk_misc_set_alignment (GTK_MISC (selection_label), 0.0, 0.5);
2771 action_button = gtk_button_new ();
2772 gtk_container_add (GTK_CONTAINER (action_button), selection_label);
2774 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
2775 gtk_box_pack_start (GTK_BOX (buttons_hbox), action_button, TRUE, TRUE, 0);
2776 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
2777 gtk_widget_set_sensitive (GTK_WIDGET (action_button), FALSE);
2778 gtk_box_pack_start (GTK_BOX (top_vbox), buttons_hbox, FALSE, FALSE, 0);
2780 /* Create pannable and add it to the dialog */
2781 folder_view_container = hildon_pannable_area_new ();
2782 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2783 gtk_box_pack_start (GTK_BOX (top_vbox), folder_view_container, TRUE, TRUE, 0);
2785 gtk_container_add (GTK_CONTAINER (align), top_vbox);
2786 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), align, TRUE, TRUE, 0);
2788 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2790 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2791 gtk_widget_show (folder_view_container);
2792 gtk_widget_show (align);
2793 gtk_widget_show (top_vbox);
2794 gtk_widget_show (*folder_view);
2795 gtk_widget_show_all (back_button);
2796 gtk_widget_show (selection_label);
2797 gtk_widget_show (action_button);
2798 gtk_widget_show (buttons_hbox);
2799 gtk_widget_show (dialog);
2801 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
2802 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
2803 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON, action_button);
2804 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL, selection_label);
2805 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE, folder_view_container);
2807 /* Simulate the behaviour of a HildonPickerDialog by emitting
2808 a response when a folder is selected */
2809 g_signal_connect (*folder_view, "row-activated",
2810 G_CALLBACK (on_move_to_dialog_folder_activated),
2813 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (*folder_view));
2814 g_signal_connect (selection, "changed",
2815 G_CALLBACK (on_move_to_dialog_selection_changed),
2818 g_signal_connect (action_button, "clicked",
2819 G_CALLBACK (on_move_to_dialog_action_clicked),
2822 g_signal_connect (back_button, "clicked",
2823 G_CALLBACK (on_move_to_dialog_back_clicked),
2826 move_to_dialog_show_accounts (dialog);
2832 modest_platform_get_list_to_move (ModestWindow *window)
2834 TnyList *list = NULL;
2836 if (MODEST_IS_HEADER_WINDOW (window)) {
2837 ModestHeaderView *header_view;
2839 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2840 list = modest_header_view_get_selected_headers (header_view);
2841 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2842 ModestFolderView *folder_view;
2843 TnyFolderStore *selected_folder;
2845 list = TNY_LIST (tny_simple_list_new ());
2846 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2847 selected_folder = modest_folder_view_get_selected (folder_view);
2848 if (selected_folder) {
2849 tny_list_prepend (list, G_OBJECT (selected_folder));
2850 g_object_unref (selected_folder);
2853 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2856 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2858 list = TNY_LIST (tny_simple_list_new ());
2859 tny_list_prepend (list, G_OBJECT (header));
2860 g_object_unref (header);
2863 g_return_val_if_reached (NULL);