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 if (modest_tny_folder_is_remote_folder (TNY_FOLDER (store))) {
790 TnyFolderType type = modest_tny_folder_guess_folder_type (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)))
799 icon_name = MODEST_FOLDER_ICON_NORMAL;
800 else if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store)))
801 icon_name = MODEST_FOLDER_ICON_MMC_FOLDER;
805 pixbuf = modest_platform_get_icon (icon_name, MODEST_ICON_SIZE_SMALL);
808 hildon_button_set_image (HILDON_BUTTON (button),
809 gtk_image_new_from_pixbuf (pixbuf));
810 g_object_unref (pixbuf);
815 /* Always returns DUPs so you must free the returned value */
817 get_next_folder_name (const gchar *suggested_name,
818 TnyFolderStore *suggested_folder)
820 const gchar *default_name = _FM("ckdg_va_new_folder_name_stub");
822 gchar *real_suggested_name;
824 if (suggested_name !=NULL) {
825 return g_strdup (suggested_name);
828 for(i = 0; i < 100; ++ i) {
829 gboolean exists = FALSE;
832 real_suggested_name = g_strdup (default_name);
834 real_suggested_name = g_strdup_printf ("%s(%d)",
835 _FM("ckdg_va_new_folder_name_stub"),
837 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
844 g_free (real_suggested_name);
847 /* Didn't find a free number */
849 real_suggested_name = g_strdup (default_name);
851 return real_suggested_name;
855 ModestFolderView *folder_view;
857 } FolderPickerHelper;
860 folder_picker_clicked (GtkButton *button,
861 FolderPickerHelper *helper)
863 TnyFolderStore *store;
865 store = folder_chooser_dialog_run (helper->folder_view);
867 const gchar *current_name;
870 folder_picker_set_store (GTK_BUTTON (button), store);
872 /* Update the name of the folder */
873 current_name = gtk_entry_get_text (helper->entry);
874 exists = modest_tny_folder_has_subfolder_with_name (store,
878 gchar *new_name = get_next_folder_name (NULL, store);
879 gtk_entry_set_text (helper->entry, new_name);
886 folder_picker_new (TnyFolderStore *suggested, FolderPickerHelper *helper)
890 button = hildon_button_new (MODEST_EDITABLE_SIZE,
891 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
893 hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 1.0);
896 folder_picker_set_store (GTK_BUTTON (button), suggested);
899 g_signal_connect (G_OBJECT (button), "clicked",
900 G_CALLBACK (folder_picker_clicked),
908 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
909 TnyFolderStore *suggested_parent,
910 const gchar *dialog_title,
911 const gchar *label_text,
912 const gchar *suggested_name,
914 gboolean show_parent,
916 TnyFolderStore **parent)
918 GtkWidget *accept_btn = NULL;
919 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
920 GtkWidget *account_picker = NULL;
921 GList *buttons = NULL;
923 GtkSizeGroup *sizegroup;
924 ModestFolderView *folder_view;
925 ModestWindow *folder_window;
926 ModestHildon2WindowMgr *window_mgr;
927 FolderPickerHelper *helper = NULL;
929 window_mgr = (ModestHildon2WindowMgr *) modest_runtime_get_window_mgr ();
930 folder_window = modest_hildon2_window_mgr_get_folder_window (window_mgr);
931 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
933 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
935 /* Ask the user for the folder name */
936 dialog = gtk_dialog_new_with_buttons (dialog_title,
938 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
939 _FM("ckdg_bd_new_folder_dialog_ok"),
943 /* Add accept button (with unsensitive handler) */
944 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
945 accept_btn = GTK_WIDGET (buttons->data);
947 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
950 label_entry = gtk_label_new (label_text);
951 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
952 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
954 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
955 gtk_size_group_add_widget (sizegroup, label_entry);
958 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
960 gtk_entry_set_text (GTK_ENTRY (entry), _FM("ckdg_va_new_folder_name_stub"));
961 gtk_entry_set_width_chars (GTK_ENTRY (entry),
962 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
963 g_utf8_strlen (_FM("ckdg_va_new_folder_name_stub"), -1)));
964 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
969 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
971 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
972 gtk_size_group_add_widget (sizegroup, label_location);
974 helper = g_slice_new0 (FolderPickerHelper);
975 helper->folder_view = folder_view;
976 helper->entry = (GtkEntry *) entry;
978 account_picker = folder_picker_new (suggested_parent, helper);
981 g_object_unref (sizegroup);
983 /* Connect to the response method to avoid closing the dialog
984 when an invalid name is selected*/
985 g_signal_connect (dialog,
987 G_CALLBACK (on_response),
991 /* Track entry changes */
992 g_signal_connect (entry,
994 G_CALLBACK (entry_insert_text),
996 g_signal_connect (entry,
998 G_CALLBACK (entry_changed),
1003 /* Some locales like pt_BR need this to get the full window
1005 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
1007 /* Create the hbox */
1009 hbox = gtk_hbox_new (FALSE, 12);
1010 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
1011 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
1013 /* Add hbox to dialog */
1014 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1015 hbox, FALSE, FALSE, 0);
1016 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
1020 hbox = gtk_hbox_new (FALSE, 12);
1021 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
1022 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
1024 /* Add hbox to dialog */
1025 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1026 hbox, FALSE, FALSE, 0);
1027 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
1029 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1030 GTK_WINDOW (dialog), parent_window);
1031 gtk_widget_show_all (GTK_WIDGET(dialog));
1033 result = gtk_dialog_run (GTK_DIALOG(dialog));
1034 if (result == GTK_RESPONSE_ACCEPT) {
1036 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1038 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
1040 g_object_ref (*parent);
1044 gtk_widget_destroy (dialog);
1047 g_slice_free (FolderPickerHelper, helper);
1049 while (gtk_events_pending ())
1050 gtk_main_iteration ();
1056 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
1057 TnyFolderStore *suggested_folder,
1058 gchar *suggested_name,
1059 gchar **folder_name,
1060 TnyFolderStore **parent_folder)
1062 gchar *real_suggested_name = NULL;
1064 ModestTnyAccountStore *acc_store;
1065 TnyAccount *account;
1067 real_suggested_name = get_next_folder_name ((const gchar *) suggested_name,
1070 /* In hildon 2.2 we always suggest the archive folder as parent */
1071 acc_store = modest_runtime_get_account_store ();
1072 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
1074 suggested_folder = (TnyFolderStore *)
1075 modest_tny_account_get_special_folder (account,
1076 TNY_FOLDER_TYPE_ARCHIVE);
1077 g_object_unref (account);
1081 /* If there is not archive folder then fallback to local folders account */
1082 if (!suggested_folder)
1083 suggested_folder = (TnyFolderStore *)
1084 modest_tny_account_store_get_local_folders_account (acc_store);
1086 result = modest_platform_run_folder_common_dialog (parent_window,
1088 _HL("ckdg_ti_new_folder"),
1089 _FM("ckdg_fi_new_folder_name"),
1090 real_suggested_name,
1096 g_free(real_suggested_name);
1102 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1103 TnyFolderStore *parent_folder,
1104 const gchar *suggested_name,
1105 gchar **folder_name)
1107 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1109 return modest_platform_run_folder_common_dialog (parent_window,
1111 _HL("ckdg_ti_rename_folder"),
1112 _HL("ckdg_fi_rename_name"),
1123 on_destroy_dialog (GtkWidget *dialog)
1125 /* This could happen when the dialogs get programatically
1126 hidden or destroyed (for example when closing the
1127 application while a dialog is being shown) */
1128 if (!GTK_IS_WIDGET (dialog))
1131 gtk_widget_destroy (dialog);
1133 if (gtk_events_pending ())
1134 gtk_main_iteration ();
1138 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1139 const gchar *message)
1144 dialog = hildon_note_new_confirmation (parent_window, message);
1145 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1146 GTK_WINDOW (dialog), parent_window);
1148 response = gtk_dialog_run (GTK_DIALOG (dialog));
1150 on_destroy_dialog (dialog);
1156 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1157 const gchar *message,
1158 const gchar *button_accept,
1159 const gchar *button_cancel)
1164 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1165 button_accept, GTK_RESPONSE_ACCEPT,
1166 button_cancel, GTK_RESPONSE_CANCEL,
1169 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1170 GTK_WINDOW (dialog), parent_window);
1172 response = gtk_dialog_run (GTK_DIALOG (dialog));
1174 on_destroy_dialog (dialog);
1180 modest_platform_run_information_dialog (GtkWindow *parent_window,
1181 const gchar *message,
1186 note = hildon_note_new_information (parent_window, message);
1188 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1189 GTK_WINDOW (note), parent_window);
1192 gtk_dialog_run (GTK_DIALOG (note));
1194 on_destroy_dialog (note);
1196 g_signal_connect_swapped (note,
1198 G_CALLBACK (on_destroy_dialog),
1201 gtk_widget_show_all (note);
1205 typedef struct _ConnectAndWaitData {
1207 GMainLoop *wait_loop;
1208 gboolean has_callback;
1210 } ConnectAndWaitData;
1214 quit_wait_loop (TnyAccount *account,
1215 ConnectAndWaitData *data)
1217 /* Set the has_callback to TRUE (means that the callback was
1218 executed and wake up every code waiting for cond to be
1220 g_mutex_lock (data->mutex);
1221 data->has_callback = TRUE;
1222 if (data->wait_loop)
1223 g_main_loop_quit (data->wait_loop);
1224 g_mutex_unlock (data->mutex);
1228 on_connection_status_changed (TnyAccount *account,
1229 TnyConnectionStatus status,
1232 TnyConnectionStatus conn_status;
1233 ConnectAndWaitData *data;
1235 /* Ignore if reconnecting or disconnected */
1236 conn_status = tny_account_get_connection_status (account);
1237 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1238 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1241 /* Remove the handler */
1242 data = (ConnectAndWaitData *) user_data;
1243 g_signal_handler_disconnect (account, data->handler);
1245 /* Quit from wait loop */
1246 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1250 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1255 /* Quit from wait loop */
1256 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1260 modest_platform_connect_and_wait (GtkWindow *parent_window,
1261 TnyAccount *account)
1263 ConnectAndWaitData *data = NULL;
1264 gboolean device_online;
1266 TnyConnectionStatus conn_status;
1267 gboolean user_requested;
1269 device = modest_runtime_get_device();
1270 device_online = tny_device_is_online (device);
1272 /* Whether the connection is user requested or automatically
1273 requested, for example via D-Bus */
1274 user_requested = (parent_window) ? TRUE : FALSE;
1276 /* If there is no account check only the device status */
1281 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1282 NULL, user_requested);
1285 /* Return if the account is already connected */
1286 conn_status = tny_account_get_connection_status (account);
1287 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1290 /* Create the helper */
1291 data = g_slice_new0 (ConnectAndWaitData);
1292 data->mutex = g_mutex_new ();
1293 data->has_callback = FALSE;
1295 /* Connect the device */
1296 if (!device_online) {
1297 /* Track account connection status changes */
1298 data->handler = g_signal_connect (account, "connection-status-changed",
1299 G_CALLBACK (on_connection_status_changed),
1301 /* Try to connect the device */
1302 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1303 NULL, user_requested);
1305 /* If the device connection failed then exit */
1306 if (!device_online && data->handler)
1309 /* Force a reconnection of the account */
1310 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1311 on_tny_camel_account_set_online_cb, data);
1314 /* Wait until the callback is executed */
1315 g_mutex_lock (data->mutex);
1316 if (!data->has_callback) {
1317 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1318 gdk_threads_leave ();
1319 g_mutex_unlock (data->mutex);
1320 g_main_loop_run (data->wait_loop);
1321 g_mutex_lock (data->mutex);
1322 gdk_threads_enter ();
1324 g_mutex_unlock (data->mutex);
1328 if (g_signal_handler_is_connected (account, data->handler))
1329 g_signal_handler_disconnect (account, data->handler);
1330 g_mutex_free (data->mutex);
1331 g_main_loop_unref (data->wait_loop);
1332 g_slice_free (ConnectAndWaitData, data);
1335 conn_status = tny_account_get_connection_status (account);
1336 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1340 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1342 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1343 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1344 /* This must be a maildir account, which does not require a connection: */
1349 return modest_platform_connect_and_wait (parent_window, account);
1353 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1356 return TRUE; /* Maybe it is something local. */
1358 gboolean result = TRUE;
1359 if (TNY_IS_FOLDER (folder_store)) {
1360 /* Get the folder's parent account: */
1361 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1362 if (account != NULL) {
1363 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1364 g_object_unref (account);
1366 } else if (TNY_IS_ACCOUNT (folder_store)) {
1367 /* Use the folder store as an account: */
1368 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1375 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1379 dialog = modest_hildon2_sort_dialog_new (parent_window);
1386 modest_platform_set_update_interval (guint minutes)
1388 #ifdef MODEST_HAVE_LIBALARM
1390 ModestConf *conf = modest_runtime_get_conf ();
1394 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1396 /* Delete any existing alarm,
1397 * because we will replace it: */
1399 if (alarmd_event_del(alarm_cookie) != 0)
1400 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1402 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1405 /* 0 means no updates: */
1410 /* Register alarm: */
1412 /* Set the interval in alarm_event_t structure: */
1413 alarm_event_t *event = alarm_event_create ();
1414 alarm_event_add_actions (event, 1);
1415 alarm_action_t *action = alarm_event_get_action (event, 0);
1416 alarm_event_set_alarm_appid (event, MODEST_ALARMD_APPID);
1417 event->alarm_time = minutes * 60; /* seconds */
1419 /* Set recurrence every few minutes: */
1420 event->recur_secs = minutes*60;
1421 event->recur_count = -1; /* Means infinite */
1423 /* Specify what should happen when the alarm happens:
1424 * It should call this D-Bus method: */
1426 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1427 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1428 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1429 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1430 action->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1432 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1433 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1434 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1435 * This is why we want to use the Alarm API instead of just g_timeout_add().
1436 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1437 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1439 event->flags = ALARM_EVENT_CONNECTED;
1441 alarm_cookie = alarmd_event_add (event);
1444 alarm_event_delete (event);
1446 /* Store the alarm ID in GConf, so we can remove it later:
1447 * This is apparently valid between application instances. */
1448 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1450 if (!alarm_cookie) {
1452 g_debug ("Error setting alarm event. \n");
1456 #endif /* MODEST_HAVE_LIBALARM */
1461 modest_platform_push_email_notification(void)
1463 gboolean screen_on, app_in_foreground;
1465 /* Get the window status */
1466 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1468 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1470 /* If the screen is on and the app is in the
1471 foreground we don't show anything */
1472 if (!(screen_on && app_in_foreground)) {
1474 _modest_platform_play_email_tone ();
1476 /* Activate LED. This must be deactivated by
1477 modest_platform_remove_new_mail_notifications */
1478 #ifdef MODEST_HAVE_MCE
1479 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1483 MCE_ACTIVATE_LED_PATTERN,
1485 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1492 modest_platform_on_new_headers_received (TnyList *header_list,
1493 gboolean show_visual)
1495 g_return_if_fail (TNY_IS_LIST(header_list));
1497 if (tny_list_get_length(header_list) == 0) {
1498 g_warning ("%s: header list is empty", __FUNCTION__);
1503 modest_platform_push_email_notification ();
1504 /* We do a return here to avoid indentation with an else */
1508 #ifdef MODEST_HAVE_HILDON_NOTIFY
1509 HildonNotification *notification;
1511 GSList *notifications_list = NULL;
1513 /* Get previous notifications ids */
1514 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1515 MODEST_CONF_NOTIFICATION_IDS,
1516 MODEST_CONF_VALUE_INT, NULL);
1518 iter = tny_list_create_iterator (header_list);
1519 while (!tny_iterator_is_done (iter)) {
1520 gchar *url = NULL, *display_address = NULL;
1521 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1522 TnyFolder *folder = tny_header_get_folder (header);
1523 gboolean first_notification = TRUE;
1527 display_address = tny_header_dup_from (header);
1528 /* string is changed in-place */
1529 modest_text_utils_get_display_address (display_address);
1531 str = tny_header_dup_subject (header);
1532 notification = hildon_notification_new (display_address,
1534 "qgn_list_messagin",
1535 MODEST_NOTIFICATION_CATEGORY);
1537 /* Create the message URL */
1538 str = tny_header_dup_uid (header);
1539 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1543 hildon_notification_add_dbus_action(notification,
1546 MODEST_DBUS_SERVICE,
1549 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1553 /* Play sound if the user wants. Show the LED
1554 pattern. Show and play just one */
1555 if (G_UNLIKELY (first_notification)) {
1556 TnyAccount *account;
1558 first_notification = FALSE;
1560 /* Set the led pattern */
1561 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1563 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1565 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1567 /* Set the account of the headers */
1568 account = tny_folder_get_account (folder);
1570 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1572 tny_account_get_id (account));
1573 g_object_unref (account);
1577 /* Notify. We need to do this in an idle because this function
1578 could be called from a thread */
1579 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1581 /* Save id in the list */
1582 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1583 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1584 /* We don't listen for the "closed" signal, because we
1585 don't care about if the notification was removed or
1586 not to store the list in gconf */
1588 /* Free & carry on */
1589 g_free (display_address);
1591 g_object_unref (folder);
1592 g_object_unref (header);
1593 tny_iterator_next (iter);
1595 g_object_unref (iter);
1598 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1599 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1601 g_slist_free (notifications_list);
1603 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1607 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1610 #ifdef MODEST_HAVE_MCE
1611 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1615 MCE_DEACTIVATE_LED_PATTERN,
1617 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1623 #ifdef MODEST_HAVE_HILDON_NOTIFY
1624 GSList *notif_list = NULL;
1626 /* Get previous notifications ids */
1627 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1628 MODEST_CONF_NOTIFICATION_IDS,
1629 MODEST_CONF_VALUE_INT, NULL);
1631 while (notif_list) {
1633 NotifyNotification *notif;
1635 /* Nasty HACK to remove the notifications, set the id
1636 of the existing ones and then close them */
1637 notif_id = GPOINTER_TO_INT(notif_list->data);
1638 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1639 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1641 /* Close the notification, note that some ids could be
1642 already invalid, but we don't care because it does
1644 notify_notification_close(notif, NULL);
1645 g_object_unref(notif);
1647 /* Delete the link, it's like going to the next */
1648 notif_list = g_slist_delete_link (notif_list, notif_list);
1652 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1653 notif_list, MODEST_CONF_VALUE_INT, NULL);
1655 g_slist_free (notif_list);
1657 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1663 modest_platform_get_global_settings_dialog ()
1665 return modest_hildon2_global_settings_dialog_new ();
1669 modest_platform_show_help (GtkWindow *parent_window,
1670 const gchar *help_id)
1676 modest_platform_show_search_messages (GtkWindow *parent_window)
1678 osso_return_t result = OSSO_ERROR;
1680 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1681 "osso_global_search",
1682 "search_email", NULL, DBUS_TYPE_INVALID);
1684 if (result != OSSO_OK) {
1685 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1690 modest_platform_show_addressbook (GtkWindow *parent_window)
1692 osso_return_t result = OSSO_ERROR;
1694 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1696 "top_application", NULL, DBUS_TYPE_INVALID);
1698 if (result != OSSO_OK) {
1699 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1704 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1706 GtkWidget *widget = modest_folder_view_new (query);
1708 /* Show one account by default */
1709 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1710 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1712 /* Restore settings */
1713 modest_widget_memory_restore (modest_runtime_get_conf(),
1715 MODEST_CONF_FOLDER_VIEW_KEY);
1721 banner_finish (gpointer data, GObject *object)
1723 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1724 modest_window_mgr_unregister_banner (mgr);
1725 g_object_unref (mgr);
1729 modest_platform_information_banner (GtkWidget *parent,
1730 const gchar *icon_name,
1733 GtkWidget *banner, *banner_parent = NULL;
1734 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1736 if (modest_window_mgr_get_num_windows (mgr) == 0)
1739 if (parent && GTK_IS_WINDOW (parent)) {
1740 /* If the window is the active one then show the
1741 banner on top of this window */
1742 if (gtk_window_is_active (GTK_WINDOW (parent)))
1743 banner_parent = parent;
1744 /* If the window is not the topmost but it's visible
1745 (it's minimized for example) then show the banner
1747 else if (GTK_WIDGET_VISIBLE (parent))
1748 banner_parent = NULL;
1749 /* If the window is hidden (like the main window when
1750 running in the background) then do not show
1757 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1759 modest_window_mgr_register_banner (mgr);
1761 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1765 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1766 const gchar *icon_name,
1772 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1775 banner = hildon_banner_show_information (parent, icon_name, text);
1776 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1780 modest_platform_animation_banner (GtkWidget *parent,
1781 const gchar *animation_name,
1784 GtkWidget *inf_note = NULL;
1786 g_return_val_if_fail (text != NULL, NULL);
1788 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1791 /* If the parent is not visible then do not show */
1792 if (parent && !GTK_WIDGET_VISIBLE (parent))
1795 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1803 TnyAccount *account;
1806 } CheckAccountIdleData;
1808 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1811 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1813 gboolean stop_trying = FALSE;
1814 g_return_val_if_fail (data && data->account, FALSE);
1816 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1817 tny_account_get_connection_status (data->account));
1819 if (data && data->account &&
1820 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1821 * after which the account is likely to be usable, or never likely to be usable soon: */
1822 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1824 data->is_online = TRUE;
1828 /* Give up if we have tried too many times: */
1829 if (data->count_tries >= NUMBER_OF_TRIES) {
1832 /* Wait for another timeout: */
1833 ++(data->count_tries);
1838 /* Allow the function that requested this idle callback to continue: */
1840 g_main_loop_quit (data->loop);
1843 g_object_unref (data->account);
1845 return FALSE; /* Don't call this again. */
1847 return TRUE; /* Call this timeout callback again. */
1851 /* Return TRUE immediately if the account is already online,
1852 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1853 * soon as the account is online, or FALSE if the account does
1854 * not become online in the NUMBER_OF_TRIES seconds.
1855 * This is useful when the D-Bus method was run immediately after
1856 * the application was started (when using D-Bus activation),
1857 * because the account usually takes a short time to go online.
1858 * The return value is maybe not very useful.
1861 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1865 g_return_val_if_fail (account, FALSE);
1867 if (!tny_device_is_online (modest_runtime_get_device())) {
1868 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1872 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1873 * so we avoid wait unnecessarily: */
1874 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1877 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1878 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1879 * we want to avoid. */
1880 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1883 /* This blocks on the result: */
1884 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1885 data->is_online = FALSE;
1886 data->account = account;
1887 g_object_ref (data->account);
1888 data->count_tries = 0;
1890 GMainContext *context = NULL; /* g_main_context_new (); */
1891 data->loop = g_main_loop_new (context, FALSE /* not running */);
1893 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1895 /* This main loop will run until the idle handler has stopped it: */
1896 g_main_loop_run (data->loop);
1898 g_main_loop_unref (data->loop);
1899 /* g_main_context_unref (context); */
1901 is_online = data->is_online;
1902 g_slice_free (CheckAccountIdleData, data);
1910 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1912 /* GTK_RESPONSE_HELP means we need to show the certificate */
1913 if (response_id == GTK_RESPONSE_APPLY) {
1917 /* Do not close the dialog */
1918 g_signal_stop_emission_by_name (dialog, "response");
1920 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1921 note = hildon_note_new_information (NULL, msg);
1922 gtk_dialog_run (GTK_DIALOG(note));
1923 gtk_widget_destroy (note);
1929 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1930 const gchar *certificate)
1935 HildonWindowStack *stack;
1937 stack = hildon_window_stack_get_default ();
1938 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1941 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1946 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1949 /* We use GTK_RESPONSE_APPLY because we want the button in the
1950 middle of OK and CANCEL the same as the browser does for
1951 example. With GTK_RESPONSE_HELP the view button is aligned
1952 to the left while the other two to the right */
1953 note = hildon_note_new_confirmation_add_buttons (
1956 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1957 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1958 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1961 g_signal_connect (G_OBJECT(note), "response",
1962 G_CALLBACK(on_cert_dialog_response),
1963 (gpointer) certificate);
1965 response = gtk_dialog_run(GTK_DIALOG(note));
1967 on_destroy_dialog (note);
1970 return response == GTK_RESPONSE_OK;
1974 modest_platform_run_alert_dialog (const gchar* prompt,
1975 gboolean is_question)
1977 ModestWindow *top_win;
1978 HildonWindowStack *stack;
1980 stack = hildon_window_stack_get_default ();
1981 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1984 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1989 gboolean retval = TRUE;
1991 /* The Tinymail documentation says that we should show Yes and No buttons,
1992 * when it is a question.
1993 * Obviously, we need tinymail to use more specific error codes instead,
1994 * so we know what buttons to show. */
1995 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
1997 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1998 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
2000 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
2001 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
2003 on_destroy_dialog (dialog);
2005 /* Just show the error text and use the default response: */
2006 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
2014 GtkWindow *parent_window;
2015 ModestConnectedPerformer callback;
2016 TnyAccount *account;
2023 on_went_online_info_free (OnWentOnlineInfo *info)
2025 /* And if we cleanup, we DO cleanup :-) */
2028 g_object_unref (info->device);
2031 if (info->parent_window)
2032 g_object_unref (info->parent_window);
2034 g_object_unref (info->account);
2036 g_slice_free (OnWentOnlineInfo, info);
2038 /* We're done ... */
2044 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
2046 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2048 /* Now it's really time to callback to the caller. If going online didn't succeed,
2049 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
2050 * canceled will be set. Etcetera etcetera. */
2052 if (info->callback) {
2053 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2056 /* This is our last call, we must cleanup here if we didn't yet do that */
2057 on_went_online_info_free (info);
2064 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2066 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2067 info->iap = g_strdup (iap_id);
2069 if (canceled || err || !info->account) {
2071 /* If there's a problem or if there's no account (then that's it for us, we callback
2072 * the caller's callback now. He'll have to handle err or canceled, of course.
2073 * We are not really online, as the account is not really online here ... */
2075 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2076 * this info. We don't cleanup err, Tinymail does that! */
2078 if (info->callback) {
2080 /* info->account can be NULL here, this means that the user did not
2081 * provide a nice account instance. We'll assume that the user knows
2082 * what he's doing and is happy with just the device going online.
2084 * We can't do magic, we don't know what account the user wants to
2085 * see going online. So just the device goes online, end of story */
2087 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2090 } else if (info->account) {
2092 /* If there's no problem and if we have an account, we'll put the account
2093 * online too. When done, the callback of bringing the account online
2094 * will callback the caller's callback. This is the most normal case. */
2096 info->device = TNY_DEVICE (g_object_ref (device));
2098 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2099 on_account_went_online, info);
2101 /* The on_account_went_online cb frees up the info, go look if you
2102 * don't believe me! (so we return here) */
2107 /* We cleanup if we are not bringing the account online too */
2108 on_went_online_info_free (info);
2114 modest_platform_connect_and_perform (GtkWindow *parent_window,
2116 TnyAccount *account,
2117 ModestConnectedPerformer callback,
2120 gboolean device_online;
2122 TnyConnectionStatus conn_status;
2123 OnWentOnlineInfo *info;
2125 device = modest_runtime_get_device();
2126 device_online = tny_device_is_online (device);
2128 /* If there is no account check only the device status */
2131 if (device_online) {
2133 /* We promise to instantly perform the callback, so ... */
2135 callback (FALSE, NULL, parent_window, account, user_data);
2140 info = g_slice_new0 (OnWentOnlineInfo);
2143 info->device = NULL;
2144 info->account = NULL;
2147 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2149 info->parent_window = NULL;
2150 info->user_data = user_data;
2151 info->callback = callback;
2153 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2154 force, on_conic_device_went_online,
2157 /* We'll cleanup in on_conic_device_went_online */
2160 /* The other code has no more reason to run. This is all that we can do for the
2161 * caller (he should have given us a nice and clean account instance!). We
2162 * can't do magic, we don't know what account he intends to bring online. So
2163 * we'll just bring the device online (and await his false bug report). */
2169 /* Return if the account is already connected */
2171 conn_status = tny_account_get_connection_status (account);
2172 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2174 /* We promise to instantly perform the callback, so ... */
2176 callback (FALSE, NULL, parent_window, account, user_data);
2182 /* Else, we are in a state that requires that we go online before we
2183 * call the caller's callback. */
2185 info = g_slice_new0 (OnWentOnlineInfo);
2187 info->device = NULL;
2189 info->account = TNY_ACCOUNT (g_object_ref (account));
2192 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2194 info->parent_window = NULL;
2196 /* So we'll put the callback away for later ... */
2198 info->user_data = user_data;
2199 info->callback = callback;
2201 if (!device_online) {
2203 /* If also the device is offline, then we connect both the device
2204 * and the account */
2206 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2207 force, on_conic_device_went_online,
2212 /* If the device is online, we'll just connect the account */
2214 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2215 on_account_went_online, info);
2218 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2219 * in both situations, go look if you don't believe me! */
2225 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2227 TnyFolderStore *folder_store,
2228 ModestConnectedPerformer callback,
2231 TnyAccount *account = NULL;
2233 if (!folder_store ||
2234 (TNY_IS_MERGE_FOLDER (folder_store) &&
2235 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2237 /* We promise to instantly perform the callback, so ... */
2239 GError *error = NULL;
2240 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2241 "Unable to move or not found folder");
2242 callback (FALSE, error, parent_window, NULL, user_data);
2243 g_error_free (error);
2247 } else if (TNY_IS_FOLDER (folder_store)) {
2248 /* Get the folder's parent account: */
2249 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2250 } else if (TNY_IS_ACCOUNT (folder_store)) {
2251 /* Use the folder store as an account: */
2252 account = TNY_ACCOUNT (g_object_ref (folder_store));
2255 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
2256 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2257 /* No need to connect a local account */
2259 callback (FALSE, NULL, parent_window, account, user_data);
2264 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2268 g_object_unref (account);
2272 src_account_connect_performer (gboolean canceled,
2274 GtkWindow *parent_window,
2275 TnyAccount *src_account,
2278 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2280 if (canceled || err) {
2281 /* If there was any error call the user callback */
2282 info->callback (canceled, err, parent_window, src_account, info->data);
2284 /* Connect the destination account */
2285 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2286 TNY_FOLDER_STORE (info->dst_account),
2287 info->callback, info->data);
2290 /* Free the info object */
2291 g_object_unref (info->dst_account);
2292 g_slice_free (DoubleConnectionInfo, info);
2297 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2299 TnyFolderStore *folder_store,
2300 DoubleConnectionInfo *connect_info)
2302 modest_platform_connect_if_remote_and_perform(parent_window,
2305 src_account_connect_performer,
2310 modest_platform_get_account_settings_wizard (void)
2312 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2314 return GTK_WIDGET (dialog);
2318 modest_platform_get_current_connection (void)
2320 TnyDevice *device = NULL;
2321 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2323 device = modest_runtime_get_device ();
2325 if (!tny_device_is_online (device))
2326 return MODEST_CONNECTED_VIA_ANY;
2328 #ifdef MODEST_HAVE_CONIC
2330 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2332 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2333 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2334 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2336 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2337 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2338 !strcmp (bearer_type, "WIMAX")) {
2339 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2341 retval = MODEST_CONNECTED_VIA_ANY;
2344 g_object_unref (iap);
2347 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2348 #endif /* MODEST_HAVE_CONIC */
2355 modest_platform_check_memory_low (ModestWindow *win,
2360 /* are we in low memory state? */
2361 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2363 if (win && lowmem && visuals)
2364 modest_platform_run_information_dialog (
2366 _KR("memr_ib_operation_disabled"),
2370 g_debug ("%s: low memory reached. disallowing some operations",
2377 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2383 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2386 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2387 GTK_WINDOW (dialog),
2389 gtk_widget_show_all (dialog);
2391 g_signal_connect_swapped (dialog, "response",
2392 G_CALLBACK (gtk_widget_destroy),
2397 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2403 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
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_get_osso_context (void)
2419 return modest_maemo_utils_get_osso_context ();
2423 _modest_platform_play_email_tone (void)
2425 gchar *active_profile;
2428 gint mail_volume_int;
2430 ca_context *ca_con = NULL;
2431 ca_proplist *pl = NULL;
2433 active_profile = profile_get_profile ();
2434 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2435 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2436 mail_volume_int = profile_parse_int (mail_volume);
2438 if (mail_tone && !strstr (mail_tone, "/")) {
2441 tmp = g_strconcat ("/usr/share/sounds", mail_tone, NULL);
2446 if (mail_volume_int > 0) {
2448 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2449 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2453 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2454 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2455 ca_context_destroy(ca_con);
2459 ca_proplist_create(&pl);
2460 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2461 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2463 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2464 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2466 ca_proplist_destroy(pl);
2467 ca_context_destroy(ca_con);
2470 g_free (mail_volume);
2472 g_free (active_profile);
2475 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
2476 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
2477 #define MOVE_TO_DIALOG_SELECTION_LABEL "selection-label"
2478 #define MOVE_TO_DIALOG_SHOWING_FOLDERS "showing-folders"
2479 #define MOVE_TO_DIALOG_PANNABLE "pannable"
2482 move_to_dialog_show_accounts (GtkWidget *dialog)
2484 GtkWidget *selection_label;
2485 GtkWidget *back_button;
2486 GtkWidget *folder_view;
2487 GtkWidget *pannable;
2489 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2490 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2491 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2492 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2494 gtk_widget_set_sensitive (back_button, FALSE);
2496 gtk_label_set_text (GTK_LABEL (selection_label), "");
2497 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2498 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
2499 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2500 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2501 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2503 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (FALSE));
2507 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
2509 GtkWidget *selection_label;
2510 GtkWidget *back_button;
2511 GtkWidget *folder_view;
2512 TnyAccount *account;
2513 const gchar *account_id;
2514 gchar *selection_label_text;
2515 GtkWidget *pannable;
2517 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2518 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2519 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2520 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2522 gtk_widget_set_sensitive (back_button, TRUE);
2524 account = TNY_ACCOUNT (folder_store);
2525 if (modest_tny_account_is_virtual_local_folders (account)) {
2527 account_id = tny_account_get_id (account);
2528 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2529 MODEST_CONF_DEVICE_NAME, NULL);
2531 selection_label_text = g_strconcat (device_name, "/", NULL);
2532 g_free (device_name);
2534 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2536 } else if (modest_tny_account_is_memory_card_account (account)) {
2537 account_id = tny_account_get_id (account);
2538 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2540 account_id = tny_account_get_id (account);
2542 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2543 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2544 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2546 gtk_label_set_text (GTK_LABEL (selection_label), selection_label_text);
2547 g_free (selection_label_text);
2549 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
2552 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
2553 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
2554 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2555 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2557 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (TRUE));
2561 on_move_to_dialog_back_clicked (GtkButton *button,
2564 GtkWidget *dialog = (GtkWidget *) userdata;
2566 move_to_dialog_show_accounts (dialog);
2570 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2572 GtkTreeViewColumn *column,
2575 TnyFolderStore *selected;
2577 GtkWidget *folder_view;
2578 gboolean showing_folders;
2580 dialog = (GtkWidget *) user_data;
2581 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2582 if (showing_folders) {
2583 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_OK);
2585 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2587 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2589 move_to_dialog_show_folders (dialog, selected);
2595 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2596 GtkWidget **folder_view)
2598 GtkWidget *dialog, *folder_view_container;
2599 GtkWidget *buttons_hbox;
2600 GtkWidget *back_button, *selection_label;
2601 GdkPixbuf *back_pixbuf;
2603 /* Create dialog. We cannot use a touch selector because we
2604 need to use here the folder view widget directly */
2605 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2606 GTK_WINDOW (parent_window),
2607 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2608 GTK_DIALOG_DESTROY_WITH_PARENT,
2609 _HL("wdgt_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2612 /* Create folder view */
2613 *folder_view = modest_platform_create_folder_view (NULL);
2615 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2616 (TnyAccountStore *) modest_runtime_get_account_store ());
2618 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
2619 back_button = gtk_button_new ();
2620 back_pixbuf = modest_platform_get_icon (_FM("filemanager_folder_up"), MODEST_ICON_SIZE_BIG);
2622 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
2623 g_object_unref (back_pixbuf);
2625 selection_label = gtk_label_new ("");
2626 gtk_misc_set_alignment (GTK_MISC (selection_label), 0.0, 0.5);
2627 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
2628 gtk_box_pack_start (GTK_BOX (buttons_hbox), selection_label, TRUE, TRUE, 0);
2629 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
2630 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), buttons_hbox, FALSE, FALSE, 0);
2632 /* Create pannable and add it to the dialog */
2633 folder_view_container = hildon_pannable_area_new ();
2634 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), folder_view_container, TRUE, TRUE, 0);
2635 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2637 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2639 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2640 gtk_widget_show (folder_view_container);
2641 gtk_widget_show (*folder_view);
2642 gtk_widget_show_all (back_button);
2643 gtk_widget_show (selection_label);
2644 gtk_widget_show (buttons_hbox);
2646 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
2647 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
2648 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL, selection_label);
2649 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE, folder_view_container);
2651 /* Simulate the behaviour of a HildonPickerDialog by emitting
2652 a response when a folder is selected */
2653 g_signal_connect (*folder_view, "row-activated",
2654 G_CALLBACK (on_move_to_dialog_folder_activated),
2657 g_signal_connect (back_button, "clicked",
2658 G_CALLBACK (on_move_to_dialog_back_clicked),
2661 move_to_dialog_show_accounts (dialog);
2667 modest_platform_get_list_to_move (ModestWindow *window)
2669 TnyList *list = NULL;
2671 if (MODEST_IS_HEADER_WINDOW (window)) {
2672 ModestHeaderView *header_view;
2674 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2675 list = modest_header_view_get_selected_headers (header_view);
2676 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2677 ModestFolderView *folder_view;
2678 TnyFolderStore *selected_folder;
2680 list = TNY_LIST (tny_simple_list_new ());
2681 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2682 selected_folder = modest_folder_view_get_selected (folder_view);
2683 if (selected_folder) {
2684 tny_list_prepend (list, G_OBJECT (selected_folder));
2685 g_object_unref (selected_folder);
2688 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2691 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2693 list = TNY_LIST (tny_simple_list_new ());
2694 tny_list_prepend (list, G_OBJECT (header));
2695 g_object_unref (header);
2698 g_return_val_if_reached (NULL);