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-camel-folder.h>
47 #include <tny-simple-list.h>
48 #include <tny-merge-folder.h>
49 #include <tny-error.h>
50 #include <tny-folder.h>
51 #include <tny-account-store-view.h>
52 #include <gtk/gtkicontheme.h>
53 #include <gtk/gtkmenuitem.h>
54 #include <gtk/gtkmain.h>
55 #include <modest-text-utils.h>
56 #include "modest-tny-folder.h"
57 #include "modest-tny-account.h"
59 #include <libgnomevfs/gnome-vfs-mime-utils.h>
60 #include <modest-account-settings-dialog.h>
61 #include <modest-easysetup-wizard-dialog.h>
62 #include "modest-hildon2-sort-dialog.h"
63 #include <hildon/hildon.h>
65 #include "hildon2/modest-hildon2-details-dialog.h"
66 #include "hildon2/modest-hildon2-window-mgr.h"
67 #ifdef MODEST_USE_PROFILE
68 #include <keys_nokia.h>
69 #include <libprofile.h>
72 #include <modest-datetime-formatter.h>
73 #include "modest-header-window.h"
74 #include <modest-folder-window.h>
75 #include <modest-account-mgr.h>
76 #include <modest-account-mgr-helpers.h>
77 #include <modest-ui-constants.h>
78 #include <modest-selector-picker.h>
79 #include <modest-icon-names.h>
81 #ifdef MODEST_HAVE_MCE
82 #include <mce/dbus-names.h>
83 #endif /*MODEST_HAVE_MCE*/
85 #ifdef MODEST_HAVE_ABOOK
86 #include <libosso-abook/osso-abook.h>
87 #endif /*MODEST_HAVE_ABOOK*/
89 #ifdef MODEST_HAVE_LIBALARM
90 #include <alarmd/libalarm.h> /* For alarm_event_add(), etc. */
91 #endif /*MODEST_HAVE_LIBALARM*/
94 #define HILDON_OSSO_URI_ACTION "uri-action"
95 #define URI_ACTION_COPY "copy:"
96 #define MODEST_NOTIFICATION_CATEGORY "email-message"
97 #define MODEST_NEW_MAIL_LIGHTING_PATTERN "PatternCommunicationEmail"
98 #ifdef MODEST_USE_PROFILE
99 #define PROFILE_MAIL_TONE PROFILEKEY_EMAIL_ALERT_TONE
100 #define PROFILE_MAIL_VOLUME PROFILEKEY_EMAIL_ALERT_VOLUME
102 #define MAIL_TONE "message-new-email"
105 #define COMMON_FOLDER_DIALOG_ENTRY "entry"
106 #define COMMON_FOLDER_DIALOG_ACCOUNT_PICKER "account-picker"
107 #define FOLDER_PICKER_CURRENT_FOLDER "current-folder"
108 #define MODEST_ALARMD_APPID PACKAGE_NAME
111 static void _modest_platform_play_email_tone (void);
115 on_modest_conf_update_interval_changed (ModestConf* self,
117 ModestConfEvent event,
118 ModestConfNotificationId id,
121 g_return_if_fail (key);
123 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
124 const guint update_interval_minutes =
125 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
126 modest_platform_set_update_interval (update_interval_minutes);
133 check_required_files (void)
135 FILE *mcc_file = modest_maemo_open_mcc_mapping_file (NULL);
137 g_printerr ("modest: check for mcc file failed\n");
142 if (access(MODEST_PROVIDER_DATA_FILE, R_OK) != 0 &&
143 access(MODEST_MAEMO_PROVIDER_DATA_FILE, R_OK) != 0) {
144 g_printerr ("modest: cannot find providers data\n");
152 /* the gpointer here is the osso_context. */
154 modest_platform_init (int argc, char *argv[])
156 osso_context_t *osso_context;
158 osso_hw_state_t hw_state = { 0 };
162 if (!check_required_files ()) {
163 g_printerr ("modest: missing required files\n");
167 osso_context = osso_initialize(PACKAGE,PACKAGE_VERSION,
170 g_printerr ("modest: failed to acquire osso context\n");
173 modest_maemo_utils_set_osso_context (osso_context);
175 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
176 g_printerr ("modest: could not get dbus connection\n");
180 /* Add a D-Bus handler to be used when the main osso-rpc
181 * D-Bus handler has not handled something.
182 * We use this for D-Bus methods that need to use more complex types
183 * than osso-rpc supports.
185 if (!dbus_connection_add_filter (con,
186 modest_dbus_req_filter,
190 g_printerr ("modest: Could not add D-Bus filter\n");
194 /* Register our simple D-Bus callbacks, via the osso API: */
195 osso_return_t result = osso_rpc_set_cb_f(osso_context,
199 modest_dbus_req_handler, NULL /* user_data */);
200 if (result != OSSO_OK) {
201 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
205 /* Register hardware event dbus callback: */
206 hw_state.shutdown_ind = TRUE;
207 osso_hw_set_event_cb(osso_context, NULL, NULL, NULL);
209 /* Register osso auto-save callbacks: */
210 result = osso_application_set_autosave_cb (osso_context,
211 modest_on_osso_application_autosave, NULL /* user_data */);
212 if (result != OSSO_OK) {
213 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
218 /* Make sure that the update interval is changed whenever its gconf key
220 /* CAUTION: we're not using here the
221 modest_conf_listen_to_namespace because we know that there
222 are other parts of Modest listening for this namespace, so
223 we'll receive the notifications anyway. We basically do not
224 use it because there is no easy way to do the
225 modest_conf_forget_namespace */
226 ModestConf *conf = modest_runtime_get_conf ();
227 g_signal_connect (G_OBJECT(conf),
229 G_CALLBACK (on_modest_conf_update_interval_changed),
232 /* only force the setting of the default interval, if there are actually
234 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
236 /* Get the initial update interval from gconf: */
237 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
238 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
239 modest_account_mgr_free_account_names (acc_names);
243 #ifdef MODEST_HAVE_ABOOK
244 /* initialize the addressbook */
245 if (!osso_abook_init (&argc, &argv, osso_context)) {
246 g_printerr ("modest: failed to initialized addressbook\n");
249 #endif /*MODEST_HAVE_ABOOK*/
255 modest_platform_uninit (void)
257 osso_context_t *osso_context =
258 modest_maemo_utils_get_osso_context ();
260 osso_deinitialize (osso_context);
269 modest_platform_get_new_device (void)
271 return TNY_DEVICE (tny_maemo_conic_device_new ());
275 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
276 gchar **effective_mime_type)
278 GString *mime_str = NULL;
279 gchar *icon_name = NULL;
280 gchar **icons, **cursor;
282 if (!mime_type || g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0)
283 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
285 mime_str = g_string_new (mime_type);
286 g_string_ascii_down (mime_str);
289 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
291 for (cursor = icons; cursor; ++cursor) {
292 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
293 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
294 icon_name = g_strdup ("qgn_list_messagin");
296 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
297 icon_name = g_strdup (*cursor);
303 if (effective_mime_type)
304 *effective_mime_type = g_string_free (mime_str, FALSE);
306 g_string_free (mime_str, TRUE);
313 checked_hildon_uri_open (const gchar *uri, HildonURIAction *action)
318 g_return_val_if_fail (uri, FALSE);
320 result = hildon_uri_open (uri, action, &err);
322 g_printerr ("modest: hildon_uri_open ('%s', %p) failed: %s",
323 uri, action, err && err->message ? err->message : "unknown error");
333 modest_platform_activate_uri (const gchar *uri)
335 HildonURIAction *action;
336 gboolean result = FALSE;
337 GSList *actions, *iter = NULL;
339 g_return_val_if_fail (uri, FALSE);
343 /* don't try to activate file: uri's -- they might confuse the user,
344 * and/or might have security implications */
345 if (!g_str_has_prefix (uri, "file:")) {
347 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
349 for (iter = actions; iter; iter = g_slist_next (iter)) {
350 action = (HildonURIAction*) iter->data;
351 if (action && strcmp (hildon_uri_action_get_service (action),
352 "com.nokia.modest") == 0) {
353 result = checked_hildon_uri_open (uri, action);
358 /* if we could not open it with email, try something else */
360 result = checked_hildon_uri_open (uri, NULL);
364 ModestWindow *parent =
365 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
366 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
367 _("mcen_ib_unsupported_link"));
368 g_warning ("%s: cannot open uri '%s'", __FUNCTION__,uri);
375 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
379 gchar *uri_path = NULL;
381 uri_path = gnome_vfs_get_uri_from_local_path (path);
382 con = osso_get_dbus_connection (modest_maemo_utils_get_osso_context());
385 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
387 result = hildon_mime_open_file (con, uri_path);
389 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"), FALSE);
397 } ModestPlatformPopupInfo;
400 delete_uri_popup (GtkWidget *menu,
404 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
406 g_free (popup_info->uri);
407 hildon_uri_free_actions (popup_info->actions);
413 activate_uri_popup_item (GtkMenuItem *menu_item,
417 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
418 const gchar* action_name;
420 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
422 g_printerr ("modest: no action name defined\n");
426 /* special handling for the copy menu item -- copy the uri to the clipboard */
427 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
428 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
429 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
430 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
432 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
433 action_name += strlen ("mailto:");
435 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
436 modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
437 return; /* we're done */
440 /* now, the real uri-actions... */
441 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
442 HildonURIAction *action = (HildonURIAction *) node->data;
443 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
444 if (!checked_hildon_uri_open (popup_info->uri, action)) {
445 ModestWindow *parent =
446 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
447 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
448 _("mcen_ib_unsupported_link"));
456 modest_platform_show_uri_popup (const gchar *uri)
458 GSList *actions_list;
463 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
466 GtkWidget *menu = gtk_menu_new ();
467 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
469 /* don't add actions for file: uri's -- they might confuse the user,
470 * and/or might have security implications
471 * we still allow to copy the url though
473 if (!g_str_has_prefix (uri, "file:")) {
476 popup_info->actions = actions_list;
477 popup_info->uri = g_strdup (uri);
479 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
480 GtkWidget *menu_item;
481 const gchar *action_name;
482 const gchar *translation_domain;
483 HildonURIAction *action = (HildonURIAction *) node->data;
484 action_name = hildon_uri_action_get_name (action);
485 translation_domain = hildon_uri_action_get_translation_domain (action);
486 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
487 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
488 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
491 if (hildon_uri_is_default_action (action, NULL)) {
492 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
494 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
496 gtk_widget_show (menu_item);
501 /* and what to do when the link is deleted */
502 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
503 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
506 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
514 modest_platform_get_icon (const gchar *name, guint icon_size)
517 GdkPixbuf* pixbuf = NULL;
518 GtkIconTheme *current_theme = NULL;
520 g_return_val_if_fail (name, NULL);
522 /* strlen == 0 is not really an error; it just
523 * means the icon is not available
525 if (!name || strlen(name) == 0)
528 current_theme = gtk_icon_theme_get_default ();
529 pixbuf = gtk_icon_theme_load_icon (current_theme, name, icon_size,
530 GTK_ICON_LOOKUP_NO_SVG,
533 g_printerr ("modest: error loading theme icon '%s': %s\n",
541 modest_platform_get_app_name (void)
543 return _("mcen_ap_name");
547 entry_insert_text (GtkEditable *editable,
556 chars = gtk_editable_get_chars (editable, 0, -1);
557 chars_length = g_utf8_strlen (chars, -1);
560 /* Show WID-INF036 */
561 if (chars_length >= 20) {
562 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
563 _CS("ckdg_ib_maximum_characters_reached"));
565 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
569 tmp = g_strndup (folder_name_forbidden_chars,
570 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
571 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
572 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
578 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
579 _CS("ckdg_ib_maximum_characters_reached"));
581 /* Write the text in the entry if it's valid */
582 g_signal_handlers_block_by_func (editable,
583 (gpointer) entry_insert_text, data);
584 gtk_editable_insert_text (editable, text, length, position);
585 g_signal_handlers_unblock_by_func (editable,
586 (gpointer) entry_insert_text, data);
589 /* Do not allow further processing */
590 g_signal_stop_emission_by_name (editable, "insert_text");
594 entry_changed (GtkEditable *editable,
598 GtkWidget *ok_button;
601 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
602 ok_button = GTK_WIDGET (buttons->data);
604 chars = gtk_editable_get_chars (editable, 0, -1);
605 g_return_if_fail (chars != NULL);
608 if (g_utf8_strlen (chars,-1) >= 20) {
609 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
610 _CS("ckdg_ib_maximum_characters_reached"));
612 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
615 g_list_free (buttons);
622 on_response (GtkDialog *dialog,
626 GtkWidget *entry, *picker;
627 TnyFolderStore *parent;
628 const gchar *new_name;
631 if (response != GTK_RESPONSE_ACCEPT)
635 entry = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY);
636 picker = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER);
638 parent = TNY_FOLDER_STORE (user_data);
639 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
642 if (picker != NULL) {
644 parent = g_object_get_data (G_OBJECT (picker), FOLDER_PICKER_CURRENT_FOLDER);
647 /* Look for another folder with the same name */
648 if (modest_tny_folder_has_subfolder_with_name (parent,
655 if (TNY_IS_ACCOUNT (parent) &&
656 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
657 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
666 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
667 NULL, _CS("ckdg_ib_folder_already_exists"));
668 /* Select the text */
669 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
670 gtk_widget_grab_focus (entry);
671 /* Do not close the dialog */
672 g_signal_stop_emission_by_name (dialog, "response");
677 typedef struct _FolderChooserData {
678 TnyFolderStore *store;
683 folder_chooser_activated (ModestFolderView *folder_view,
684 TnyFolderStore *folder,
685 FolderChooserData *userdata)
687 userdata->store = folder;
688 gtk_dialog_response (GTK_DIALOG (userdata->dialog), GTK_RESPONSE_OK);
691 static TnyFolderStore *
692 folder_chooser_dialog_run (ModestFolderView *original)
694 GtkWidget *folder_view;
695 FolderChooserData userdata = {NULL, NULL};
697 const gchar *visible_id = NULL;
699 userdata.dialog = hildon_dialog_new ();
700 pannable = hildon_pannable_area_new ();
701 folder_view = modest_platform_create_folder_view (NULL);
703 gtk_window_set_title (GTK_WINDOW (userdata.dialog), _FM("ckdg_ti_change_folder"));
705 modest_folder_view_copy_model (MODEST_FOLDER_VIEW (original),
706 MODEST_FOLDER_VIEW (folder_view));
709 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(original));
710 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view),
713 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (userdata.dialog)->vbox), pannable);
714 gtk_container_add (GTK_CONTAINER (pannable), folder_view);
715 gtk_widget_set_size_request (pannable, -1, 320);
717 gtk_widget_show (folder_view);
718 gtk_widget_show (pannable);
719 gtk_widget_show (userdata.dialog);
720 g_signal_connect (G_OBJECT (folder_view), "folder-activated",
721 G_CALLBACK (folder_chooser_activated),
722 (gpointer) &userdata);
724 gtk_dialog_run (GTK_DIALOG (userdata.dialog));
725 gtk_widget_destroy (userdata.dialog);
727 return userdata.store;
731 folder_store_get_display_name (TnyFolderStore *store)
733 if (TNY_IS_ACCOUNT (store)) {
734 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
735 return modest_conf_get_string (modest_runtime_get_conf(),
736 MODEST_CONF_DEVICE_NAME, NULL);
738 return g_strdup (tny_account_get_name (TNY_ACCOUNT (store)));
741 TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
743 fname = g_strdup (tny_folder_get_name (TNY_FOLDER (store)));
744 type = tny_folder_get_folder_type (TNY_FOLDER (store));
745 if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)) ||
746 modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
747 type = modest_tny_folder_get_local_or_mmc_folder_type (TNY_FOLDER (store));
748 if (type != TNY_FOLDER_TYPE_UNKNOWN) {
750 fname = g_strdup (modest_local_folder_info_get_type_display_name (type));
753 /* Sometimes an special folder is reported by the server as
754 NORMAL, like some versions of Dovecot */
755 if (type == TNY_FOLDER_TYPE_NORMAL ||
756 type == TNY_FOLDER_TYPE_UNKNOWN) {
757 type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
761 if (type == TNY_FOLDER_TYPE_INBOX) {
763 fname = g_strdup (_("mcen_me_folder_inbox"));
770 folder_picker_set_store (GtkButton *button, TnyFolderStore *store)
775 g_object_set_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER, NULL);
778 const gchar *icon_name = NULL;
780 g_object_ref (store);
781 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
782 store, (GDestroyNotify) g_object_unref);
783 name = folder_store_get_display_name (store);
784 hildon_button_set_value (HILDON_BUTTON (button), name);
788 if (TNY_IS_ACCOUNT (store)) {
789 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
790 icon_name = MODEST_FOLDER_ICON_LOCAL_FOLDERS;
791 else if (modest_tny_account_is_memory_card_account (TNY_ACCOUNT (store)))
792 icon_name = MODEST_FOLDER_ICON_MMC;
794 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
796 TnyFolderType type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
797 if (modest_tny_folder_is_remote_folder (TNY_FOLDER (store))) {
799 case TNY_FOLDER_TYPE_INBOX:
800 icon_name = MODEST_FOLDER_ICON_INBOX;
803 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
805 } else if (modest_tny_folder_is_local_folder (TNY_FOLDER (store))) {
807 case TNY_FOLDER_TYPE_OUTBOX:
808 icon_name = MODEST_FOLDER_ICON_OUTBOX;
810 case TNY_FOLDER_TYPE_DRAFTS:
811 icon_name = MODEST_FOLDER_ICON_DRAFTS;
813 case TNY_FOLDER_TYPE_SENT:
814 icon_name = MODEST_FOLDER_ICON_SENT;
817 icon_name = MODEST_FOLDER_ICON_NORMAL;
819 } else if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
820 icon_name = MODEST_FOLDER_ICON_MMC_FOLDER;
825 pixbuf = modest_platform_get_icon (icon_name, MODEST_ICON_SIZE_SMALL);
828 hildon_button_set_image (HILDON_BUTTON (button),
829 gtk_image_new_from_pixbuf (pixbuf));
830 g_object_unref (pixbuf);
835 /* Always returns DUPs so you must free the returned value */
837 get_next_folder_name (const gchar *suggested_name,
838 TnyFolderStore *suggested_folder)
840 const gchar *default_name = _FM("ckdg_va_new_folder_name_stub");
842 gchar *real_suggested_name;
844 if (suggested_name !=NULL) {
845 return g_strdup (suggested_name);
848 for(i = 0; i < 100; ++ i) {
849 gboolean exists = FALSE;
852 real_suggested_name = g_strdup (default_name);
854 real_suggested_name = g_strdup_printf ("%s(%d)",
855 _FM("ckdg_va_new_folder_name_stub"),
857 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
864 g_free (real_suggested_name);
867 /* Didn't find a free number */
869 real_suggested_name = g_strdup (default_name);
871 return real_suggested_name;
875 ModestFolderView *folder_view;
877 } FolderPickerHelper;
880 folder_picker_clicked (GtkButton *button,
881 FolderPickerHelper *helper)
883 TnyFolderStore *store;
885 store = folder_chooser_dialog_run (helper->folder_view);
887 const gchar *current_name;
890 folder_picker_set_store (GTK_BUTTON (button), store);
892 /* Update the name of the folder */
893 current_name = gtk_entry_get_text (helper->entry);
894 exists = modest_tny_folder_has_subfolder_with_name (store,
898 gchar *new_name = get_next_folder_name (NULL, store);
899 gtk_entry_set_text (helper->entry, new_name);
906 folder_picker_new (TnyFolderStore *suggested, FolderPickerHelper *helper)
910 button = hildon_button_new (MODEST_EDITABLE_SIZE,
911 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
913 hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 1.0);
916 folder_picker_set_store (GTK_BUTTON (button), suggested);
919 g_signal_connect (G_OBJECT (button), "clicked",
920 G_CALLBACK (folder_picker_clicked),
928 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
929 TnyFolderStore *suggested_parent,
930 const gchar *dialog_title,
931 const gchar *label_text,
932 const gchar *suggested_name,
934 gboolean show_parent,
936 TnyFolderStore **parent)
938 GtkWidget *accept_btn = NULL;
939 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
940 GtkWidget *account_picker = NULL;
941 GList *buttons = NULL;
943 GtkSizeGroup *sizegroup;
944 ModestFolderView *folder_view;
945 ModestWindow *folder_window;
946 ModestHildon2WindowMgr *window_mgr;
947 FolderPickerHelper *helper = NULL;
948 GtkWidget *top_vbox, *top_align;
950 window_mgr = (ModestHildon2WindowMgr *) modest_runtime_get_window_mgr ();
951 folder_window = modest_hildon2_window_mgr_get_folder_window (window_mgr);
952 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
954 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
956 top_vbox = gtk_vbox_new (FALSE, 0);
957 top_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
958 gtk_alignment_set_padding (GTK_ALIGNMENT (top_align), 0, 0, MODEST_MARGIN_DOUBLE, 0);
960 /* Ask the user for the folder name */
961 dialog = gtk_dialog_new_with_buttons (dialog_title,
963 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
964 _FM("ckdg_bd_new_folder_dialog_ok"),
968 /* Add accept button (with unsensitive handler) */
969 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
970 accept_btn = GTK_WIDGET (buttons->data);
972 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
975 label_entry = gtk_label_new (label_text);
976 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
977 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
979 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
980 gtk_size_group_add_widget (sizegroup, label_entry);
983 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
985 gtk_entry_set_text (GTK_ENTRY (entry), _FM("ckdg_va_new_folder_name_stub"));
986 gtk_entry_set_width_chars (GTK_ENTRY (entry),
987 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
988 g_utf8_strlen (_FM("ckdg_va_new_folder_name_stub"), -1)));
989 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
994 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
996 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
997 gtk_size_group_add_widget (sizegroup, label_location);
999 helper = g_slice_new0 (FolderPickerHelper);
1000 helper->folder_view = folder_view;
1001 helper->entry = (GtkEntry *) entry;
1003 account_picker = folder_picker_new (suggested_parent, helper);
1006 g_object_unref (sizegroup);
1008 /* Connect to the response method to avoid closing the dialog
1009 when an invalid name is selected*/
1010 g_signal_connect (dialog,
1012 G_CALLBACK (on_response),
1016 /* Track entry changes */
1017 g_signal_connect (entry,
1019 G_CALLBACK (entry_insert_text),
1021 g_signal_connect (entry,
1023 G_CALLBACK (entry_changed),
1028 /* Some locales like pt_BR need this to get the full window
1030 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
1032 /* Create the hbox */
1034 hbox = gtk_hbox_new (FALSE, 12);
1035 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
1036 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
1038 /* Add hbox to dialog */
1039 gtk_box_pack_start (GTK_BOX (top_vbox),
1040 hbox, FALSE, FALSE, 0);
1041 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
1045 hbox = gtk_hbox_new (FALSE, 12);
1046 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
1047 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
1049 /* Add hbox to dialog */
1050 gtk_box_pack_start (GTK_BOX (top_vbox),
1051 hbox, FALSE, FALSE, 0);
1052 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
1054 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1055 GTK_WINDOW (dialog), parent_window);
1057 gtk_container_add (GTK_CONTAINER (top_align), top_vbox);
1058 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), top_align, TRUE, TRUE, 0);
1060 gtk_widget_show_all (GTK_WIDGET(dialog));
1062 result = gtk_dialog_run (GTK_DIALOG(dialog));
1063 if (result == GTK_RESPONSE_ACCEPT) {
1065 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1067 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
1069 g_object_ref (*parent);
1073 gtk_widget_destroy (dialog);
1076 g_slice_free (FolderPickerHelper, helper);
1078 while (gtk_events_pending ())
1079 gtk_main_iteration ();
1085 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
1086 TnyFolderStore *suggested_folder,
1087 gchar *suggested_name,
1088 gchar **folder_name,
1089 TnyFolderStore **parent_folder)
1091 gchar *real_suggested_name = NULL;
1093 ModestTnyAccountStore *acc_store;
1094 TnyAccount *account;
1096 real_suggested_name = get_next_folder_name ((const gchar *) suggested_name,
1099 /* In hildon 2.2 we always suggest the archive folder as parent */
1100 acc_store = modest_runtime_get_account_store ();
1101 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
1103 suggested_folder = (TnyFolderStore *)
1104 modest_tny_account_get_special_folder (account,
1105 TNY_FOLDER_TYPE_ARCHIVE);
1106 g_object_unref (account);
1110 /* If there is not archive folder then fallback to local folders account */
1111 if (!suggested_folder)
1112 suggested_folder = (TnyFolderStore *)
1113 modest_tny_account_store_get_local_folders_account (acc_store);
1115 result = modest_platform_run_folder_common_dialog (parent_window,
1117 _HL("ckdg_ti_new_folder"),
1118 _FM("ckdg_fi_new_folder_name"),
1119 real_suggested_name,
1125 g_free(real_suggested_name);
1131 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1132 TnyFolderStore *parent_folder,
1133 const gchar *suggested_name,
1134 gchar **folder_name)
1136 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1138 return modest_platform_run_folder_common_dialog (parent_window,
1140 _HL("ckdg_ti_rename_folder"),
1141 _HL("ckdg_fi_rename_name"),
1152 on_destroy_dialog (GtkWidget *dialog)
1154 /* This could happen when the dialogs get programatically
1155 hidden or destroyed (for example when closing the
1156 application while a dialog is being shown) */
1157 if (!GTK_IS_WIDGET (dialog))
1160 gtk_widget_destroy (dialog);
1162 if (gtk_events_pending ())
1163 gtk_main_iteration ();
1167 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1168 const gchar *message)
1173 dialog = hildon_note_new_confirmation (parent_window, message);
1174 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1175 GTK_WINDOW (dialog), parent_window);
1177 response = gtk_dialog_run (GTK_DIALOG (dialog));
1179 on_destroy_dialog (dialog);
1185 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1186 const gchar *message,
1187 const gchar *button_accept,
1188 const gchar *button_cancel)
1193 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1194 button_accept, GTK_RESPONSE_ACCEPT,
1195 button_cancel, GTK_RESPONSE_CANCEL,
1198 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1199 GTK_WINDOW (dialog), parent_window);
1201 response = gtk_dialog_run (GTK_DIALOG (dialog));
1203 on_destroy_dialog (dialog);
1209 modest_platform_run_information_dialog (GtkWindow *parent_window,
1210 const gchar *message,
1215 note = hildon_note_new_information (parent_window, message);
1217 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1218 GTK_WINDOW (note), parent_window);
1221 gtk_dialog_run (GTK_DIALOG (note));
1223 on_destroy_dialog (note);
1225 g_signal_connect_swapped (note,
1227 G_CALLBACK (on_destroy_dialog),
1230 gtk_widget_show_all (note);
1234 typedef struct _ConnectAndWaitData {
1236 GMainLoop *wait_loop;
1237 gboolean has_callback;
1239 } ConnectAndWaitData;
1243 quit_wait_loop (TnyAccount *account,
1244 ConnectAndWaitData *data)
1246 /* Set the has_callback to TRUE (means that the callback was
1247 executed and wake up every code waiting for cond to be
1249 g_mutex_lock (data->mutex);
1250 data->has_callback = TRUE;
1251 if (data->wait_loop)
1252 g_main_loop_quit (data->wait_loop);
1253 g_mutex_unlock (data->mutex);
1257 on_connection_status_changed (TnyAccount *account,
1258 TnyConnectionStatus status,
1261 TnyConnectionStatus conn_status;
1262 ConnectAndWaitData *data;
1264 /* Ignore if reconnecting or disconnected */
1265 conn_status = tny_account_get_connection_status (account);
1266 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1267 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1270 /* Remove the handler */
1271 data = (ConnectAndWaitData *) user_data;
1272 g_signal_handler_disconnect (account, data->handler);
1274 /* Quit from wait loop */
1275 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1279 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1284 /* Quit from wait loop */
1285 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1289 modest_platform_connect_and_wait (GtkWindow *parent_window,
1290 TnyAccount *account)
1292 ConnectAndWaitData *data = NULL;
1293 gboolean device_online;
1295 TnyConnectionStatus conn_status;
1296 gboolean user_requested;
1298 device = modest_runtime_get_device();
1299 device_online = tny_device_is_online (device);
1301 /* Whether the connection is user requested or automatically
1302 requested, for example via D-Bus */
1303 user_requested = (parent_window) ? TRUE : FALSE;
1305 /* If there is no account check only the device status */
1310 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1311 NULL, user_requested);
1314 /* Return if the account is already connected */
1315 conn_status = tny_account_get_connection_status (account);
1316 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1319 /* Create the helper */
1320 data = g_slice_new0 (ConnectAndWaitData);
1321 data->mutex = g_mutex_new ();
1322 data->has_callback = FALSE;
1324 /* Connect the device */
1325 if (!device_online) {
1326 /* Track account connection status changes */
1327 data->handler = g_signal_connect (account, "connection-status-changed",
1328 G_CALLBACK (on_connection_status_changed),
1330 /* Try to connect the device */
1331 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1332 NULL, user_requested);
1334 /* If the device connection failed then exit */
1335 if (!device_online && data->handler)
1338 /* Force a reconnection of the account */
1339 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1340 on_tny_camel_account_set_online_cb, data);
1343 /* Wait until the callback is executed */
1344 g_mutex_lock (data->mutex);
1345 if (!data->has_callback) {
1346 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1347 gdk_threads_leave ();
1348 g_mutex_unlock (data->mutex);
1349 g_main_loop_run (data->wait_loop);
1350 g_mutex_lock (data->mutex);
1351 gdk_threads_enter ();
1353 g_mutex_unlock (data->mutex);
1356 if (g_signal_handler_is_connected (account, data->handler))
1357 g_signal_handler_disconnect (account, data->handler);
1358 g_mutex_free (data->mutex);
1359 g_main_loop_unref (data->wait_loop);
1360 g_slice_free (ConnectAndWaitData, data);
1362 conn_status = tny_account_get_connection_status (account);
1363 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1367 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1369 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1370 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1371 /* This must be a maildir account, which does not require a connection: */
1376 return modest_platform_connect_and_wait (parent_window, account);
1380 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1383 return TRUE; /* Maybe it is something local. */
1385 gboolean result = TRUE;
1386 if (TNY_IS_FOLDER (folder_store)) {
1387 /* Get the folder's parent account: */
1388 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1389 if (account != NULL) {
1390 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1391 g_object_unref (account);
1393 } else if (TNY_IS_ACCOUNT (folder_store)) {
1394 /* Use the folder store as an account: */
1395 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1402 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1406 dialog = modest_hildon2_sort_dialog_new (parent_window);
1413 modest_platform_set_update_interval (guint minutes)
1415 #ifdef MODEST_HAVE_LIBALARM
1417 ModestConf *conf = modest_runtime_get_conf ();
1421 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1423 /* Delete any existing alarm,
1424 * because we will replace it: */
1426 if (alarmd_event_del(alarm_cookie) != 0)
1427 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1429 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1432 /* 0 means no updates: */
1437 /* Register alarm: */
1439 /* Set the interval in alarm_event_t structure: */
1440 alarm_event_t *event = alarm_event_create ();
1441 alarm_event_add_actions (event, 1);
1442 alarm_action_t *action = alarm_event_get_action (event, 0);
1443 alarm_event_set_alarm_appid (event, MODEST_ALARMD_APPID);
1444 event->alarm_time = minutes * 60; /* seconds */
1446 /* Set recurrence every few minutes: */
1447 event->recur_secs = minutes*60;
1448 event->recur_count = -1; /* Means infinite */
1450 /* Specify what should happen when the alarm happens:
1451 * It should call this D-Bus method: */
1453 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1454 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1455 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1456 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1457 action->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1459 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1460 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1461 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1462 * This is why we want to use the Alarm API instead of just g_timeout_add().
1463 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1464 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1466 event->flags = ALARM_EVENT_CONNECTED;
1468 alarm_cookie = alarmd_event_add (event);
1471 alarm_event_delete (event);
1473 /* Store the alarm ID in GConf, so we can remove it later:
1474 * This is apparently valid between application instances. */
1475 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1477 if (!alarm_cookie) {
1479 g_debug ("Error setting alarm event. \n");
1483 #endif /* MODEST_HAVE_LIBALARM */
1488 modest_platform_push_email_notification(void)
1490 gboolean screen_on, app_in_foreground;
1492 /* Get the window status */
1493 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1495 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1497 /* If the screen is on and the app is in the
1498 foreground we don't show anything */
1499 if (!(screen_on && app_in_foreground)) {
1501 _modest_platform_play_email_tone ();
1503 /* Activate LED. This must be deactivated by
1504 modest_platform_remove_new_mail_notifications */
1505 #ifdef MODEST_HAVE_MCE
1506 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1510 MCE_ACTIVATE_LED_PATTERN,
1512 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1519 modest_platform_on_new_headers_received (TnyList *header_list,
1520 gboolean show_visual)
1522 g_return_if_fail (TNY_IS_LIST(header_list));
1524 if (tny_list_get_length(header_list) == 0) {
1525 g_warning ("%s: header list is empty", __FUNCTION__);
1530 modest_platform_push_email_notification ();
1531 /* We do a return here to avoid indentation with an else */
1535 #ifdef MODEST_HAVE_HILDON_NOTIFY
1536 HildonNotification *notification;
1538 GSList *notifications_list = NULL;
1540 /* Get previous notifications ids */
1541 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1542 MODEST_CONF_NOTIFICATION_IDS,
1543 MODEST_CONF_VALUE_INT, NULL);
1545 iter = tny_list_create_iterator (header_list);
1546 while (!tny_iterator_is_done (iter)) {
1547 gchar *url = NULL, *display_address = NULL;
1548 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1549 TnyFolder *folder = tny_header_get_folder (header);
1550 gboolean first_notification = TRUE;
1554 display_address = tny_header_dup_from (header);
1555 /* string is changed in-place */
1556 modest_text_utils_get_display_address (display_address);
1558 str = tny_header_dup_subject (header);
1559 notification = hildon_notification_new (display_address,
1561 "qgn_list_messagin",
1562 MODEST_NOTIFICATION_CATEGORY);
1564 /* Create the message URL */
1565 str = tny_header_dup_uid (header);
1566 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1570 hildon_notification_add_dbus_action(notification,
1573 MODEST_DBUS_SERVICE,
1576 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1580 /* Play sound if the user wants. Show the LED
1581 pattern. Show and play just one */
1582 if (G_UNLIKELY (first_notification)) {
1583 TnyAccount *account;
1585 first_notification = FALSE;
1587 /* Set the led pattern */
1588 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1590 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1592 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1594 /* Set the account of the headers */
1595 account = tny_folder_get_account (folder);
1597 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1599 tny_account_get_id (account));
1600 g_object_unref (account);
1604 /* Notify. We need to do this in an idle because this function
1605 could be called from a thread */
1606 if (!notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL)) {
1607 g_warning ("Failed to send notification");
1610 /* Save id in the list */
1611 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1612 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1613 /* We don't listen for the "closed" signal, because we
1614 don't care about if the notification was removed or
1615 not to store the list in gconf */
1617 /* Free & carry on */
1618 g_free (display_address);
1620 g_object_unref (folder);
1621 g_object_unref (header);
1622 tny_iterator_next (iter);
1624 g_object_unref (iter);
1627 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1628 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1630 g_slist_free (notifications_list);
1632 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1636 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1639 #ifdef MODEST_HAVE_MCE
1640 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1644 MCE_DEACTIVATE_LED_PATTERN,
1646 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1652 #ifdef MODEST_HAVE_HILDON_NOTIFY
1653 GSList *notif_list = NULL;
1655 /* Get previous notifications ids */
1656 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1657 MODEST_CONF_NOTIFICATION_IDS,
1658 MODEST_CONF_VALUE_INT, NULL);
1660 while (notif_list) {
1662 NotifyNotification *notif;
1664 /* Nasty HACK to remove the notifications, set the id
1665 of the existing ones and then close them */
1666 notif_id = GPOINTER_TO_INT(notif_list->data);
1667 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1668 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1670 /* Close the notification, note that some ids could be
1671 already invalid, but we don't care because it does
1673 notify_notification_close(notif, NULL);
1674 g_object_unref(notif);
1676 /* Delete the link, it's like going to the next */
1677 notif_list = g_slist_delete_link (notif_list, notif_list);
1681 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1682 notif_list, MODEST_CONF_VALUE_INT, NULL);
1684 g_slist_free (notif_list);
1686 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1692 modest_platform_get_global_settings_dialog ()
1694 return modest_hildon2_global_settings_dialog_new ();
1698 modest_platform_show_help (GtkWindow *parent_window,
1699 const gchar *help_id)
1705 modest_platform_show_search_messages (GtkWindow *parent_window)
1707 osso_return_t result = OSSO_ERROR;
1709 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1710 "osso_global_search",
1711 "search_email", NULL, DBUS_TYPE_INVALID);
1713 if (result != OSSO_OK) {
1714 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1719 modest_platform_show_addressbook (GtkWindow *parent_window)
1721 osso_return_t result = OSSO_ERROR;
1723 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1725 "top_application", NULL, DBUS_TYPE_INVALID);
1727 if (result != OSSO_OK) {
1728 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1733 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1735 GtkWidget *widget = modest_folder_view_new (query);
1737 /* Show one account by default */
1738 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1739 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1741 /* Restore settings */
1742 modest_widget_memory_restore (modest_runtime_get_conf(),
1744 MODEST_CONF_FOLDER_VIEW_KEY);
1750 banner_finish (gpointer data, GObject *object)
1752 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1753 modest_window_mgr_unregister_banner (mgr);
1754 g_object_unref (mgr);
1758 modest_platform_information_banner (GtkWidget *parent,
1759 const gchar *icon_name,
1762 GtkWidget *banner, *banner_parent = NULL;
1763 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1765 if (modest_window_mgr_get_num_windows (mgr) == 0)
1768 if (parent && GTK_IS_WINDOW (parent)) {
1769 /* If the window is the active one then show the
1770 banner on top of this window */
1771 if (gtk_window_is_active (GTK_WINDOW (parent)))
1772 banner_parent = parent;
1773 /* If the window is not the topmost but it's visible
1774 (it's minimized for example) then show the banner
1776 else if (GTK_WIDGET_VISIBLE (parent))
1777 banner_parent = NULL;
1778 /* If the window is hidden (like the main window when
1779 running in the background) then do not show
1786 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1788 modest_window_mgr_register_banner (mgr);
1790 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1794 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1795 const gchar *icon_name,
1801 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1804 banner = hildon_banner_show_information (parent, icon_name, text);
1805 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1809 modest_platform_animation_banner (GtkWidget *parent,
1810 const gchar *animation_name,
1813 GtkWidget *inf_note = NULL;
1815 g_return_val_if_fail (text != NULL, NULL);
1817 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1820 /* If the parent is not visible then do not show */
1821 if (parent && !GTK_WIDGET_VISIBLE (parent))
1824 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1832 TnyAccount *account;
1835 } CheckAccountIdleData;
1837 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1840 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1842 gboolean stop_trying = FALSE;
1843 g_return_val_if_fail (data && data->account, FALSE);
1845 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1846 tny_account_get_connection_status (data->account));
1848 if (data && data->account &&
1849 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1850 * after which the account is likely to be usable, or never likely to be usable soon: */
1851 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1853 data->is_online = TRUE;
1857 /* Give up if we have tried too many times: */
1858 if (data->count_tries >= NUMBER_OF_TRIES) {
1861 /* Wait for another timeout: */
1862 ++(data->count_tries);
1867 /* Allow the function that requested this idle callback to continue: */
1869 g_main_loop_quit (data->loop);
1872 g_object_unref (data->account);
1874 return FALSE; /* Don't call this again. */
1876 return TRUE; /* Call this timeout callback again. */
1880 /* Return TRUE immediately if the account is already online,
1881 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1882 * soon as the account is online, or FALSE if the account does
1883 * not become online in the NUMBER_OF_TRIES seconds.
1884 * This is useful when the D-Bus method was run immediately after
1885 * the application was started (when using D-Bus activation),
1886 * because the account usually takes a short time to go online.
1887 * The return value is maybe not very useful.
1890 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1894 g_return_val_if_fail (account, FALSE);
1896 if (!tny_device_is_online (modest_runtime_get_device())) {
1897 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1901 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1902 * so we avoid wait unnecessarily: */
1903 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1906 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1907 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1908 * we want to avoid. */
1909 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1912 /* This blocks on the result: */
1913 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1914 data->is_online = FALSE;
1915 data->account = account;
1916 g_object_ref (data->account);
1917 data->count_tries = 0;
1919 GMainContext *context = NULL; /* g_main_context_new (); */
1920 data->loop = g_main_loop_new (context, FALSE /* not running */);
1922 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1924 /* This main loop will run until the idle handler has stopped it: */
1925 g_main_loop_run (data->loop);
1927 g_main_loop_unref (data->loop);
1928 /* g_main_context_unref (context); */
1930 is_online = data->is_online;
1931 g_slice_free (CheckAccountIdleData, data);
1939 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1941 /* GTK_RESPONSE_HELP means we need to show the certificate */
1942 if (response_id == GTK_RESPONSE_APPLY) {
1946 /* Do not close the dialog */
1947 g_signal_stop_emission_by_name (dialog, "response");
1949 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1950 note = hildon_note_new_information (NULL, msg);
1951 gtk_dialog_run (GTK_DIALOG(note));
1952 gtk_widget_destroy (note);
1958 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1959 const gchar *certificate)
1964 HildonWindowStack *stack;
1966 stack = hildon_window_stack_get_default ();
1967 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1970 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1975 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1978 /* We use GTK_RESPONSE_APPLY because we want the button in the
1979 middle of OK and CANCEL the same as the browser does for
1980 example. With GTK_RESPONSE_HELP the view button is aligned
1981 to the left while the other two to the right */
1982 note = hildon_note_new_confirmation_add_buttons (
1985 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1986 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1987 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1990 g_signal_connect (G_OBJECT(note), "response",
1991 G_CALLBACK(on_cert_dialog_response),
1992 (gpointer) certificate);
1994 response = gtk_dialog_run(GTK_DIALOG(note));
1996 on_destroy_dialog (note);
1999 return response == GTK_RESPONSE_OK;
2003 modest_platform_run_alert_dialog (const gchar* prompt,
2004 gboolean is_question)
2006 ModestWindow *top_win;
2007 HildonWindowStack *stack;
2009 stack = hildon_window_stack_get_default ();
2010 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
2013 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
2018 gboolean retval = TRUE;
2020 /* The Tinymail documentation says that we should show Yes and No buttons,
2021 * when it is a question.
2022 * Obviously, we need tinymail to use more specific error codes instead,
2023 * so we know what buttons to show. */
2024 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
2026 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2027 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
2029 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
2030 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
2032 on_destroy_dialog (dialog);
2034 /* Just show the error text and use the default response: */
2035 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
2043 GtkWindow *parent_window;
2044 ModestConnectedPerformer callback;
2045 TnyAccount *account;
2052 on_went_online_info_free (OnWentOnlineInfo *info)
2054 /* And if we cleanup, we DO cleanup :-) */
2057 g_object_unref (info->device);
2060 if (info->parent_window)
2061 g_object_unref (info->parent_window);
2063 g_object_unref (info->account);
2065 g_slice_free (OnWentOnlineInfo, info);
2067 /* We're done ... */
2073 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
2075 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2077 /* Now it's really time to callback to the caller. If going online didn't succeed,
2078 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
2079 * canceled will be set. Etcetera etcetera. */
2081 if (info->callback) {
2082 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2085 /* This is our last call, we must cleanup here if we didn't yet do that */
2086 on_went_online_info_free (info);
2093 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2095 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2096 info->iap = g_strdup (iap_id);
2098 if (canceled || err || !info->account) {
2100 /* If there's a problem or if there's no account (then that's it for us, we callback
2101 * the caller's callback now. He'll have to handle err or canceled, of course.
2102 * We are not really online, as the account is not really online here ... */
2104 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2105 * this info. We don't cleanup err, Tinymail does that! */
2107 if (info->callback) {
2109 /* info->account can be NULL here, this means that the user did not
2110 * provide a nice account instance. We'll assume that the user knows
2111 * what he's doing and is happy with just the device going online.
2113 * We can't do magic, we don't know what account the user wants to
2114 * see going online. So just the device goes online, end of story */
2116 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2119 } else if (info->account) {
2121 /* If there's no problem and if we have an account, we'll put the account
2122 * online too. When done, the callback of bringing the account online
2123 * will callback the caller's callback. This is the most normal case. */
2125 info->device = TNY_DEVICE (g_object_ref (device));
2127 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2128 on_account_went_online, info);
2130 /* The on_account_went_online cb frees up the info, go look if you
2131 * don't believe me! (so we return here) */
2136 /* We cleanup if we are not bringing the account online too */
2137 on_went_online_info_free (info);
2143 modest_platform_connect_and_perform (GtkWindow *parent_window,
2145 TnyAccount *account,
2146 ModestConnectedPerformer callback,
2149 gboolean device_online;
2151 TnyConnectionStatus conn_status;
2152 OnWentOnlineInfo *info;
2154 device = modest_runtime_get_device();
2155 device_online = tny_device_is_online (device);
2157 /* If there is no account check only the device status */
2160 if (device_online) {
2162 /* We promise to instantly perform the callback, so ... */
2164 callback (FALSE, NULL, parent_window, account, user_data);
2169 info = g_slice_new0 (OnWentOnlineInfo);
2172 info->device = NULL;
2173 info->account = NULL;
2176 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2178 info->parent_window = NULL;
2179 info->user_data = user_data;
2180 info->callback = callback;
2182 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2183 force, on_conic_device_went_online,
2186 /* We'll cleanup in on_conic_device_went_online */
2189 /* The other code has no more reason to run. This is all that we can do for the
2190 * caller (he should have given us a nice and clean account instance!). We
2191 * can't do magic, we don't know what account he intends to bring online. So
2192 * we'll just bring the device online (and await his false bug report). */
2198 /* Return if the account is already connected */
2200 conn_status = tny_account_get_connection_status (account);
2201 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2203 /* We promise to instantly perform the callback, so ... */
2205 callback (FALSE, NULL, parent_window, account, user_data);
2211 /* Else, we are in a state that requires that we go online before we
2212 * call the caller's callback. */
2214 info = g_slice_new0 (OnWentOnlineInfo);
2216 info->device = NULL;
2218 info->account = TNY_ACCOUNT (g_object_ref (account));
2221 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2223 info->parent_window = NULL;
2225 /* So we'll put the callback away for later ... */
2227 info->user_data = user_data;
2228 info->callback = callback;
2230 if (!device_online) {
2232 /* If also the device is offline, then we connect both the device
2233 * and the account */
2235 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2236 force, on_conic_device_went_online,
2241 /* If the device is online, we'll just connect the account */
2243 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2244 on_account_went_online, info);
2247 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2248 * in both situations, go look if you don't believe me! */
2254 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2256 TnyFolderStore *folder_store,
2257 ModestConnectedPerformer callback,
2260 TnyAccount *account = NULL;
2262 if (!folder_store ||
2263 (TNY_IS_MERGE_FOLDER (folder_store) &&
2264 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2266 /* We promise to instantly perform the callback, so ... */
2268 GError *error = NULL;
2269 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2270 "Unable to move or not found folder");
2271 callback (FALSE, error, parent_window, NULL, user_data);
2272 g_error_free (error);
2276 } else if (TNY_IS_FOLDER (folder_store)) {
2277 /* Get the folder's parent account: */
2278 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2279 } else if (TNY_IS_ACCOUNT (folder_store)) {
2280 /* Use the folder store as an account: */
2281 account = TNY_ACCOUNT (g_object_ref (folder_store));
2284 if (account && (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE)) {
2285 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2286 /* No need to connect a local account */
2288 callback (FALSE, NULL, parent_window, account, user_data);
2293 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2297 g_object_unref (account);
2301 src_account_connect_performer (gboolean canceled,
2303 GtkWindow *parent_window,
2304 TnyAccount *src_account,
2307 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2309 if (canceled || err) {
2310 /* If there was any error call the user callback */
2311 info->callback (canceled, err, parent_window, src_account, info->data);
2313 /* Connect the destination account */
2314 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2315 TNY_FOLDER_STORE (info->dst_account),
2316 info->callback, info->data);
2319 /* Free the info object */
2320 g_object_unref (info->dst_account);
2321 g_slice_free (DoubleConnectionInfo, info);
2326 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2328 TnyFolderStore *folder_store,
2329 DoubleConnectionInfo *connect_info)
2331 modest_platform_connect_if_remote_and_perform(parent_window,
2334 src_account_connect_performer,
2339 modest_platform_get_account_settings_wizard (void)
2341 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2343 return GTK_WIDGET (dialog);
2347 modest_platform_get_current_connection (void)
2349 TnyDevice *device = NULL;
2350 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2352 device = modest_runtime_get_device ();
2354 if (!tny_device_is_online (device))
2355 return MODEST_CONNECTED_VIA_ANY;
2357 #ifdef MODEST_HAVE_CONIC
2359 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2361 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2362 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2363 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2365 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2366 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2367 !strcmp (bearer_type, "WIMAX")) {
2368 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2370 retval = MODEST_CONNECTED_VIA_ANY;
2373 g_object_unref (iap);
2376 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2377 #endif /* MODEST_HAVE_CONIC */
2384 modest_platform_check_memory_low (ModestWindow *win,
2389 /* are we in low memory state? */
2390 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2392 if (win && lowmem && visuals)
2393 modest_platform_run_information_dialog (
2395 _KR("memr_ib_operation_disabled"),
2399 g_debug ("%s: low memory reached. disallowing some operations",
2406 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2412 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2415 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2416 GTK_WINDOW (dialog),
2418 gtk_widget_show_all (dialog);
2420 g_signal_connect_swapped (dialog, "response",
2421 G_CALLBACK (gtk_widget_destroy),
2426 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2432 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2435 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2436 GTK_WINDOW (dialog),
2438 gtk_widget_show_all (dialog);
2440 g_signal_connect_swapped (dialog, "response",
2441 G_CALLBACK (gtk_widget_destroy),
2446 modest_platform_get_osso_context (void)
2448 return modest_maemo_utils_get_osso_context ();
2452 _modest_platform_play_email_tone (void)
2455 gint mail_volume_int;
2457 ca_context *ca_con = NULL;
2458 ca_proplist *pl = NULL;
2460 #ifdef MODEST_USE_PROFILE
2461 gchar *active_profile;
2464 active_profile = profile_get_profile ();
2465 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2466 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2467 mail_volume_int = profile_parse_int (mail_volume);
2468 g_free (mail_volume);
2469 g_free (active_profile);
2471 mail_tone = MAIL_TONE;
2472 mail_volume_int = 100;
2475 if (mail_tone && !strstr (mail_tone, "/")) {
2478 tmp = g_strconcat ("/usr/share/sounds", mail_tone, NULL);
2483 if (mail_volume_int > 0) {
2485 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2486 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2490 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2491 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2492 ca_context_destroy(ca_con);
2496 ca_proplist_create(&pl);
2497 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2498 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2500 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2501 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2503 ca_proplist_destroy(pl);
2504 ca_context_destroy(ca_con);
2510 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
2511 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
2512 #define MOVE_TO_DIALOG_ACTION_BUTTON "action-button"
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 *back_button;
2520 GtkWidget *folder_view;
2521 GtkWidget *pannable;
2522 GtkWidget *action_button;
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 /* Reset action button */
2537 hildon_button_set_title (HILDON_BUTTON (action_button), "");
2538 hildon_button_set_value (HILDON_BUTTON (action_button), "");
2540 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view), NULL);
2541 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2542 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
2543 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
2544 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2545 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
2546 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2547 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
2548 MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
2549 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2550 MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2551 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2555 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
2557 GtkWidget *back_button;
2558 GtkWidget *folder_view;
2559 TnyAccount *account;
2560 const gchar *account_id;
2561 gchar *selection_label_text;
2562 GtkWidget *pannable;
2563 GtkWidget *action_button;
2566 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2568 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2570 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2572 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2574 gtk_widget_set_sensitive (back_button, TRUE);
2575 gtk_widget_set_sensitive (action_button, TRUE);
2577 /* Need to set this here, otherwise callbacks called because
2578 of filtering won't perform correctly */
2579 g_object_set_data (G_OBJECT (dialog),
2580 MOVE_TO_DIALOG_SHOWING_FOLDERS,
2581 GINT_TO_POINTER (TRUE));
2583 account = TNY_ACCOUNT (folder_store);
2584 if (modest_tny_account_is_virtual_local_folders (account)) {
2586 account_id = tny_account_get_id (account);
2587 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2588 MODEST_CONF_DEVICE_NAME, NULL);
2590 selection_label_text = g_strconcat (device_name, "/", NULL);
2591 g_free (device_name);
2593 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_MCC_FOLDERS);
2597 } else if (modest_tny_account_is_memory_card_account (account)) {
2598 account_id = tny_account_get_id (account);
2599 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2600 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2601 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2603 account_id = tny_account_get_id (account);
2605 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2606 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2607 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2608 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2609 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2611 hildon_button_set_title (HILDON_BUTTON (action_button), selection_label_text);
2612 g_free (selection_label_text);
2614 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
2617 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
2618 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
2619 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
2620 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2621 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2625 move_to_dialog_set_selected_folder (GtkWidget *dialog, TnyFolderStore *folder_store)
2627 GtkWidget *action_button;
2629 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2631 hildon_button_set_title (HILDON_BUTTON (action_button),
2632 (TNY_IS_ACCOUNT (folder_store)) ?
2633 tny_account_get_name (TNY_ACCOUNT (folder_store)) :
2634 tny_folder_get_name (TNY_FOLDER (folder_store)));
2636 if (TNY_IS_CAMEL_FOLDER (folder_store))
2637 hildon_button_set_value (HILDON_BUTTON (action_button),
2638 tny_camel_folder_get_full_name (TNY_CAMEL_FOLDER (folder_store)));
2642 on_move_to_dialog_back_clicked (GtkButton *button,
2645 GtkWidget *dialog = (GtkWidget *) userdata;
2647 /* Back to show accounts */
2648 move_to_dialog_show_accounts (dialog);
2652 on_move_to_dialog_row_activated (GtkTreeView *tree_view,
2654 GtkTreeViewColumn *column,
2657 TnyFolderStore *selected = NULL;
2659 GtkWidget *folder_view;
2660 gboolean showing_folders;
2662 dialog = (GtkWidget *) user_data;
2663 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog),
2664 MOVE_TO_DIALOG_SHOWING_FOLDERS));
2666 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog),
2667 MOVE_TO_DIALOG_FOLDER_VIEW));
2669 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2673 if (!showing_folders) {
2674 gboolean valid = TRUE;
2676 if (TNY_IS_ACCOUNT (selected) &&
2677 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (selected))) {
2678 ModestProtocolType protocol_type;
2680 protocol_type = modest_tny_account_get_protocol_type (TNY_ACCOUNT (selected));
2681 valid = !modest_protocol_registry_protocol_type_has_tag
2682 (modest_runtime_get_protocol_registry (),
2684 MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
2687 move_to_dialog_show_folders (dialog, selected);
2689 move_to_dialog_set_selected_folder (dialog, selected);
2694 on_move_to_dialog_selection_changed (GtkTreeSelection *selection,
2697 gboolean showing_folders;
2700 dialog = (GtkWidget *) user_data;
2701 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2702 if (showing_folders) {
2703 TnyFolderStore *selected;
2704 GtkWidget *folder_view;
2706 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2707 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2710 move_to_dialog_set_selected_folder (dialog, selected);
2711 g_object_unref (selected);
2717 on_move_to_dialog_action_clicked (GtkButton *selection,
2720 TnyFolderStore *selected;
2722 GtkWidget *folder_view;
2723 gboolean showing_folders;
2725 dialog = (GtkWidget *) user_data;
2726 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2727 if (showing_folders) {
2728 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2729 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2732 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
2737 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2738 GtkWidget **folder_view)
2740 GtkWidget *dialog, *folder_view_container;
2742 GtkWidget *buttons_hbox;
2743 GtkWidget *back_button;
2744 GdkPixbuf *back_pixbuf;
2745 GtkWidget *top_vbox;
2746 GtkWidget *action_button;
2747 GtkTreeSelection *selection;
2749 /* Create dialog. We cannot use a touch selector because we
2750 need to use here the folder view widget directly */
2751 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2752 GTK_WINDOW (parent_window),
2753 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2754 GTK_DIALOG_DESTROY_WITH_PARENT,
2755 _HL("wdgt_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2758 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
2759 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_NONE);
2760 top_vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
2762 /* Create folder view */
2763 *folder_view = modest_platform_create_folder_view (NULL);
2765 modest_folder_view_set_cell_style (MODEST_FOLDER_VIEW (*folder_view),
2766 MODEST_FOLDER_VIEW_CELL_STYLE_COMPACT);
2767 modest_folder_view_show_message_count (MODEST_FOLDER_VIEW (*folder_view),
2769 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2770 (TnyAccountStore *) modest_runtime_get_account_store ());
2772 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
2773 back_button = gtk_button_new ();
2774 back_pixbuf = modest_platform_get_icon (_FM("filemanager_folder_up"), MODEST_ICON_SIZE_BIG);
2776 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
2777 g_object_unref (back_pixbuf);
2780 action_button = hildon_button_new (HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT,
2781 HILDON_BUTTON_ARRANGEMENT_VERTICAL);
2782 gtk_button_set_alignment (GTK_BUTTON (action_button), 0.0, 0.5);
2784 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
2785 gtk_box_pack_start (GTK_BOX (buttons_hbox), action_button, TRUE, TRUE, 0);
2786 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
2787 gtk_widget_set_sensitive (GTK_WIDGET (action_button), FALSE);
2788 gtk_box_pack_start (GTK_BOX (top_vbox), buttons_hbox, FALSE, FALSE, 0);
2790 /* Create pannable and add it to the dialog */
2791 folder_view_container = hildon_pannable_area_new ();
2792 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2793 gtk_box_pack_start (GTK_BOX (top_vbox), folder_view_container, TRUE, TRUE, 0);
2795 gtk_container_add (GTK_CONTAINER (align), top_vbox);
2796 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), align, TRUE, TRUE, 0);
2798 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2800 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2801 gtk_widget_show (folder_view_container);
2802 gtk_widget_show (align);
2803 gtk_widget_show (top_vbox);
2804 gtk_widget_show (*folder_view);
2805 gtk_widget_show_all (back_button);
2806 gtk_widget_show (action_button);
2807 gtk_widget_show (buttons_hbox);
2808 gtk_widget_show (dialog);
2810 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
2811 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
2812 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON, action_button);
2813 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE, folder_view_container);
2815 /* Simulate the behaviour of a HildonPickerDialog by emitting
2816 a response when a folder is selected */
2817 g_signal_connect (*folder_view, "row-activated",
2818 G_CALLBACK (on_move_to_dialog_row_activated),
2821 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (*folder_view));
2822 g_signal_connect (selection, "changed",
2823 G_CALLBACK (on_move_to_dialog_selection_changed),
2826 g_signal_connect (action_button, "clicked",
2827 G_CALLBACK (on_move_to_dialog_action_clicked),
2830 g_signal_connect (back_button, "clicked",
2831 G_CALLBACK (on_move_to_dialog_back_clicked),
2834 move_to_dialog_show_accounts (dialog);
2840 modest_platform_get_list_to_move (ModestWindow *window)
2842 TnyList *list = NULL;
2844 if (MODEST_IS_HEADER_WINDOW (window)) {
2845 ModestHeaderView *header_view;
2847 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2848 list = modest_header_view_get_selected_headers (header_view);
2849 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2850 ModestFolderView *folder_view;
2851 TnyFolderStore *selected_folder;
2853 list = TNY_LIST (tny_simple_list_new ());
2854 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2855 selected_folder = modest_folder_view_get_selected (folder_view);
2856 if (selected_folder) {
2857 tny_list_prepend (list, G_OBJECT (selected_folder));
2858 g_object_unref (selected_folder);
2861 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2864 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2866 list = TNY_LIST (tny_simple_list_new ());
2867 tny_list_prepend (list, G_OBJECT (header));
2868 g_object_unref (header);
2871 g_return_val_if_reached (NULL);