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 #include <keys_nokia.h>
67 #include <libprofile.h>
69 #include <modest-datetime-formatter.h>
70 #include "modest-header-window.h"
71 #include <modest-folder-window.h>
72 #include <modest-account-mgr.h>
73 #include <modest-account-mgr-helpers.h>
74 #include <modest-ui-constants.h>
75 #include <modest-selector-picker.h>
76 #include <modest-icon-names.h>
78 #ifdef MODEST_HAVE_MCE
79 #include <mce/dbus-names.h>
80 #endif /*MODEST_HAVE_MCE*/
82 #ifdef MODEST_HAVE_ABOOK
83 #include <libosso-abook/osso-abook.h>
84 #endif /*MODEST_HAVE_ABOOK*/
86 #ifdef MODEST_HAVE_LIBALARM
87 #include <alarmd/libalarm.h> /* For alarm_event_add(), etc. */
88 #endif /*MODEST_HAVE_LIBALARM*/
91 #define HILDON_OSSO_URI_ACTION "uri-action"
92 #define URI_ACTION_COPY "copy:"
93 #define MODEST_NOTIFICATION_CATEGORY "email-message"
94 #define MODEST_NEW_MAIL_LIGHTING_PATTERN "PatternCommunicationEmail"
95 #define PROFILE_MAIL_TONE PROFILEKEY_EMAIL_ALERT_TONE
96 #define PROFILE_MAIL_VOLUME PROFILEKEY_EMAIL_ALERT_VOLUME
98 #define COMMON_FOLDER_DIALOG_ENTRY "entry"
99 #define COMMON_FOLDER_DIALOG_ACCOUNT_PICKER "account-picker"
100 #define FOLDER_PICKER_CURRENT_FOLDER "current-folder"
101 #define MODEST_ALARMD_APPID PACKAGE_NAME
104 static void _modest_platform_play_email_tone (void);
108 on_modest_conf_update_interval_changed (ModestConf* self,
110 ModestConfEvent event,
111 ModestConfNotificationId id,
114 g_return_if_fail (key);
116 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
117 const guint update_interval_minutes =
118 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
119 modest_platform_set_update_interval (update_interval_minutes);
126 check_required_files (void)
128 FILE *mcc_file = modest_maemo_open_mcc_mapping_file (NULL);
130 g_printerr ("modest: check for mcc file failed\n");
135 if (access(MODEST_PROVIDER_DATA_FILE, R_OK) != 0 &&
136 access(MODEST_MAEMO_PROVIDER_DATA_FILE, R_OK) != 0) {
137 g_printerr ("modest: cannot find providers data\n");
145 /* the gpointer here is the osso_context. */
147 modest_platform_init (int argc, char *argv[])
149 osso_context_t *osso_context;
151 osso_hw_state_t hw_state = { 0 };
155 if (!check_required_files ()) {
156 g_printerr ("modest: missing required files\n");
160 osso_context = osso_initialize(PACKAGE,PACKAGE_VERSION,
163 g_printerr ("modest: failed to acquire osso context\n");
166 modest_maemo_utils_set_osso_context (osso_context);
168 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
169 g_printerr ("modest: could not get dbus connection\n");
173 /* Add a D-Bus handler to be used when the main osso-rpc
174 * D-Bus handler has not handled something.
175 * We use this for D-Bus methods that need to use more complex types
176 * than osso-rpc supports.
178 if (!dbus_connection_add_filter (con,
179 modest_dbus_req_filter,
183 g_printerr ("modest: Could not add D-Bus filter\n");
187 /* Register our simple D-Bus callbacks, via the osso API: */
188 osso_return_t result = osso_rpc_set_cb_f(osso_context,
192 modest_dbus_req_handler, NULL /* user_data */);
193 if (result != OSSO_OK) {
194 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
198 /* Register hardware event dbus callback: */
199 hw_state.shutdown_ind = TRUE;
200 osso_hw_set_event_cb(osso_context, NULL, NULL, NULL);
202 /* Register osso auto-save callbacks: */
203 result = osso_application_set_autosave_cb (osso_context,
204 modest_on_osso_application_autosave, NULL /* user_data */);
205 if (result != OSSO_OK) {
206 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
211 /* Make sure that the update interval is changed whenever its gconf key
213 /* CAUTION: we're not using here the
214 modest_conf_listen_to_namespace because we know that there
215 are other parts of Modest listening for this namespace, so
216 we'll receive the notifications anyway. We basically do not
217 use it because there is no easy way to do the
218 modest_conf_forget_namespace */
219 ModestConf *conf = modest_runtime_get_conf ();
220 g_signal_connect (G_OBJECT(conf),
222 G_CALLBACK (on_modest_conf_update_interval_changed),
225 /* only force the setting of the default interval, if there are actually
227 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
229 /* Get the initial update interval from gconf: */
230 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
231 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
232 modest_account_mgr_free_account_names (acc_names);
236 #ifdef MODEST_HAVE_ABOOK
237 /* initialize the addressbook */
238 if (!osso_abook_init (&argc, &argv, osso_context)) {
239 g_printerr ("modest: failed to initialized addressbook\n");
242 #endif /*MODEST_HAVE_ABOOK*/
248 modest_platform_uninit (void)
250 osso_context_t *osso_context =
251 modest_maemo_utils_get_osso_context ();
253 osso_deinitialize (osso_context);
262 modest_platform_get_new_device (void)
264 return TNY_DEVICE (tny_maemo_conic_device_new ());
268 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
269 gchar **effective_mime_type)
271 GString *mime_str = NULL;
272 gchar *icon_name = NULL;
273 gchar **icons, **cursor;
275 if (!mime_type || g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0)
276 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
278 mime_str = g_string_new (mime_type);
279 g_string_ascii_down (mime_str);
282 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
284 for (cursor = icons; cursor; ++cursor) {
285 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
286 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
287 icon_name = g_strdup ("qgn_list_messagin");
289 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
290 icon_name = g_strdup (*cursor);
296 if (effective_mime_type)
297 *effective_mime_type = g_string_free (mime_str, FALSE);
299 g_string_free (mime_str, TRUE);
306 checked_hildon_uri_open (const gchar *uri, HildonURIAction *action)
311 g_return_val_if_fail (uri, FALSE);
313 result = hildon_uri_open (uri, action, &err);
315 g_printerr ("modest: hildon_uri_open ('%s', %p) failed: %s",
316 uri, action, err && err->message ? err->message : "unknown error");
326 modest_platform_activate_uri (const gchar *uri)
328 HildonURIAction *action;
329 gboolean result = FALSE;
330 GSList *actions, *iter = NULL;
332 g_return_val_if_fail (uri, FALSE);
336 /* don't try to activate file: uri's -- they might confuse the user,
337 * and/or might have security implications */
338 if (!g_str_has_prefix (uri, "file:")) {
340 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
342 for (iter = actions; iter; iter = g_slist_next (iter)) {
343 action = (HildonURIAction*) iter->data;
344 if (action && strcmp (hildon_uri_action_get_service (action),
345 "com.nokia.modest") == 0) {
346 result = checked_hildon_uri_open (uri, action);
351 /* if we could not open it with email, try something else */
353 result = checked_hildon_uri_open (uri, NULL);
357 ModestWindow *parent =
358 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
359 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
360 _("mcen_ib_unsupported_link"));
361 g_warning ("%s: cannot open uri '%s'", __FUNCTION__,uri);
368 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
372 gchar *uri_path = NULL;
374 uri_path = gnome_vfs_get_uri_from_local_path (path);
375 con = osso_get_dbus_connection (modest_maemo_utils_get_osso_context());
378 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
380 result = hildon_mime_open_file (con, uri_path);
382 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"), FALSE);
390 } ModestPlatformPopupInfo;
393 delete_uri_popup (GtkWidget *menu,
397 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
399 g_free (popup_info->uri);
400 hildon_uri_free_actions (popup_info->actions);
406 activate_uri_popup_item (GtkMenuItem *menu_item,
410 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
411 const gchar* action_name;
413 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
415 g_printerr ("modest: no action name defined\n");
419 /* special handling for the copy menu item -- copy the uri to the clipboard */
420 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
421 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
422 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
423 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
425 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
426 action_name += strlen ("mailto:");
428 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
429 modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
430 return; /* we're done */
433 /* now, the real uri-actions... */
434 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
435 HildonURIAction *action = (HildonURIAction *) node->data;
436 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
437 if (!checked_hildon_uri_open (popup_info->uri, action)) {
438 ModestWindow *parent =
439 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
440 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
441 _("mcen_ib_unsupported_link"));
449 modest_platform_show_uri_popup (const gchar *uri)
451 GSList *actions_list;
456 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
459 GtkWidget *menu = gtk_menu_new ();
460 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
462 /* don't add actions for file: uri's -- they might confuse the user,
463 * and/or might have security implications
464 * we still allow to copy the url though
466 if (!g_str_has_prefix (uri, "file:")) {
469 popup_info->actions = actions_list;
470 popup_info->uri = g_strdup (uri);
472 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
473 GtkWidget *menu_item;
474 const gchar *action_name;
475 const gchar *translation_domain;
476 HildonURIAction *action = (HildonURIAction *) node->data;
477 action_name = hildon_uri_action_get_name (action);
478 translation_domain = hildon_uri_action_get_translation_domain (action);
479 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
480 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
481 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
484 if (hildon_uri_is_default_action (action, NULL)) {
485 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
487 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
489 gtk_widget_show (menu_item);
494 /* and what to do when the link is deleted */
495 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
496 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
499 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
507 modest_platform_get_icon (const gchar *name, guint icon_size)
510 GdkPixbuf* pixbuf = NULL;
511 GtkIconTheme *current_theme = NULL;
513 g_return_val_if_fail (name, NULL);
515 /* strlen == 0 is not really an error; it just
516 * means the icon is not available
518 if (!name || strlen(name) == 0)
521 current_theme = gtk_icon_theme_get_default ();
522 pixbuf = gtk_icon_theme_load_icon (current_theme, name, icon_size,
523 GTK_ICON_LOOKUP_NO_SVG,
526 g_printerr ("modest: error loading theme icon '%s': %s\n",
534 modest_platform_get_app_name (void)
536 return _("mcen_ap_name");
540 entry_insert_text (GtkEditable *editable,
549 chars = gtk_editable_get_chars (editable, 0, -1);
550 chars_length = g_utf8_strlen (chars, -1);
553 /* Show WID-INF036 */
554 if (chars_length >= 20) {
555 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
556 _CS("ckdg_ib_maximum_characters_reached"));
558 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
562 tmp = g_strndup (folder_name_forbidden_chars,
563 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
564 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
565 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
571 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
572 _CS("ckdg_ib_maximum_characters_reached"));
574 /* Write the text in the entry if it's valid */
575 g_signal_handlers_block_by_func (editable,
576 (gpointer) entry_insert_text, data);
577 gtk_editable_insert_text (editable, text, length, position);
578 g_signal_handlers_unblock_by_func (editable,
579 (gpointer) entry_insert_text, data);
582 /* Do not allow further processing */
583 g_signal_stop_emission_by_name (editable, "insert_text");
587 entry_changed (GtkEditable *editable,
591 GtkWidget *ok_button;
594 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
595 ok_button = GTK_WIDGET (buttons->data);
597 chars = gtk_editable_get_chars (editable, 0, -1);
598 g_return_if_fail (chars != NULL);
601 if (g_utf8_strlen (chars,-1) >= 20) {
602 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
603 _CS("ckdg_ib_maximum_characters_reached"));
605 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
608 g_list_free (buttons);
615 on_response (GtkDialog *dialog,
619 GtkWidget *entry, *picker;
620 TnyFolderStore *parent;
621 const gchar *new_name;
624 if (response != GTK_RESPONSE_ACCEPT)
628 entry = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY);
629 picker = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER);
631 parent = TNY_FOLDER_STORE (user_data);
632 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
635 if (picker != NULL) {
637 parent = g_object_get_data (G_OBJECT (picker), FOLDER_PICKER_CURRENT_FOLDER);
640 /* Look for another folder with the same name */
641 if (modest_tny_folder_has_subfolder_with_name (parent,
648 if (TNY_IS_ACCOUNT (parent) &&
649 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
650 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
659 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
660 NULL, _CS("ckdg_ib_folder_already_exists"));
661 /* Select the text */
662 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
663 gtk_widget_grab_focus (entry);
664 /* Do not close the dialog */
665 g_signal_stop_emission_by_name (dialog, "response");
670 typedef struct _FolderChooserData {
671 TnyFolderStore *store;
676 folder_chooser_activated (ModestFolderView *folder_view,
677 TnyFolderStore *folder,
678 FolderChooserData *userdata)
680 userdata->store = folder;
681 gtk_dialog_response (GTK_DIALOG (userdata->dialog), GTK_RESPONSE_OK);
684 static TnyFolderStore *
685 folder_chooser_dialog_run (ModestFolderView *original)
687 GtkWidget *folder_view;
688 FolderChooserData userdata = {NULL, NULL};
690 const gchar *visible_id = NULL;
692 userdata.dialog = hildon_dialog_new ();
693 pannable = hildon_pannable_area_new ();
694 folder_view = modest_platform_create_folder_view (NULL);
696 gtk_window_set_title (GTK_WINDOW (userdata.dialog), _FM("ckdg_ti_change_folder"));
698 modest_folder_view_copy_model (MODEST_FOLDER_VIEW (original),
699 MODEST_FOLDER_VIEW (folder_view));
702 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(original));
703 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view),
706 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (userdata.dialog)->vbox), pannable);
707 gtk_container_add (GTK_CONTAINER (pannable), folder_view);
708 gtk_widget_set_size_request (pannable, -1, 320);
710 gtk_widget_show (folder_view);
711 gtk_widget_show (pannable);
712 gtk_widget_show (userdata.dialog);
713 g_signal_connect (G_OBJECT (folder_view), "folder-activated",
714 G_CALLBACK (folder_chooser_activated),
715 (gpointer) &userdata);
717 gtk_dialog_run (GTK_DIALOG (userdata.dialog));
718 gtk_widget_destroy (userdata.dialog);
720 return userdata.store;
724 folder_store_get_display_name (TnyFolderStore *store)
726 if (TNY_IS_ACCOUNT (store)) {
727 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
728 return modest_conf_get_string (modest_runtime_get_conf(),
729 MODEST_CONF_DEVICE_NAME, NULL);
731 return g_strdup (tny_account_get_name (TNY_ACCOUNT (store)));
734 TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
736 fname = g_strdup (tny_folder_get_name (TNY_FOLDER (store)));
737 type = tny_folder_get_folder_type (TNY_FOLDER (store));
738 if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)) ||
739 modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
740 type = modest_tny_folder_get_local_or_mmc_folder_type (TNY_FOLDER (store));
741 if (type != TNY_FOLDER_TYPE_UNKNOWN) {
743 fname = g_strdup (modest_local_folder_info_get_type_display_name (type));
746 /* Sometimes an special folder is reported by the server as
747 NORMAL, like some versions of Dovecot */
748 if (type == TNY_FOLDER_TYPE_NORMAL ||
749 type == TNY_FOLDER_TYPE_UNKNOWN) {
750 type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
754 if (type == TNY_FOLDER_TYPE_INBOX) {
756 fname = g_strdup (_("mcen_me_folder_inbox"));
763 folder_picker_set_store (GtkButton *button, TnyFolderStore *store)
768 g_object_set_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER, NULL);
771 const gchar *icon_name = NULL;
773 g_object_ref (store);
774 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
775 store, (GDestroyNotify) g_object_unref);
776 name = folder_store_get_display_name (store);
777 hildon_button_set_value (HILDON_BUTTON (button), name);
781 if (TNY_IS_ACCOUNT (store)) {
782 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
783 icon_name = MODEST_FOLDER_ICON_LOCAL_FOLDERS;
784 else if (modest_tny_account_is_memory_card_account (TNY_ACCOUNT (store)))
785 icon_name = MODEST_FOLDER_ICON_MMC;
787 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
789 TnyFolderType type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
790 if (modest_tny_folder_is_remote_folder (TNY_FOLDER (store))) {
792 case TNY_FOLDER_TYPE_INBOX:
793 icon_name = MODEST_FOLDER_ICON_INBOX;
796 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
798 } else if (modest_tny_folder_is_local_folder (TNY_FOLDER (store))) {
800 case TNY_FOLDER_TYPE_OUTBOX:
801 icon_name = MODEST_FOLDER_ICON_OUTBOX;
803 case TNY_FOLDER_TYPE_DRAFTS:
804 icon_name = MODEST_FOLDER_ICON_DRAFTS;
806 case TNY_FOLDER_TYPE_SENT:
807 icon_name = MODEST_FOLDER_ICON_SENT;
810 icon_name = MODEST_FOLDER_ICON_NORMAL;
812 } else if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
813 icon_name = MODEST_FOLDER_ICON_MMC_FOLDER;
818 pixbuf = modest_platform_get_icon (icon_name, MODEST_ICON_SIZE_SMALL);
821 hildon_button_set_image (HILDON_BUTTON (button),
822 gtk_image_new_from_pixbuf (pixbuf));
823 g_object_unref (pixbuf);
828 /* Always returns DUPs so you must free the returned value */
830 get_next_folder_name (const gchar *suggested_name,
831 TnyFolderStore *suggested_folder)
833 const gchar *default_name = _FM("ckdg_va_new_folder_name_stub");
835 gchar *real_suggested_name;
837 if (suggested_name !=NULL) {
838 return g_strdup (suggested_name);
841 for(i = 0; i < 100; ++ i) {
842 gboolean exists = FALSE;
845 real_suggested_name = g_strdup (default_name);
847 real_suggested_name = g_strdup_printf ("%s(%d)",
848 _FM("ckdg_va_new_folder_name_stub"),
850 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
857 g_free (real_suggested_name);
860 /* Didn't find a free number */
862 real_suggested_name = g_strdup (default_name);
864 return real_suggested_name;
868 ModestFolderView *folder_view;
870 } FolderPickerHelper;
873 folder_picker_clicked (GtkButton *button,
874 FolderPickerHelper *helper)
876 TnyFolderStore *store;
878 store = folder_chooser_dialog_run (helper->folder_view);
880 const gchar *current_name;
883 folder_picker_set_store (GTK_BUTTON (button), store);
885 /* Update the name of the folder */
886 current_name = gtk_entry_get_text (helper->entry);
887 exists = modest_tny_folder_has_subfolder_with_name (store,
891 gchar *new_name = get_next_folder_name (NULL, store);
892 gtk_entry_set_text (helper->entry, new_name);
899 folder_picker_new (TnyFolderStore *suggested, FolderPickerHelper *helper)
903 button = hildon_button_new (MODEST_EDITABLE_SIZE,
904 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
906 hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 1.0);
909 folder_picker_set_store (GTK_BUTTON (button), suggested);
912 g_signal_connect (G_OBJECT (button), "clicked",
913 G_CALLBACK (folder_picker_clicked),
921 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
922 TnyFolderStore *suggested_parent,
923 const gchar *dialog_title,
924 const gchar *label_text,
925 const gchar *suggested_name,
927 gboolean show_parent,
929 TnyFolderStore **parent)
931 GtkWidget *accept_btn = NULL;
932 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
933 GtkWidget *account_picker = NULL;
934 GList *buttons = NULL;
936 GtkSizeGroup *sizegroup;
937 ModestFolderView *folder_view;
938 ModestWindow *folder_window;
939 ModestHildon2WindowMgr *window_mgr;
940 FolderPickerHelper *helper = NULL;
941 GtkWidget *top_vbox, *top_align;
943 window_mgr = (ModestHildon2WindowMgr *) modest_runtime_get_window_mgr ();
944 folder_window = modest_hildon2_window_mgr_get_folder_window (window_mgr);
945 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
947 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
949 top_vbox = gtk_vbox_new (FALSE, 0);
950 top_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
951 gtk_alignment_set_padding (GTK_ALIGNMENT (top_align), 0, 0, MODEST_MARGIN_DOUBLE, 0);
953 /* Ask the user for the folder name */
954 dialog = gtk_dialog_new_with_buttons (dialog_title,
956 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
957 _FM("ckdg_bd_new_folder_dialog_ok"),
961 /* Add accept button (with unsensitive handler) */
962 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
963 accept_btn = GTK_WIDGET (buttons->data);
965 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
968 label_entry = gtk_label_new (label_text);
969 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
970 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
972 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
973 gtk_size_group_add_widget (sizegroup, label_entry);
976 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
978 gtk_entry_set_text (GTK_ENTRY (entry), _FM("ckdg_va_new_folder_name_stub"));
979 gtk_entry_set_width_chars (GTK_ENTRY (entry),
980 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
981 g_utf8_strlen (_FM("ckdg_va_new_folder_name_stub"), -1)));
982 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
987 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
989 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
990 gtk_size_group_add_widget (sizegroup, label_location);
992 helper = g_slice_new0 (FolderPickerHelper);
993 helper->folder_view = folder_view;
994 helper->entry = (GtkEntry *) entry;
996 account_picker = folder_picker_new (suggested_parent, helper);
999 g_object_unref (sizegroup);
1001 /* Connect to the response method to avoid closing the dialog
1002 when an invalid name is selected*/
1003 g_signal_connect (dialog,
1005 G_CALLBACK (on_response),
1009 /* Track entry changes */
1010 g_signal_connect (entry,
1012 G_CALLBACK (entry_insert_text),
1014 g_signal_connect (entry,
1016 G_CALLBACK (entry_changed),
1021 /* Some locales like pt_BR need this to get the full window
1023 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
1025 /* Create the hbox */
1027 hbox = gtk_hbox_new (FALSE, 12);
1028 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
1029 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
1031 /* Add hbox to dialog */
1032 gtk_box_pack_start (GTK_BOX (top_vbox),
1033 hbox, FALSE, FALSE, 0);
1034 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
1038 hbox = gtk_hbox_new (FALSE, 12);
1039 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
1040 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
1042 /* Add hbox to dialog */
1043 gtk_box_pack_start (GTK_BOX (top_vbox),
1044 hbox, FALSE, FALSE, 0);
1045 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
1047 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1048 GTK_WINDOW (dialog), parent_window);
1050 gtk_container_add (GTK_CONTAINER (top_align), top_vbox);
1051 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), top_align, TRUE, TRUE, 0);
1053 gtk_widget_show_all (GTK_WIDGET(dialog));
1055 result = gtk_dialog_run (GTK_DIALOG(dialog));
1056 if (result == GTK_RESPONSE_ACCEPT) {
1058 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1060 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
1062 g_object_ref (*parent);
1066 gtk_widget_destroy (dialog);
1069 g_slice_free (FolderPickerHelper, helper);
1071 while (gtk_events_pending ())
1072 gtk_main_iteration ();
1078 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
1079 TnyFolderStore *suggested_folder,
1080 gchar *suggested_name,
1081 gchar **folder_name,
1082 TnyFolderStore **parent_folder)
1084 gchar *real_suggested_name = NULL;
1086 ModestTnyAccountStore *acc_store;
1087 TnyAccount *account;
1089 real_suggested_name = get_next_folder_name ((const gchar *) suggested_name,
1092 /* In hildon 2.2 we always suggest the archive folder as parent */
1093 acc_store = modest_runtime_get_account_store ();
1094 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
1096 suggested_folder = (TnyFolderStore *)
1097 modest_tny_account_get_special_folder (account,
1098 TNY_FOLDER_TYPE_ARCHIVE);
1099 g_object_unref (account);
1103 /* If there is not archive folder then fallback to local folders account */
1104 if (!suggested_folder)
1105 suggested_folder = (TnyFolderStore *)
1106 modest_tny_account_store_get_local_folders_account (acc_store);
1108 result = modest_platform_run_folder_common_dialog (parent_window,
1110 _HL("ckdg_ti_new_folder"),
1111 _FM("ckdg_fi_new_folder_name"),
1112 real_suggested_name,
1118 g_free(real_suggested_name);
1124 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1125 TnyFolderStore *parent_folder,
1126 const gchar *suggested_name,
1127 gchar **folder_name)
1129 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1131 return modest_platform_run_folder_common_dialog (parent_window,
1133 _HL("ckdg_ti_rename_folder"),
1134 _HL("ckdg_fi_rename_name"),
1145 on_destroy_dialog (GtkWidget *dialog)
1147 /* This could happen when the dialogs get programatically
1148 hidden or destroyed (for example when closing the
1149 application while a dialog is being shown) */
1150 if (!GTK_IS_WIDGET (dialog))
1153 gtk_widget_destroy (dialog);
1155 if (gtk_events_pending ())
1156 gtk_main_iteration ();
1160 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1161 const gchar *message)
1166 dialog = hildon_note_new_confirmation (parent_window, message);
1167 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1168 GTK_WINDOW (dialog), parent_window);
1170 response = gtk_dialog_run (GTK_DIALOG (dialog));
1172 on_destroy_dialog (dialog);
1178 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1179 const gchar *message,
1180 const gchar *button_accept,
1181 const gchar *button_cancel)
1186 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1187 button_accept, GTK_RESPONSE_ACCEPT,
1188 button_cancel, GTK_RESPONSE_CANCEL,
1191 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1192 GTK_WINDOW (dialog), parent_window);
1194 response = gtk_dialog_run (GTK_DIALOG (dialog));
1196 on_destroy_dialog (dialog);
1202 modest_platform_run_information_dialog (GtkWindow *parent_window,
1203 const gchar *message,
1208 note = hildon_note_new_information (parent_window, message);
1210 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1211 GTK_WINDOW (note), parent_window);
1214 gtk_dialog_run (GTK_DIALOG (note));
1216 on_destroy_dialog (note);
1218 g_signal_connect_swapped (note,
1220 G_CALLBACK (on_destroy_dialog),
1223 gtk_widget_show_all (note);
1227 typedef struct _ConnectAndWaitData {
1229 GMainLoop *wait_loop;
1230 gboolean has_callback;
1232 } ConnectAndWaitData;
1236 quit_wait_loop (TnyAccount *account,
1237 ConnectAndWaitData *data)
1239 /* Set the has_callback to TRUE (means that the callback was
1240 executed and wake up every code waiting for cond to be
1242 g_mutex_lock (data->mutex);
1243 data->has_callback = TRUE;
1244 if (data->wait_loop)
1245 g_main_loop_quit (data->wait_loop);
1246 g_mutex_unlock (data->mutex);
1250 on_connection_status_changed (TnyAccount *account,
1251 TnyConnectionStatus status,
1254 TnyConnectionStatus conn_status;
1255 ConnectAndWaitData *data;
1257 /* Ignore if reconnecting or disconnected */
1258 conn_status = tny_account_get_connection_status (account);
1259 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1260 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1263 /* Remove the handler */
1264 data = (ConnectAndWaitData *) user_data;
1265 g_signal_handler_disconnect (account, data->handler);
1267 /* Quit from wait loop */
1268 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1272 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1277 /* Quit from wait loop */
1278 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1282 modest_platform_connect_and_wait (GtkWindow *parent_window,
1283 TnyAccount *account)
1285 ConnectAndWaitData *data = NULL;
1286 gboolean device_online;
1288 TnyConnectionStatus conn_status;
1289 gboolean user_requested;
1291 device = modest_runtime_get_device();
1292 device_online = tny_device_is_online (device);
1294 /* Whether the connection is user requested or automatically
1295 requested, for example via D-Bus */
1296 user_requested = (parent_window) ? TRUE : FALSE;
1298 /* If there is no account check only the device status */
1303 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1304 NULL, user_requested);
1307 /* Return if the account is already connected */
1308 conn_status = tny_account_get_connection_status (account);
1309 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1312 /* Create the helper */
1313 data = g_slice_new0 (ConnectAndWaitData);
1314 data->mutex = g_mutex_new ();
1315 data->has_callback = FALSE;
1317 /* Connect the device */
1318 if (!device_online) {
1319 /* Track account connection status changes */
1320 data->handler = g_signal_connect (account, "connection-status-changed",
1321 G_CALLBACK (on_connection_status_changed),
1323 /* Try to connect the device */
1324 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1325 NULL, user_requested);
1327 /* If the device connection failed then exit */
1328 if (!device_online && data->handler)
1331 /* Force a reconnection of the account */
1332 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1333 on_tny_camel_account_set_online_cb, data);
1336 /* Wait until the callback is executed */
1337 g_mutex_lock (data->mutex);
1338 if (!data->has_callback) {
1339 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1340 gdk_threads_leave ();
1341 g_mutex_unlock (data->mutex);
1342 g_main_loop_run (data->wait_loop);
1343 g_mutex_lock (data->mutex);
1344 gdk_threads_enter ();
1346 g_mutex_unlock (data->mutex);
1349 if (g_signal_handler_is_connected (account, data->handler))
1350 g_signal_handler_disconnect (account, data->handler);
1351 g_mutex_free (data->mutex);
1352 g_main_loop_unref (data->wait_loop);
1353 g_slice_free (ConnectAndWaitData, data);
1355 conn_status = tny_account_get_connection_status (account);
1356 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1360 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1362 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1363 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1364 /* This must be a maildir account, which does not require a connection: */
1369 return modest_platform_connect_and_wait (parent_window, account);
1373 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1376 return TRUE; /* Maybe it is something local. */
1378 gboolean result = TRUE;
1379 if (TNY_IS_FOLDER (folder_store)) {
1380 /* Get the folder's parent account: */
1381 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1382 if (account != NULL) {
1383 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1384 g_object_unref (account);
1386 } else if (TNY_IS_ACCOUNT (folder_store)) {
1387 /* Use the folder store as an account: */
1388 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1395 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1399 dialog = modest_hildon2_sort_dialog_new (parent_window);
1406 modest_platform_set_update_interval (guint minutes)
1408 #ifdef MODEST_HAVE_LIBALARM
1410 ModestConf *conf = modest_runtime_get_conf ();
1414 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1416 /* Delete any existing alarm,
1417 * because we will replace it: */
1419 if (alarmd_event_del(alarm_cookie) != 0)
1420 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1422 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1425 /* 0 means no updates: */
1430 /* Register alarm: */
1432 /* Set the interval in alarm_event_t structure: */
1433 alarm_event_t *event = alarm_event_create ();
1434 alarm_event_add_actions (event, 1);
1435 alarm_action_t *action = alarm_event_get_action (event, 0);
1436 alarm_event_set_alarm_appid (event, MODEST_ALARMD_APPID);
1437 event->alarm_time = minutes * 60; /* seconds */
1439 /* Set recurrence every few minutes: */
1440 event->recur_secs = minutes*60;
1441 event->recur_count = -1; /* Means infinite */
1443 /* Specify what should happen when the alarm happens:
1444 * It should call this D-Bus method: */
1446 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1447 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1448 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1449 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1450 action->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1452 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1453 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1454 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1455 * This is why we want to use the Alarm API instead of just g_timeout_add().
1456 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1457 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1459 event->flags = ALARM_EVENT_CONNECTED;
1461 alarm_cookie = alarmd_event_add (event);
1464 alarm_event_delete (event);
1466 /* Store the alarm ID in GConf, so we can remove it later:
1467 * This is apparently valid between application instances. */
1468 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1470 if (!alarm_cookie) {
1472 g_debug ("Error setting alarm event. \n");
1476 #endif /* MODEST_HAVE_LIBALARM */
1481 modest_platform_push_email_notification(void)
1483 gboolean screen_on, app_in_foreground;
1485 /* Get the window status */
1486 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1488 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1490 /* If the screen is on and the app is in the
1491 foreground we don't show anything */
1492 if (!(screen_on && app_in_foreground)) {
1494 _modest_platform_play_email_tone ();
1496 /* Activate LED. This must be deactivated by
1497 modest_platform_remove_new_mail_notifications */
1498 #ifdef MODEST_HAVE_MCE
1499 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1503 MCE_ACTIVATE_LED_PATTERN,
1505 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1512 modest_platform_on_new_headers_received (TnyList *header_list,
1513 gboolean show_visual)
1515 g_return_if_fail (TNY_IS_LIST(header_list));
1517 if (tny_list_get_length(header_list) == 0) {
1518 g_warning ("%s: header list is empty", __FUNCTION__);
1523 modest_platform_push_email_notification ();
1524 /* We do a return here to avoid indentation with an else */
1528 #ifdef MODEST_HAVE_HILDON_NOTIFY
1529 HildonNotification *notification;
1531 GSList *notifications_list = NULL;
1533 /* Get previous notifications ids */
1534 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1535 MODEST_CONF_NOTIFICATION_IDS,
1536 MODEST_CONF_VALUE_INT, NULL);
1538 iter = tny_list_create_iterator (header_list);
1539 while (!tny_iterator_is_done (iter)) {
1540 gchar *url = NULL, *display_address = NULL;
1541 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1542 TnyFolder *folder = tny_header_get_folder (header);
1543 gboolean first_notification = TRUE;
1547 display_address = tny_header_dup_from (header);
1548 /* string is changed in-place */
1549 modest_text_utils_get_display_address (display_address);
1551 str = tny_header_dup_subject (header);
1552 notification = hildon_notification_new (display_address,
1554 "qgn_list_messagin",
1555 MODEST_NOTIFICATION_CATEGORY);
1557 /* Create the message URL */
1558 str = tny_header_dup_uid (header);
1559 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1563 hildon_notification_add_dbus_action(notification,
1566 MODEST_DBUS_SERVICE,
1569 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1573 /* Play sound if the user wants. Show the LED
1574 pattern. Show and play just one */
1575 if (G_UNLIKELY (first_notification)) {
1576 TnyAccount *account;
1578 first_notification = FALSE;
1580 /* Set the led pattern */
1581 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1583 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1585 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1587 /* Set the account of the headers */
1588 account = tny_folder_get_account (folder);
1590 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1592 tny_account_get_id (account));
1593 g_object_unref (account);
1597 /* Notify. We need to do this in an idle because this function
1598 could be called from a thread */
1599 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1601 /* Save id in the list */
1602 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1603 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1604 /* We don't listen for the "closed" signal, because we
1605 don't care about if the notification was removed or
1606 not to store the list in gconf */
1608 /* Free & carry on */
1609 g_free (display_address);
1611 g_object_unref (folder);
1612 g_object_unref (header);
1613 tny_iterator_next (iter);
1615 g_object_unref (iter);
1618 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1619 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1621 g_slist_free (notifications_list);
1623 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1627 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1630 #ifdef MODEST_HAVE_MCE
1631 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1635 MCE_DEACTIVATE_LED_PATTERN,
1637 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1643 #ifdef MODEST_HAVE_HILDON_NOTIFY
1644 GSList *notif_list = NULL;
1646 /* Get previous notifications ids */
1647 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1648 MODEST_CONF_NOTIFICATION_IDS,
1649 MODEST_CONF_VALUE_INT, NULL);
1651 while (notif_list) {
1653 NotifyNotification *notif;
1655 /* Nasty HACK to remove the notifications, set the id
1656 of the existing ones and then close them */
1657 notif_id = GPOINTER_TO_INT(notif_list->data);
1658 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1659 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1661 /* Close the notification, note that some ids could be
1662 already invalid, but we don't care because it does
1664 notify_notification_close(notif, NULL);
1665 g_object_unref(notif);
1667 /* Delete the link, it's like going to the next */
1668 notif_list = g_slist_delete_link (notif_list, notif_list);
1672 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1673 notif_list, MODEST_CONF_VALUE_INT, NULL);
1675 g_slist_free (notif_list);
1677 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1683 modest_platform_get_global_settings_dialog ()
1685 return modest_hildon2_global_settings_dialog_new ();
1689 modest_platform_show_help (GtkWindow *parent_window,
1690 const gchar *help_id)
1696 modest_platform_show_search_messages (GtkWindow *parent_window)
1698 osso_return_t result = OSSO_ERROR;
1700 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1701 "osso_global_search",
1702 "search_email", NULL, DBUS_TYPE_INVALID);
1704 if (result != OSSO_OK) {
1705 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1710 modest_platform_show_addressbook (GtkWindow *parent_window)
1712 osso_return_t result = OSSO_ERROR;
1714 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1716 "top_application", NULL, DBUS_TYPE_INVALID);
1718 if (result != OSSO_OK) {
1719 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1724 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1726 GtkWidget *widget = modest_folder_view_new (query);
1728 /* Show one account by default */
1729 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1730 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1732 /* Restore settings */
1733 modest_widget_memory_restore (modest_runtime_get_conf(),
1735 MODEST_CONF_FOLDER_VIEW_KEY);
1741 banner_finish (gpointer data, GObject *object)
1743 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1744 modest_window_mgr_unregister_banner (mgr);
1745 g_object_unref (mgr);
1749 modest_platform_information_banner (GtkWidget *parent,
1750 const gchar *icon_name,
1753 GtkWidget *banner, *banner_parent = NULL;
1754 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1756 if (modest_window_mgr_get_num_windows (mgr) == 0)
1759 if (parent && GTK_IS_WINDOW (parent)) {
1760 /* If the window is the active one then show the
1761 banner on top of this window */
1762 if (gtk_window_is_active (GTK_WINDOW (parent)))
1763 banner_parent = parent;
1764 /* If the window is not the topmost but it's visible
1765 (it's minimized for example) then show the banner
1767 else if (GTK_WIDGET_VISIBLE (parent))
1768 banner_parent = NULL;
1769 /* If the window is hidden (like the main window when
1770 running in the background) then do not show
1777 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1779 modest_window_mgr_register_banner (mgr);
1781 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1785 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1786 const gchar *icon_name,
1792 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1795 banner = hildon_banner_show_information (parent, icon_name, text);
1796 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1800 modest_platform_animation_banner (GtkWidget *parent,
1801 const gchar *animation_name,
1804 GtkWidget *inf_note = NULL;
1806 g_return_val_if_fail (text != NULL, NULL);
1808 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1811 /* If the parent is not visible then do not show */
1812 if (parent && !GTK_WIDGET_VISIBLE (parent))
1815 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1823 TnyAccount *account;
1826 } CheckAccountIdleData;
1828 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1831 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1833 gboolean stop_trying = FALSE;
1834 g_return_val_if_fail (data && data->account, FALSE);
1836 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1837 tny_account_get_connection_status (data->account));
1839 if (data && data->account &&
1840 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1841 * after which the account is likely to be usable, or never likely to be usable soon: */
1842 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1844 data->is_online = TRUE;
1848 /* Give up if we have tried too many times: */
1849 if (data->count_tries >= NUMBER_OF_TRIES) {
1852 /* Wait for another timeout: */
1853 ++(data->count_tries);
1858 /* Allow the function that requested this idle callback to continue: */
1860 g_main_loop_quit (data->loop);
1863 g_object_unref (data->account);
1865 return FALSE; /* Don't call this again. */
1867 return TRUE; /* Call this timeout callback again. */
1871 /* Return TRUE immediately if the account is already online,
1872 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1873 * soon as the account is online, or FALSE if the account does
1874 * not become online in the NUMBER_OF_TRIES seconds.
1875 * This is useful when the D-Bus method was run immediately after
1876 * the application was started (when using D-Bus activation),
1877 * because the account usually takes a short time to go online.
1878 * The return value is maybe not very useful.
1881 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1885 g_return_val_if_fail (account, FALSE);
1887 if (!tny_device_is_online (modest_runtime_get_device())) {
1888 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1892 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1893 * so we avoid wait unnecessarily: */
1894 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1897 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1898 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1899 * we want to avoid. */
1900 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1903 /* This blocks on the result: */
1904 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1905 data->is_online = FALSE;
1906 data->account = account;
1907 g_object_ref (data->account);
1908 data->count_tries = 0;
1910 GMainContext *context = NULL; /* g_main_context_new (); */
1911 data->loop = g_main_loop_new (context, FALSE /* not running */);
1913 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1915 /* This main loop will run until the idle handler has stopped it: */
1916 g_main_loop_run (data->loop);
1918 g_main_loop_unref (data->loop);
1919 /* g_main_context_unref (context); */
1921 is_online = data->is_online;
1922 g_slice_free (CheckAccountIdleData, data);
1930 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1932 /* GTK_RESPONSE_HELP means we need to show the certificate */
1933 if (response_id == GTK_RESPONSE_APPLY) {
1937 /* Do not close the dialog */
1938 g_signal_stop_emission_by_name (dialog, "response");
1940 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1941 note = hildon_note_new_information (NULL, msg);
1942 gtk_dialog_run (GTK_DIALOG(note));
1943 gtk_widget_destroy (note);
1949 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1950 const gchar *certificate)
1955 HildonWindowStack *stack;
1957 stack = hildon_window_stack_get_default ();
1958 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1961 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1966 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1969 /* We use GTK_RESPONSE_APPLY because we want the button in the
1970 middle of OK and CANCEL the same as the browser does for
1971 example. With GTK_RESPONSE_HELP the view button is aligned
1972 to the left while the other two to the right */
1973 note = hildon_note_new_confirmation_add_buttons (
1976 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1977 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1978 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1981 g_signal_connect (G_OBJECT(note), "response",
1982 G_CALLBACK(on_cert_dialog_response),
1983 (gpointer) certificate);
1985 response = gtk_dialog_run(GTK_DIALOG(note));
1987 on_destroy_dialog (note);
1990 return response == GTK_RESPONSE_OK;
1994 modest_platform_run_alert_dialog (const gchar* prompt,
1995 gboolean is_question)
1997 ModestWindow *top_win;
1998 HildonWindowStack *stack;
2000 stack = hildon_window_stack_get_default ();
2001 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
2004 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
2009 gboolean retval = TRUE;
2011 /* The Tinymail documentation says that we should show Yes and No buttons,
2012 * when it is a question.
2013 * Obviously, we need tinymail to use more specific error codes instead,
2014 * so we know what buttons to show. */
2015 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
2017 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2018 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
2020 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
2021 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
2023 on_destroy_dialog (dialog);
2025 /* Just show the error text and use the default response: */
2026 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
2034 GtkWindow *parent_window;
2035 ModestConnectedPerformer callback;
2036 TnyAccount *account;
2043 on_went_online_info_free (OnWentOnlineInfo *info)
2045 /* And if we cleanup, we DO cleanup :-) */
2048 g_object_unref (info->device);
2051 if (info->parent_window)
2052 g_object_unref (info->parent_window);
2054 g_object_unref (info->account);
2056 g_slice_free (OnWentOnlineInfo, info);
2058 /* We're done ... */
2064 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
2066 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2068 /* Now it's really time to callback to the caller. If going online didn't succeed,
2069 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
2070 * canceled will be set. Etcetera etcetera. */
2072 if (info->callback) {
2073 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2076 /* This is our last call, we must cleanup here if we didn't yet do that */
2077 on_went_online_info_free (info);
2084 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2086 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2087 info->iap = g_strdup (iap_id);
2089 if (canceled || err || !info->account) {
2091 /* If there's a problem or if there's no account (then that's it for us, we callback
2092 * the caller's callback now. He'll have to handle err or canceled, of course.
2093 * We are not really online, as the account is not really online here ... */
2095 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2096 * this info. We don't cleanup err, Tinymail does that! */
2098 if (info->callback) {
2100 /* info->account can be NULL here, this means that the user did not
2101 * provide a nice account instance. We'll assume that the user knows
2102 * what he's doing and is happy with just the device going online.
2104 * We can't do magic, we don't know what account the user wants to
2105 * see going online. So just the device goes online, end of story */
2107 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2110 } else if (info->account) {
2112 /* If there's no problem and if we have an account, we'll put the account
2113 * online too. When done, the callback of bringing the account online
2114 * will callback the caller's callback. This is the most normal case. */
2116 info->device = TNY_DEVICE (g_object_ref (device));
2118 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2119 on_account_went_online, info);
2121 /* The on_account_went_online cb frees up the info, go look if you
2122 * don't believe me! (so we return here) */
2127 /* We cleanup if we are not bringing the account online too */
2128 on_went_online_info_free (info);
2134 modest_platform_connect_and_perform (GtkWindow *parent_window,
2136 TnyAccount *account,
2137 ModestConnectedPerformer callback,
2140 gboolean device_online;
2142 TnyConnectionStatus conn_status;
2143 OnWentOnlineInfo *info;
2145 device = modest_runtime_get_device();
2146 device_online = tny_device_is_online (device);
2148 /* If there is no account check only the device status */
2151 if (device_online) {
2153 /* We promise to instantly perform the callback, so ... */
2155 callback (FALSE, NULL, parent_window, account, user_data);
2160 info = g_slice_new0 (OnWentOnlineInfo);
2163 info->device = NULL;
2164 info->account = NULL;
2167 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2169 info->parent_window = NULL;
2170 info->user_data = user_data;
2171 info->callback = callback;
2173 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2174 force, on_conic_device_went_online,
2177 /* We'll cleanup in on_conic_device_went_online */
2180 /* The other code has no more reason to run. This is all that we can do for the
2181 * caller (he should have given us a nice and clean account instance!). We
2182 * can't do magic, we don't know what account he intends to bring online. So
2183 * we'll just bring the device online (and await his false bug report). */
2189 /* Return if the account is already connected */
2191 conn_status = tny_account_get_connection_status (account);
2192 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2194 /* We promise to instantly perform the callback, so ... */
2196 callback (FALSE, NULL, parent_window, account, user_data);
2202 /* Else, we are in a state that requires that we go online before we
2203 * call the caller's callback. */
2205 info = g_slice_new0 (OnWentOnlineInfo);
2207 info->device = NULL;
2209 info->account = TNY_ACCOUNT (g_object_ref (account));
2212 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2214 info->parent_window = NULL;
2216 /* So we'll put the callback away for later ... */
2218 info->user_data = user_data;
2219 info->callback = callback;
2221 if (!device_online) {
2223 /* If also the device is offline, then we connect both the device
2224 * and the account */
2226 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2227 force, on_conic_device_went_online,
2232 /* If the device is online, we'll just connect the account */
2234 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2235 on_account_went_online, info);
2238 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2239 * in both situations, go look if you don't believe me! */
2245 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2247 TnyFolderStore *folder_store,
2248 ModestConnectedPerformer callback,
2251 TnyAccount *account = NULL;
2253 if (!folder_store ||
2254 (TNY_IS_MERGE_FOLDER (folder_store) &&
2255 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2257 /* We promise to instantly perform the callback, so ... */
2259 GError *error = NULL;
2260 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2261 "Unable to move or not found folder");
2262 callback (FALSE, error, parent_window, NULL, user_data);
2263 g_error_free (error);
2267 } else if (TNY_IS_FOLDER (folder_store)) {
2268 /* Get the folder's parent account: */
2269 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2270 } else if (TNY_IS_ACCOUNT (folder_store)) {
2271 /* Use the folder store as an account: */
2272 account = TNY_ACCOUNT (g_object_ref (folder_store));
2275 if (account && (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE)) {
2276 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2277 /* No need to connect a local account */
2279 callback (FALSE, NULL, parent_window, account, user_data);
2284 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2288 g_object_unref (account);
2292 src_account_connect_performer (gboolean canceled,
2294 GtkWindow *parent_window,
2295 TnyAccount *src_account,
2298 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2300 if (canceled || err) {
2301 /* If there was any error call the user callback */
2302 info->callback (canceled, err, parent_window, src_account, info->data);
2304 /* Connect the destination account */
2305 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2306 TNY_FOLDER_STORE (info->dst_account),
2307 info->callback, info->data);
2310 /* Free the info object */
2311 g_object_unref (info->dst_account);
2312 g_slice_free (DoubleConnectionInfo, info);
2317 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2319 TnyFolderStore *folder_store,
2320 DoubleConnectionInfo *connect_info)
2322 modest_platform_connect_if_remote_and_perform(parent_window,
2325 src_account_connect_performer,
2330 modest_platform_get_account_settings_wizard (void)
2332 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2334 return GTK_WIDGET (dialog);
2338 modest_platform_get_current_connection (void)
2340 TnyDevice *device = NULL;
2341 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2343 device = modest_runtime_get_device ();
2345 if (!tny_device_is_online (device))
2346 return MODEST_CONNECTED_VIA_ANY;
2348 #ifdef MODEST_HAVE_CONIC
2350 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2352 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2353 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2354 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2356 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2357 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2358 !strcmp (bearer_type, "WIMAX")) {
2359 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2361 retval = MODEST_CONNECTED_VIA_ANY;
2364 g_object_unref (iap);
2367 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2368 #endif /* MODEST_HAVE_CONIC */
2375 modest_platform_check_memory_low (ModestWindow *win,
2380 /* are we in low memory state? */
2381 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2383 if (win && lowmem && visuals)
2384 modest_platform_run_information_dialog (
2386 _KR("memr_ib_operation_disabled"),
2390 g_debug ("%s: low memory reached. disallowing some operations",
2397 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2403 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2406 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2407 GTK_WINDOW (dialog),
2409 gtk_widget_show_all (dialog);
2411 g_signal_connect_swapped (dialog, "response",
2412 G_CALLBACK (gtk_widget_destroy),
2417 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2423 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2426 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2427 GTK_WINDOW (dialog),
2429 gtk_widget_show_all (dialog);
2431 g_signal_connect_swapped (dialog, "response",
2432 G_CALLBACK (gtk_widget_destroy),
2437 modest_platform_get_osso_context (void)
2439 return modest_maemo_utils_get_osso_context ();
2443 _modest_platform_play_email_tone (void)
2445 gchar *active_profile;
2448 gint mail_volume_int;
2450 ca_context *ca_con = NULL;
2451 ca_proplist *pl = NULL;
2453 active_profile = profile_get_profile ();
2454 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2455 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2456 mail_volume_int = profile_parse_int (mail_volume);
2458 if (mail_tone && !strstr (mail_tone, "/")) {
2461 tmp = g_strconcat ("/usr/share/sounds", mail_tone, NULL);
2466 if (mail_volume_int > 0) {
2468 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2469 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2473 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2474 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2475 ca_context_destroy(ca_con);
2479 ca_proplist_create(&pl);
2480 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2481 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2483 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2484 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2486 ca_proplist_destroy(pl);
2487 ca_context_destroy(ca_con);
2490 g_free (mail_volume);
2492 g_free (active_profile);
2495 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
2496 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
2497 #define MOVE_TO_DIALOG_ACTION_BUTTON "action-button"
2498 #define MOVE_TO_DIALOG_SELECTION_LABEL "selection-label"
2499 #define MOVE_TO_DIALOG_SHOWING_FOLDERS "showing-folders"
2500 #define MOVE_TO_DIALOG_PANNABLE "pannable"
2503 move_to_dialog_show_accounts (GtkWidget *dialog)
2505 GtkWidget *selection_label;
2506 GtkWidget *back_button;
2507 GtkWidget *folder_view;
2508 GtkWidget *pannable;
2509 GtkWidget *action_button;
2511 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2512 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2513 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2514 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2515 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2517 gtk_widget_set_sensitive (back_button, FALSE);
2518 gtk_widget_set_sensitive (action_button, FALSE);
2520 gtk_label_set_text (GTK_LABEL (selection_label), "");
2521 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2522 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
2523 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2524 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2526 g_object_set (G_OBJECT (folder_view),
2527 "hildon-ui-mode", HILDON_UI_MODE_NORMAL,
2530 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (FALSE));
2534 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
2536 GtkWidget *selection_label;
2537 GtkWidget *back_button;
2538 GtkWidget *folder_view;
2539 TnyAccount *account;
2540 const gchar *account_id;
2541 gchar *selection_label_text;
2542 GtkWidget *pannable;
2543 GtkWidget *action_button;
2545 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2546 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2547 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2548 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2549 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2551 gtk_widget_set_sensitive (back_button, TRUE);
2552 gtk_widget_set_sensitive (action_button, FALSE);
2554 g_object_set (G_OBJECT (folder_view),
2555 "hildon-ui-mode", HILDON_UI_MODE_EDIT,
2558 account = TNY_ACCOUNT (folder_store);
2559 if (modest_tny_account_is_virtual_local_folders (account)) {
2561 account_id = tny_account_get_id (account);
2562 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2563 MODEST_CONF_DEVICE_NAME, NULL);
2565 selection_label_text = g_strconcat (device_name, "/", NULL);
2566 g_free (device_name);
2568 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2570 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2571 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2572 } else if (modest_tny_account_is_memory_card_account (account)) {
2573 account_id = tny_account_get_id (account);
2574 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2575 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2576 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2578 account_id = tny_account_get_id (account);
2580 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2581 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2582 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2583 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2584 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2586 gtk_label_set_text (GTK_LABEL (selection_label), selection_label_text);
2587 g_free (selection_label_text);
2589 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
2592 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
2593 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
2594 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2595 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2597 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (TRUE));
2601 move_to_dialog_set_selected_folder (GtkWidget *dialog, TnyFolderStore *folder_store)
2603 GtkWidget *selection_label;
2604 GtkWidget *action_button;
2607 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2608 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2610 gtk_widget_set_sensitive (action_button, TRUE);
2612 if (TNY_IS_FOLDER (folder_store)) {
2613 folder_name = modest_tny_folder_get_display_name (TNY_FOLDER (folder_store));
2614 } else if (TNY_IS_ACCOUNT (folder_store)) {
2615 folder_name = g_strdup (tny_account_get_name (TNY_ACCOUNT (folder_store)));
2617 folder_name = g_strdup ("");
2620 gtk_label_set_text (GTK_LABEL (selection_label), folder_name);
2621 g_free (folder_name);
2626 on_move_to_dialog_back_clicked (GtkButton *button,
2629 GtkWidget *dialog = (GtkWidget *) userdata;
2630 ModestFolderView *folder_view;
2632 /* Revert the effect of show_folders filters */
2633 folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2634 modest_folder_view_set_account_id_of_visible_server_account (folder_view, NULL);
2635 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2636 modest_folder_view_unset_filter (folder_view, MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2637 modest_folder_view_unset_filter (folder_view, MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2639 /* Back to show accounts */
2640 move_to_dialog_show_accounts (dialog);
2644 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2646 GtkTreeViewColumn *column,
2649 TnyFolderStore *selected;
2651 GtkWidget *folder_view;
2652 gboolean showing_folders;
2654 dialog = (GtkWidget *) user_data;
2655 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2656 if (!showing_folders) {
2657 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2659 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2661 move_to_dialog_show_folders (dialog, selected);
2667 on_move_to_dialog_selection_changed (GtkTreeSelection *selection,
2670 TnyFolderStore *selected;
2672 GtkWidget *folder_view;
2673 gboolean showing_folders;
2675 dialog = (GtkWidget *) user_data;
2676 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2677 if (showing_folders) {
2678 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2679 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2682 move_to_dialog_set_selected_folder (dialog, selected);
2687 on_move_to_dialog_action_clicked (GtkButton *selection,
2690 TnyFolderStore *selected;
2692 GtkWidget *folder_view;
2693 gboolean showing_folders;
2695 dialog = (GtkWidget *) user_data;
2696 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2697 if (showing_folders) {
2698 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2699 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2702 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
2707 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2708 GtkWidget **folder_view)
2710 GtkWidget *dialog, *folder_view_container;
2712 GtkWidget *buttons_hbox;
2713 GtkWidget *back_button, *selection_label;
2714 GdkPixbuf *back_pixbuf;
2715 GtkWidget *top_vbox;
2716 GtkWidget *action_button;
2717 GtkTreeSelection *selection;
2719 /* Create dialog. We cannot use a touch selector because we
2720 need to use here the folder view widget directly */
2721 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2722 GTK_WINDOW (parent_window),
2723 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2724 GTK_DIALOG_DESTROY_WITH_PARENT,
2725 _HL("wdgt_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2728 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
2729 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_NONE);
2730 top_vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
2732 /* Create folder view */
2733 *folder_view = modest_platform_create_folder_view (NULL);
2735 modest_folder_view_set_cell_style (MODEST_FOLDER_VIEW (*folder_view),
2736 MODEST_FOLDER_VIEW_CELL_STYLE_COMPACT);
2737 modest_folder_view_show_message_count (MODEST_FOLDER_VIEW (*folder_view),
2739 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2740 (TnyAccountStore *) modest_runtime_get_account_store ());
2742 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
2743 back_button = gtk_button_new ();
2744 back_pixbuf = modest_platform_get_icon (_FM("filemanager_folder_up"), MODEST_ICON_SIZE_BIG);
2746 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
2747 g_object_unref (back_pixbuf);
2749 selection_label = gtk_label_new ("");
2750 gtk_misc_set_alignment (GTK_MISC (selection_label), 0.0, 0.5);
2752 action_button = gtk_button_new ();
2753 gtk_container_add (GTK_CONTAINER (action_button), selection_label);
2755 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
2756 gtk_box_pack_start (GTK_BOX (buttons_hbox), action_button, TRUE, TRUE, 0);
2757 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
2758 gtk_widget_set_sensitive (GTK_WIDGET (action_button), FALSE);
2759 gtk_box_pack_start (GTK_BOX (top_vbox), buttons_hbox, FALSE, FALSE, 0);
2761 /* Create pannable and add it to the dialog */
2762 folder_view_container = hildon_pannable_area_new ();
2763 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2764 gtk_box_pack_start (GTK_BOX (top_vbox), folder_view_container, TRUE, TRUE, 0);
2766 gtk_container_add (GTK_CONTAINER (align), top_vbox);
2767 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), align, TRUE, TRUE, 0);
2769 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2771 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2772 gtk_widget_show (folder_view_container);
2773 gtk_widget_show (align);
2774 gtk_widget_show (top_vbox);
2775 gtk_widget_show (*folder_view);
2776 gtk_widget_show_all (back_button);
2777 gtk_widget_show (selection_label);
2778 gtk_widget_show (action_button);
2779 gtk_widget_show (buttons_hbox);
2781 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
2782 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
2783 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON, action_button);
2784 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL, selection_label);
2785 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE, folder_view_container);
2787 /* Simulate the behaviour of a HildonPickerDialog by emitting
2788 a response when a folder is selected */
2789 g_signal_connect (*folder_view, "row-activated",
2790 G_CALLBACK (on_move_to_dialog_folder_activated),
2793 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (*folder_view));
2794 g_signal_connect (selection, "changed",
2795 G_CALLBACK (on_move_to_dialog_selection_changed),
2798 g_signal_connect (action_button, "clicked",
2799 G_CALLBACK (on_move_to_dialog_action_clicked),
2802 g_signal_connect (back_button, "clicked",
2803 G_CALLBACK (on_move_to_dialog_back_clicked),
2806 move_to_dialog_show_accounts (dialog);
2812 modest_platform_get_list_to_move (ModestWindow *window)
2814 TnyList *list = NULL;
2816 if (MODEST_IS_HEADER_WINDOW (window)) {
2817 ModestHeaderView *header_view;
2819 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2820 list = modest_header_view_get_selected_headers (header_view);
2821 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2822 ModestFolderView *folder_view;
2823 TnyFolderStore *selected_folder;
2825 list = TNY_LIST (tny_simple_list_new ());
2826 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2827 selected_folder = modest_folder_view_get_selected (folder_view);
2828 if (selected_folder) {
2829 tny_list_prepend (list, G_OBJECT (selected_folder));
2830 g_object_unref (selected_folder);
2833 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2836 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2838 list = TNY_LIST (tny_simple_list_new ());
2839 tny_list_prepend (list, G_OBJECT (header));
2840 g_object_unref (header);
2843 g_return_val_if_reached (NULL);