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);
1350 if (g_signal_handler_is_connected (account, data->handler))
1351 g_signal_handler_disconnect (account, data->handler);
1352 g_mutex_free (data->mutex);
1353 g_main_loop_unref (data->wait_loop);
1354 g_slice_free (ConnectAndWaitData, data);
1357 conn_status = tny_account_get_connection_status (account);
1358 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1362 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1364 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1365 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1366 /* This must be a maildir account, which does not require a connection: */
1371 return modest_platform_connect_and_wait (parent_window, account);
1375 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1378 return TRUE; /* Maybe it is something local. */
1380 gboolean result = TRUE;
1381 if (TNY_IS_FOLDER (folder_store)) {
1382 /* Get the folder's parent account: */
1383 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1384 if (account != NULL) {
1385 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1386 g_object_unref (account);
1388 } else if (TNY_IS_ACCOUNT (folder_store)) {
1389 /* Use the folder store as an account: */
1390 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1397 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1401 dialog = modest_hildon2_sort_dialog_new (parent_window);
1408 modest_platform_set_update_interval (guint minutes)
1410 #ifdef MODEST_HAVE_LIBALARM
1412 ModestConf *conf = modest_runtime_get_conf ();
1416 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1418 /* Delete any existing alarm,
1419 * because we will replace it: */
1421 if (alarmd_event_del(alarm_cookie) != 0)
1422 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1424 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1427 /* 0 means no updates: */
1432 /* Register alarm: */
1434 /* Set the interval in alarm_event_t structure: */
1435 alarm_event_t *event = alarm_event_create ();
1436 alarm_event_add_actions (event, 1);
1437 alarm_action_t *action = alarm_event_get_action (event, 0);
1438 alarm_event_set_alarm_appid (event, MODEST_ALARMD_APPID);
1439 event->alarm_time = minutes * 60; /* seconds */
1441 /* Set recurrence every few minutes: */
1442 event->recur_secs = minutes*60;
1443 event->recur_count = -1; /* Means infinite */
1445 /* Specify what should happen when the alarm happens:
1446 * It should call this D-Bus method: */
1448 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1449 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1450 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1451 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1452 action->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1454 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1455 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1456 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1457 * This is why we want to use the Alarm API instead of just g_timeout_add().
1458 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1459 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1461 event->flags = ALARM_EVENT_CONNECTED;
1463 alarm_cookie = alarmd_event_add (event);
1466 alarm_event_delete (event);
1468 /* Store the alarm ID in GConf, so we can remove it later:
1469 * This is apparently valid between application instances. */
1470 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1472 if (!alarm_cookie) {
1474 g_debug ("Error setting alarm event. \n");
1478 #endif /* MODEST_HAVE_LIBALARM */
1483 modest_platform_push_email_notification(void)
1485 gboolean screen_on, app_in_foreground;
1487 /* Get the window status */
1488 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1490 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1492 /* If the screen is on and the app is in the
1493 foreground we don't show anything */
1494 if (!(screen_on && app_in_foreground)) {
1496 _modest_platform_play_email_tone ();
1498 /* Activate LED. This must be deactivated by
1499 modest_platform_remove_new_mail_notifications */
1500 #ifdef MODEST_HAVE_MCE
1501 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1505 MCE_ACTIVATE_LED_PATTERN,
1507 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1514 modest_platform_on_new_headers_received (TnyList *header_list,
1515 gboolean show_visual)
1517 g_return_if_fail (TNY_IS_LIST(header_list));
1519 if (tny_list_get_length(header_list) == 0) {
1520 g_warning ("%s: header list is empty", __FUNCTION__);
1525 modest_platform_push_email_notification ();
1526 /* We do a return here to avoid indentation with an else */
1530 #ifdef MODEST_HAVE_HILDON_NOTIFY
1531 HildonNotification *notification;
1533 GSList *notifications_list = NULL;
1535 /* Get previous notifications ids */
1536 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1537 MODEST_CONF_NOTIFICATION_IDS,
1538 MODEST_CONF_VALUE_INT, NULL);
1540 iter = tny_list_create_iterator (header_list);
1541 while (!tny_iterator_is_done (iter)) {
1542 gchar *url = NULL, *display_address = NULL;
1543 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1544 TnyFolder *folder = tny_header_get_folder (header);
1545 gboolean first_notification = TRUE;
1549 display_address = tny_header_dup_from (header);
1550 /* string is changed in-place */
1551 modest_text_utils_get_display_address (display_address);
1553 str = tny_header_dup_subject (header);
1554 notification = hildon_notification_new (display_address,
1556 "qgn_list_messagin",
1557 MODEST_NOTIFICATION_CATEGORY);
1559 /* Create the message URL */
1560 str = tny_header_dup_uid (header);
1561 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1565 hildon_notification_add_dbus_action(notification,
1568 MODEST_DBUS_SERVICE,
1571 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1575 /* Play sound if the user wants. Show the LED
1576 pattern. Show and play just one */
1577 if (G_UNLIKELY (first_notification)) {
1578 TnyAccount *account;
1580 first_notification = FALSE;
1582 /* Set the led pattern */
1583 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1585 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1587 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1589 /* Set the account of the headers */
1590 account = tny_folder_get_account (folder);
1592 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1594 tny_account_get_id (account));
1595 g_object_unref (account);
1599 /* Notify. We need to do this in an idle because this function
1600 could be called from a thread */
1601 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1603 /* Save id in the list */
1604 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1605 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1606 /* We don't listen for the "closed" signal, because we
1607 don't care about if the notification was removed or
1608 not to store the list in gconf */
1610 /* Free & carry on */
1611 g_free (display_address);
1613 g_object_unref (folder);
1614 g_object_unref (header);
1615 tny_iterator_next (iter);
1617 g_object_unref (iter);
1620 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1621 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1623 g_slist_free (notifications_list);
1625 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1629 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1632 #ifdef MODEST_HAVE_MCE
1633 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1637 MCE_DEACTIVATE_LED_PATTERN,
1639 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1645 #ifdef MODEST_HAVE_HILDON_NOTIFY
1646 GSList *notif_list = NULL;
1648 /* Get previous notifications ids */
1649 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1650 MODEST_CONF_NOTIFICATION_IDS,
1651 MODEST_CONF_VALUE_INT, NULL);
1653 while (notif_list) {
1655 NotifyNotification *notif;
1657 /* Nasty HACK to remove the notifications, set the id
1658 of the existing ones and then close them */
1659 notif_id = GPOINTER_TO_INT(notif_list->data);
1660 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1661 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1663 /* Close the notification, note that some ids could be
1664 already invalid, but we don't care because it does
1666 notify_notification_close(notif, NULL);
1667 g_object_unref(notif);
1669 /* Delete the link, it's like going to the next */
1670 notif_list = g_slist_delete_link (notif_list, notif_list);
1674 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1675 notif_list, MODEST_CONF_VALUE_INT, NULL);
1677 g_slist_free (notif_list);
1679 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1685 modest_platform_get_global_settings_dialog ()
1687 return modest_hildon2_global_settings_dialog_new ();
1691 modest_platform_show_help (GtkWindow *parent_window,
1692 const gchar *help_id)
1698 modest_platform_show_search_messages (GtkWindow *parent_window)
1700 osso_return_t result = OSSO_ERROR;
1702 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1703 "osso_global_search",
1704 "search_email", NULL, DBUS_TYPE_INVALID);
1706 if (result != OSSO_OK) {
1707 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1712 modest_platform_show_addressbook (GtkWindow *parent_window)
1714 osso_return_t result = OSSO_ERROR;
1716 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1718 "top_application", NULL, DBUS_TYPE_INVALID);
1720 if (result != OSSO_OK) {
1721 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1726 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1728 GtkWidget *widget = modest_folder_view_new (query);
1730 /* Show one account by default */
1731 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1732 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1734 /* Restore settings */
1735 modest_widget_memory_restore (modest_runtime_get_conf(),
1737 MODEST_CONF_FOLDER_VIEW_KEY);
1743 banner_finish (gpointer data, GObject *object)
1745 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1746 modest_window_mgr_unregister_banner (mgr);
1747 g_object_unref (mgr);
1751 modest_platform_information_banner (GtkWidget *parent,
1752 const gchar *icon_name,
1755 GtkWidget *banner, *banner_parent = NULL;
1756 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1758 if (modest_window_mgr_get_num_windows (mgr) == 0)
1761 if (parent && GTK_IS_WINDOW (parent)) {
1762 /* If the window is the active one then show the
1763 banner on top of this window */
1764 if (gtk_window_is_active (GTK_WINDOW (parent)))
1765 banner_parent = parent;
1766 /* If the window is not the topmost but it's visible
1767 (it's minimized for example) then show the banner
1769 else if (GTK_WIDGET_VISIBLE (parent))
1770 banner_parent = NULL;
1771 /* If the window is hidden (like the main window when
1772 running in the background) then do not show
1779 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1781 modest_window_mgr_register_banner (mgr);
1783 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1787 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1788 const gchar *icon_name,
1794 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1797 banner = hildon_banner_show_information (parent, icon_name, text);
1798 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1802 modest_platform_animation_banner (GtkWidget *parent,
1803 const gchar *animation_name,
1806 GtkWidget *inf_note = NULL;
1808 g_return_val_if_fail (text != NULL, NULL);
1810 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1813 /* If the parent is not visible then do not show */
1814 if (parent && !GTK_WIDGET_VISIBLE (parent))
1817 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1825 TnyAccount *account;
1828 } CheckAccountIdleData;
1830 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1833 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1835 gboolean stop_trying = FALSE;
1836 g_return_val_if_fail (data && data->account, FALSE);
1838 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1839 tny_account_get_connection_status (data->account));
1841 if (data && data->account &&
1842 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1843 * after which the account is likely to be usable, or never likely to be usable soon: */
1844 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1846 data->is_online = TRUE;
1850 /* Give up if we have tried too many times: */
1851 if (data->count_tries >= NUMBER_OF_TRIES) {
1854 /* Wait for another timeout: */
1855 ++(data->count_tries);
1860 /* Allow the function that requested this idle callback to continue: */
1862 g_main_loop_quit (data->loop);
1865 g_object_unref (data->account);
1867 return FALSE; /* Don't call this again. */
1869 return TRUE; /* Call this timeout callback again. */
1873 /* Return TRUE immediately if the account is already online,
1874 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1875 * soon as the account is online, or FALSE if the account does
1876 * not become online in the NUMBER_OF_TRIES seconds.
1877 * This is useful when the D-Bus method was run immediately after
1878 * the application was started (when using D-Bus activation),
1879 * because the account usually takes a short time to go online.
1880 * The return value is maybe not very useful.
1883 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1887 g_return_val_if_fail (account, FALSE);
1889 if (!tny_device_is_online (modest_runtime_get_device())) {
1890 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1894 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1895 * so we avoid wait unnecessarily: */
1896 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1899 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1900 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1901 * we want to avoid. */
1902 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1905 /* This blocks on the result: */
1906 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1907 data->is_online = FALSE;
1908 data->account = account;
1909 g_object_ref (data->account);
1910 data->count_tries = 0;
1912 GMainContext *context = NULL; /* g_main_context_new (); */
1913 data->loop = g_main_loop_new (context, FALSE /* not running */);
1915 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1917 /* This main loop will run until the idle handler has stopped it: */
1918 g_main_loop_run (data->loop);
1920 g_main_loop_unref (data->loop);
1921 /* g_main_context_unref (context); */
1923 is_online = data->is_online;
1924 g_slice_free (CheckAccountIdleData, data);
1932 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1934 /* GTK_RESPONSE_HELP means we need to show the certificate */
1935 if (response_id == GTK_RESPONSE_APPLY) {
1939 /* Do not close the dialog */
1940 g_signal_stop_emission_by_name (dialog, "response");
1942 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1943 note = hildon_note_new_information (NULL, msg);
1944 gtk_dialog_run (GTK_DIALOG(note));
1945 gtk_widget_destroy (note);
1951 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1952 const gchar *certificate)
1957 HildonWindowStack *stack;
1959 stack = hildon_window_stack_get_default ();
1960 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1963 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1968 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1971 /* We use GTK_RESPONSE_APPLY because we want the button in the
1972 middle of OK and CANCEL the same as the browser does for
1973 example. With GTK_RESPONSE_HELP the view button is aligned
1974 to the left while the other two to the right */
1975 note = hildon_note_new_confirmation_add_buttons (
1978 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1979 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1980 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1983 g_signal_connect (G_OBJECT(note), "response",
1984 G_CALLBACK(on_cert_dialog_response),
1985 (gpointer) certificate);
1987 response = gtk_dialog_run(GTK_DIALOG(note));
1989 on_destroy_dialog (note);
1992 return response == GTK_RESPONSE_OK;
1996 modest_platform_run_alert_dialog (const gchar* prompt,
1997 gboolean is_question)
1999 ModestWindow *top_win;
2000 HildonWindowStack *stack;
2002 stack = hildon_window_stack_get_default ();
2003 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
2006 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
2011 gboolean retval = TRUE;
2013 /* The Tinymail documentation says that we should show Yes and No buttons,
2014 * when it is a question.
2015 * Obviously, we need tinymail to use more specific error codes instead,
2016 * so we know what buttons to show. */
2017 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
2019 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2020 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
2022 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
2023 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
2025 on_destroy_dialog (dialog);
2027 /* Just show the error text and use the default response: */
2028 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
2036 GtkWindow *parent_window;
2037 ModestConnectedPerformer callback;
2038 TnyAccount *account;
2045 on_went_online_info_free (OnWentOnlineInfo *info)
2047 /* And if we cleanup, we DO cleanup :-) */
2050 g_object_unref (info->device);
2053 if (info->parent_window)
2054 g_object_unref (info->parent_window);
2056 g_object_unref (info->account);
2058 g_slice_free (OnWentOnlineInfo, info);
2060 /* We're done ... */
2066 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
2068 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2070 /* Now it's really time to callback to the caller. If going online didn't succeed,
2071 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
2072 * canceled will be set. Etcetera etcetera. */
2074 if (info->callback) {
2075 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2078 /* This is our last call, we must cleanup here if we didn't yet do that */
2079 on_went_online_info_free (info);
2086 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2088 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2089 info->iap = g_strdup (iap_id);
2091 if (canceled || err || !info->account) {
2093 /* If there's a problem or if there's no account (then that's it for us, we callback
2094 * the caller's callback now. He'll have to handle err or canceled, of course.
2095 * We are not really online, as the account is not really online here ... */
2097 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2098 * this info. We don't cleanup err, Tinymail does that! */
2100 if (info->callback) {
2102 /* info->account can be NULL here, this means that the user did not
2103 * provide a nice account instance. We'll assume that the user knows
2104 * what he's doing and is happy with just the device going online.
2106 * We can't do magic, we don't know what account the user wants to
2107 * see going online. So just the device goes online, end of story */
2109 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2112 } else if (info->account) {
2114 /* If there's no problem and if we have an account, we'll put the account
2115 * online too. When done, the callback of bringing the account online
2116 * will callback the caller's callback. This is the most normal case. */
2118 info->device = TNY_DEVICE (g_object_ref (device));
2120 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2121 on_account_went_online, info);
2123 /* The on_account_went_online cb frees up the info, go look if you
2124 * don't believe me! (so we return here) */
2129 /* We cleanup if we are not bringing the account online too */
2130 on_went_online_info_free (info);
2136 modest_platform_connect_and_perform (GtkWindow *parent_window,
2138 TnyAccount *account,
2139 ModestConnectedPerformer callback,
2142 gboolean device_online;
2144 TnyConnectionStatus conn_status;
2145 OnWentOnlineInfo *info;
2147 device = modest_runtime_get_device();
2148 device_online = tny_device_is_online (device);
2150 /* If there is no account check only the device status */
2153 if (device_online) {
2155 /* We promise to instantly perform the callback, so ... */
2157 callback (FALSE, NULL, parent_window, account, user_data);
2162 info = g_slice_new0 (OnWentOnlineInfo);
2165 info->device = NULL;
2166 info->account = NULL;
2169 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2171 info->parent_window = NULL;
2172 info->user_data = user_data;
2173 info->callback = callback;
2175 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2176 force, on_conic_device_went_online,
2179 /* We'll cleanup in on_conic_device_went_online */
2182 /* The other code has no more reason to run. This is all that we can do for the
2183 * caller (he should have given us a nice and clean account instance!). We
2184 * can't do magic, we don't know what account he intends to bring online. So
2185 * we'll just bring the device online (and await his false bug report). */
2191 /* Return if the account is already connected */
2193 conn_status = tny_account_get_connection_status (account);
2194 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2196 /* We promise to instantly perform the callback, so ... */
2198 callback (FALSE, NULL, parent_window, account, user_data);
2204 /* Else, we are in a state that requires that we go online before we
2205 * call the caller's callback. */
2207 info = g_slice_new0 (OnWentOnlineInfo);
2209 info->device = NULL;
2211 info->account = TNY_ACCOUNT (g_object_ref (account));
2214 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2216 info->parent_window = NULL;
2218 /* So we'll put the callback away for later ... */
2220 info->user_data = user_data;
2221 info->callback = callback;
2223 if (!device_online) {
2225 /* If also the device is offline, then we connect both the device
2226 * and the account */
2228 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2229 force, on_conic_device_went_online,
2234 /* If the device is online, we'll just connect the account */
2236 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2237 on_account_went_online, info);
2240 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2241 * in both situations, go look if you don't believe me! */
2247 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2249 TnyFolderStore *folder_store,
2250 ModestConnectedPerformer callback,
2253 TnyAccount *account = NULL;
2255 if (!folder_store ||
2256 (TNY_IS_MERGE_FOLDER (folder_store) &&
2257 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2259 /* We promise to instantly perform the callback, so ... */
2261 GError *error = NULL;
2262 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2263 "Unable to move or not found folder");
2264 callback (FALSE, error, parent_window, NULL, user_data);
2265 g_error_free (error);
2269 } else if (TNY_IS_FOLDER (folder_store)) {
2270 /* Get the folder's parent account: */
2271 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2272 } else if (TNY_IS_ACCOUNT (folder_store)) {
2273 /* Use the folder store as an account: */
2274 account = TNY_ACCOUNT (g_object_ref (folder_store));
2277 if (account && (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE)) {
2278 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2279 /* No need to connect a local account */
2281 callback (FALSE, NULL, parent_window, account, user_data);
2286 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2290 g_object_unref (account);
2294 src_account_connect_performer (gboolean canceled,
2296 GtkWindow *parent_window,
2297 TnyAccount *src_account,
2300 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2302 if (canceled || err) {
2303 /* If there was any error call the user callback */
2304 info->callback (canceled, err, parent_window, src_account, info->data);
2306 /* Connect the destination account */
2307 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2308 TNY_FOLDER_STORE (info->dst_account),
2309 info->callback, info->data);
2312 /* Free the info object */
2313 g_object_unref (info->dst_account);
2314 g_slice_free (DoubleConnectionInfo, info);
2319 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2321 TnyFolderStore *folder_store,
2322 DoubleConnectionInfo *connect_info)
2324 modest_platform_connect_if_remote_and_perform(parent_window,
2327 src_account_connect_performer,
2332 modest_platform_get_account_settings_wizard (void)
2334 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2336 return GTK_WIDGET (dialog);
2340 modest_platform_get_current_connection (void)
2342 TnyDevice *device = NULL;
2343 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2345 device = modest_runtime_get_device ();
2347 if (!tny_device_is_online (device))
2348 return MODEST_CONNECTED_VIA_ANY;
2350 #ifdef MODEST_HAVE_CONIC
2352 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2354 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2355 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2356 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2358 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2359 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2360 !strcmp (bearer_type, "WIMAX")) {
2361 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2363 retval = MODEST_CONNECTED_VIA_ANY;
2366 g_object_unref (iap);
2369 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2370 #endif /* MODEST_HAVE_CONIC */
2377 modest_platform_check_memory_low (ModestWindow *win,
2382 /* are we in low memory state? */
2383 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2385 if (win && lowmem && visuals)
2386 modest_platform_run_information_dialog (
2388 _KR("memr_ib_operation_disabled"),
2392 g_debug ("%s: low memory reached. disallowing some operations",
2399 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2405 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2408 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2409 GTK_WINDOW (dialog),
2411 gtk_widget_show_all (dialog);
2413 g_signal_connect_swapped (dialog, "response",
2414 G_CALLBACK (gtk_widget_destroy),
2419 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2425 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2428 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2429 GTK_WINDOW (dialog),
2431 gtk_widget_show_all (dialog);
2433 g_signal_connect_swapped (dialog, "response",
2434 G_CALLBACK (gtk_widget_destroy),
2439 modest_platform_get_osso_context (void)
2441 return modest_maemo_utils_get_osso_context ();
2445 _modest_platform_play_email_tone (void)
2447 gchar *active_profile;
2450 gint mail_volume_int;
2452 ca_context *ca_con = NULL;
2453 ca_proplist *pl = NULL;
2455 active_profile = profile_get_profile ();
2456 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2457 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2458 mail_volume_int = profile_parse_int (mail_volume);
2460 if (mail_tone && !strstr (mail_tone, "/")) {
2463 tmp = g_strconcat ("/usr/share/sounds", mail_tone, NULL);
2468 if (mail_volume_int > 0) {
2470 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2471 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2475 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2476 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2477 ca_context_destroy(ca_con);
2481 ca_proplist_create(&pl);
2482 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2483 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2485 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2486 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2488 ca_proplist_destroy(pl);
2489 ca_context_destroy(ca_con);
2492 g_free (mail_volume);
2494 g_free (active_profile);
2497 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
2498 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
2499 #define MOVE_TO_DIALOG_ACTION_BUTTON "action-button"
2500 #define MOVE_TO_DIALOG_SELECTION_LABEL "selection-label"
2501 #define MOVE_TO_DIALOG_SHOWING_FOLDERS "showing-folders"
2502 #define MOVE_TO_DIALOG_PANNABLE "pannable"
2505 move_to_dialog_show_accounts (GtkWidget *dialog)
2507 GtkWidget *selection_label;
2508 GtkWidget *back_button;
2509 GtkWidget *folder_view;
2510 GtkWidget *pannable;
2511 GtkWidget *action_button;
2513 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2514 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2515 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2516 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2517 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2519 gtk_widget_set_sensitive (back_button, FALSE);
2520 gtk_widget_set_sensitive (action_button, FALSE);
2522 gtk_label_set_text (GTK_LABEL (selection_label), "");
2523 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2524 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
2525 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2526 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2528 g_object_set (G_OBJECT (folder_view),
2529 "hildon-ui-mode", HILDON_UI_MODE_NORMAL,
2532 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (FALSE));
2536 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
2538 GtkWidget *selection_label;
2539 GtkWidget *back_button;
2540 GtkWidget *folder_view;
2541 TnyAccount *account;
2542 const gchar *account_id;
2543 gchar *selection_label_text;
2544 GtkWidget *pannable;
2545 GtkWidget *action_button;
2547 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2548 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2549 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2550 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2551 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2553 gtk_widget_set_sensitive (back_button, TRUE);
2554 gtk_widget_set_sensitive (action_button, FALSE);
2556 g_object_set (G_OBJECT (folder_view),
2557 "hildon-ui-mode", HILDON_UI_MODE_EDIT,
2560 account = TNY_ACCOUNT (folder_store);
2561 if (modest_tny_account_is_virtual_local_folders (account)) {
2563 account_id = tny_account_get_id (account);
2564 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2565 MODEST_CONF_DEVICE_NAME, NULL);
2567 selection_label_text = g_strconcat (device_name, "/", NULL);
2568 g_free (device_name);
2570 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2572 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2573 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2574 } else if (modest_tny_account_is_memory_card_account (account)) {
2575 account_id = tny_account_get_id (account);
2576 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2577 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2578 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2580 account_id = tny_account_get_id (account);
2582 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2583 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2584 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2585 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2586 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2588 gtk_label_set_text (GTK_LABEL (selection_label), selection_label_text);
2589 g_free (selection_label_text);
2591 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
2594 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
2595 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
2596 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2597 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2599 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (TRUE));
2603 move_to_dialog_set_selected_folder (GtkWidget *dialog, TnyFolderStore *folder_store)
2605 GtkWidget *selection_label;
2606 GtkWidget *action_button;
2609 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2610 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2612 gtk_widget_set_sensitive (action_button, TRUE);
2614 if (TNY_IS_FOLDER (folder_store)) {
2615 folder_name = modest_tny_folder_get_display_name (TNY_FOLDER (folder_store));
2616 } else if (TNY_IS_ACCOUNT (folder_store)) {
2617 folder_name = g_strdup (tny_account_get_name (TNY_ACCOUNT (folder_store)));
2619 folder_name = g_strdup ("");
2622 gtk_label_set_text (GTK_LABEL (selection_label), folder_name);
2623 g_free (folder_name);
2628 on_move_to_dialog_back_clicked (GtkButton *button,
2631 GtkWidget *dialog = (GtkWidget *) userdata;
2632 ModestFolderView *folder_view;
2634 /* Revert the effect of show_folders filters */
2635 folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2636 modest_folder_view_set_account_id_of_visible_server_account (folder_view, NULL);
2637 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2638 modest_folder_view_unset_filter (folder_view, MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2639 modest_folder_view_unset_filter (folder_view, MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2641 /* Back to show accounts */
2642 move_to_dialog_show_accounts (dialog);
2646 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2648 GtkTreeViewColumn *column,
2651 TnyFolderStore *selected;
2653 GtkWidget *folder_view;
2654 gboolean showing_folders;
2656 dialog = (GtkWidget *) user_data;
2657 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2658 if (!showing_folders) {
2659 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2661 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2663 move_to_dialog_show_folders (dialog, selected);
2669 on_move_to_dialog_selection_changed (GtkTreeSelection *selection,
2672 TnyFolderStore *selected;
2674 GtkWidget *folder_view;
2675 gboolean showing_folders;
2677 dialog = (GtkWidget *) user_data;
2678 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2679 if (showing_folders) {
2680 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2681 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2684 move_to_dialog_set_selected_folder (dialog, selected);
2689 on_move_to_dialog_action_clicked (GtkButton *selection,
2692 TnyFolderStore *selected;
2694 GtkWidget *folder_view;
2695 gboolean showing_folders;
2697 dialog = (GtkWidget *) user_data;
2698 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2699 if (showing_folders) {
2700 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2701 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2704 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
2709 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2710 GtkWidget **folder_view)
2712 GtkWidget *dialog, *folder_view_container;
2714 GtkWidget *buttons_hbox;
2715 GtkWidget *back_button, *selection_label;
2716 GdkPixbuf *back_pixbuf;
2717 GtkWidget *top_vbox;
2718 GtkWidget *action_button;
2719 GtkTreeSelection *selection;
2721 /* Create dialog. We cannot use a touch selector because we
2722 need to use here the folder view widget directly */
2723 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2724 GTK_WINDOW (parent_window),
2725 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2726 GTK_DIALOG_DESTROY_WITH_PARENT,
2727 _HL("wdgt_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2730 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
2731 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_NONE);
2732 top_vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
2734 /* Create folder view */
2735 *folder_view = modest_platform_create_folder_view (NULL);
2737 modest_folder_view_set_cell_style (MODEST_FOLDER_VIEW (*folder_view),
2738 MODEST_FOLDER_VIEW_CELL_STYLE_COMPACT);
2739 modest_folder_view_show_message_count (MODEST_FOLDER_VIEW (*folder_view),
2741 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2742 (TnyAccountStore *) modest_runtime_get_account_store ());
2744 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
2745 back_button = gtk_button_new ();
2746 back_pixbuf = modest_platform_get_icon (_FM("filemanager_folder_up"), MODEST_ICON_SIZE_BIG);
2748 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
2749 g_object_unref (back_pixbuf);
2751 selection_label = gtk_label_new ("");
2752 gtk_misc_set_alignment (GTK_MISC (selection_label), 0.0, 0.5);
2754 action_button = gtk_button_new ();
2755 gtk_container_add (GTK_CONTAINER (action_button), selection_label);
2757 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
2758 gtk_box_pack_start (GTK_BOX (buttons_hbox), action_button, TRUE, TRUE, 0);
2759 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
2760 gtk_widget_set_sensitive (GTK_WIDGET (action_button), FALSE);
2761 gtk_box_pack_start (GTK_BOX (top_vbox), buttons_hbox, FALSE, FALSE, 0);
2763 /* Create pannable and add it to the dialog */
2764 folder_view_container = hildon_pannable_area_new ();
2765 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2766 gtk_box_pack_start (GTK_BOX (top_vbox), folder_view_container, TRUE, TRUE, 0);
2768 gtk_container_add (GTK_CONTAINER (align), top_vbox);
2769 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), align, TRUE, TRUE, 0);
2771 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2773 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2774 gtk_widget_show (folder_view_container);
2775 gtk_widget_show (align);
2776 gtk_widget_show (top_vbox);
2777 gtk_widget_show (*folder_view);
2778 gtk_widget_show_all (back_button);
2779 gtk_widget_show (selection_label);
2780 gtk_widget_show (action_button);
2781 gtk_widget_show (buttons_hbox);
2783 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
2784 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
2785 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON, action_button);
2786 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL, selection_label);
2787 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE, folder_view_container);
2789 /* Simulate the behaviour of a HildonPickerDialog by emitting
2790 a response when a folder is selected */
2791 g_signal_connect (*folder_view, "row-activated",
2792 G_CALLBACK (on_move_to_dialog_folder_activated),
2795 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (*folder_view));
2796 g_signal_connect (selection, "changed",
2797 G_CALLBACK (on_move_to_dialog_selection_changed),
2800 g_signal_connect (action_button, "clicked",
2801 G_CALLBACK (on_move_to_dialog_action_clicked),
2804 g_signal_connect (back_button, "clicked",
2805 G_CALLBACK (on_move_to_dialog_back_clicked),
2808 move_to_dialog_show_accounts (dialog);
2814 modest_platform_get_list_to_move (ModestWindow *window)
2816 TnyList *list = NULL;
2818 if (MODEST_IS_HEADER_WINDOW (window)) {
2819 ModestHeaderView *header_view;
2821 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2822 list = modest_header_view_get_selected_headers (header_view);
2823 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2824 ModestFolderView *folder_view;
2825 TnyFolderStore *selected_folder;
2827 list = TNY_LIST (tny_simple_list_new ());
2828 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2829 selected_folder = modest_folder_view_get_selected (folder_view);
2830 if (selected_folder) {
2831 tny_list_prepend (list, G_OBJECT (selected_folder));
2832 g_object_unref (selected_folder);
2835 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2838 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2840 list = TNY_LIST (tny_simple_list_new ());
2841 tny_list_prepend (list, G_OBJECT (header));
2842 g_object_unref (header);
2845 g_return_val_if_reached (NULL);