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 ();
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 return g_strdup (tny_account_get_name (TNY_ACCOUNT (store)));
730 TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
732 fname = g_strdup (tny_folder_get_name (TNY_FOLDER (store)));
733 type = tny_folder_get_folder_type (TNY_FOLDER (store));
734 if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)) ||
735 modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
736 type = modest_tny_folder_get_local_or_mmc_folder_type (TNY_FOLDER (store));
737 if (type != TNY_FOLDER_TYPE_UNKNOWN) {
739 fname = g_strdup (modest_local_folder_info_get_type_display_name (type));
742 /* Sometimes an special folder is reported by the server as
743 NORMAL, like some versions of Dovecot */
744 if (type == TNY_FOLDER_TYPE_NORMAL ||
745 type == TNY_FOLDER_TYPE_UNKNOWN) {
746 type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
750 if (type == TNY_FOLDER_TYPE_INBOX) {
752 fname = g_strdup (_("mcen_me_folder_inbox"));
759 folder_picker_set_store (GtkButton *button, TnyFolderStore *store)
764 g_object_set_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER, NULL);
767 const gchar *icon_name = NULL;
769 g_object_ref (store);
770 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
771 store, (GDestroyNotify) g_object_unref);
772 name = folder_store_get_display_name (store);
773 hildon_button_set_value (HILDON_BUTTON (button), name);
777 if (TNY_IS_ACCOUNT (store)) {
778 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
779 icon_name = MODEST_FOLDER_ICON_LOCAL_FOLDERS;
780 else if (modest_tny_account_is_memory_card_account (TNY_ACCOUNT (store)))
781 icon_name = MODEST_FOLDER_ICON_MMC;
783 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
785 if (modest_tny_folder_is_remote_folder (TNY_FOLDER (store))) {
786 TnyFolderType type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
788 case TNY_FOLDER_TYPE_INBOX:
789 icon_name = MODEST_FOLDER_ICON_INBOX;
792 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
794 } else if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)))
795 icon_name = MODEST_FOLDER_ICON_NORMAL;
796 else if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store)))
797 icon_name = MODEST_FOLDER_ICON_MMC_FOLDER;
801 pixbuf = modest_platform_get_icon (icon_name, MODEST_ICON_SIZE_SMALL);
804 hildon_button_set_image (HILDON_BUTTON (button),
805 gtk_image_new_from_pixbuf (pixbuf));
806 g_object_unref (pixbuf);
812 folder_picker_clicked (GtkButton *button,
813 ModestFolderView *folder_view)
815 TnyFolderStore *store;
817 store = folder_chooser_dialog_run (folder_view);
819 folder_picker_set_store (GTK_BUTTON (button), store);
824 folder_picker_new (ModestFolderView *folder_view, TnyFolderStore *suggested)
828 button = hildon_button_new (MODEST_EDITABLE_SIZE,
829 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
831 hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 1.0);
834 folder_picker_set_store (GTK_BUTTON (button), suggested);
837 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (folder_picker_clicked), folder_view);
844 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
845 TnyFolderStore *suggested_parent,
846 const gchar *dialog_title,
847 const gchar *label_text,
848 const gchar *suggested_name,
850 gboolean show_parent,
852 TnyFolderStore **parent)
854 GtkWidget *accept_btn = NULL;
855 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
856 GtkWidget *account_picker = NULL;
857 GList *buttons = NULL;
859 GtkSizeGroup *sizegroup;
860 ModestFolderView *folder_view;
861 ModestWindow *folder_window;
862 ModestHildon2WindowMgr *window_mgr;
864 window_mgr = (ModestHildon2WindowMgr *) modest_runtime_get_window_mgr ();
865 folder_window = modest_hildon2_window_mgr_get_folder_window (window_mgr);
866 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
868 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
870 /* Ask the user for the folder name */
871 dialog = gtk_dialog_new_with_buttons (dialog_title,
873 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
874 _FM("ckdg_bd_new_folder_dialog_ok"),
878 /* Add accept button (with unsensitive handler) */
879 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
880 accept_btn = GTK_WIDGET (buttons->data);
882 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
885 label_entry = gtk_label_new (label_text);
886 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
887 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
889 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
890 gtk_size_group_add_widget (sizegroup, label_entry);
893 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
895 gtk_entry_set_text (GTK_ENTRY (entry), _FM("ckdg_va_new_folder_name_stub"));
896 gtk_entry_set_width_chars (GTK_ENTRY (entry),
897 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
898 g_utf8_strlen (_FM("ckdg_va_new_folder_name_stub"), -1)));
899 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
904 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
906 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
907 gtk_size_group_add_widget (sizegroup, label_location);
909 account_picker = folder_picker_new (folder_view, suggested_parent);
912 g_object_unref (sizegroup);
914 /* Connect to the response method to avoid closing the dialog
915 when an invalid name is selected*/
916 g_signal_connect (dialog,
918 G_CALLBACK (on_response),
922 /* Track entry changes */
923 g_signal_connect (entry,
925 G_CALLBACK (entry_insert_text),
927 g_signal_connect (entry,
929 G_CALLBACK (entry_changed),
934 /* Some locales like pt_BR need this to get the full window
936 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
938 /* Create the hbox */
940 hbox = gtk_hbox_new (FALSE, 12);
941 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
942 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
944 /* Add hbox to dialog */
945 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
946 hbox, FALSE, FALSE, 0);
947 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
951 hbox = gtk_hbox_new (FALSE, 12);
952 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
953 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
955 /* Add hbox to dialog */
956 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
957 hbox, FALSE, FALSE, 0);
958 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
960 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
961 GTK_WINDOW (dialog), parent_window);
962 gtk_widget_show_all (GTK_WIDGET(dialog));
964 result = gtk_dialog_run (GTK_DIALOG(dialog));
965 if (result == GTK_RESPONSE_ACCEPT) {
967 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
969 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
971 g_object_ref (*parent);
975 gtk_widget_destroy (dialog);
977 while (gtk_events_pending ())
978 gtk_main_iteration ();
984 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
985 TnyFolderStore *suggested_folder,
986 gchar *suggested_name,
988 TnyFolderStore **parent_folder)
990 gchar *real_suggested_name = NULL;
992 ModestTnyAccountStore *acc_store;
995 if(suggested_name == NULL)
997 const gchar *default_name = _FM("ckdg_va_new_folder_name_stub");
1000 for(i = 0; i < 100; ++ i) {
1001 gboolean exists = FALSE;
1004 real_suggested_name = g_strdup (default_name);
1006 real_suggested_name = g_strdup_printf ("%s(%d)",
1007 _FM("ckdg_va_new_folder_name_stub"),
1009 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
1010 real_suggested_name,
1016 g_free (real_suggested_name);
1019 /* Didn't find a free number */
1021 real_suggested_name = g_strdup (default_name);
1023 real_suggested_name = suggested_name;
1026 /* In hildon 2.2 we always suggest the archive folder as parent */
1027 acc_store = modest_runtime_get_account_store ();
1028 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
1030 suggested_folder = (TnyFolderStore *)
1031 modest_tny_account_get_special_folder (account,
1032 TNY_FOLDER_TYPE_ARCHIVE);
1033 g_object_unref (account);
1037 /* If there is not archive folder then fallback to local folders account */
1038 if (!suggested_folder)
1039 suggested_folder = (TnyFolderStore *)
1040 modest_tny_account_store_get_local_folders_account (acc_store);
1042 result = modest_platform_run_folder_common_dialog (parent_window,
1044 _HL("ckdg_ti_new_folder"),
1045 _FM("ckdg_fi_new_folder_name"),
1046 real_suggested_name,
1052 if (suggested_name == NULL)
1053 g_free(real_suggested_name);
1059 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1060 TnyFolderStore *parent_folder,
1061 const gchar *suggested_name,
1062 gchar **folder_name)
1064 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1066 return modest_platform_run_folder_common_dialog (parent_window,
1068 _HL("ckdg_ti_rename_folder"),
1069 _HL("ckdg_fi_rename_name"),
1080 on_destroy_dialog (GtkWidget *dialog)
1082 /* This could happen when the dialogs get programatically
1083 hidden or destroyed (for example when closing the
1084 application while a dialog is being shown) */
1085 if (!GTK_IS_WIDGET (dialog))
1088 gtk_widget_destroy (dialog);
1090 if (gtk_events_pending ())
1091 gtk_main_iteration ();
1095 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1096 const gchar *message)
1101 dialog = hildon_note_new_confirmation (parent_window, message);
1102 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1103 GTK_WINDOW (dialog), parent_window);
1105 response = gtk_dialog_run (GTK_DIALOG (dialog));
1107 on_destroy_dialog (dialog);
1113 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1114 const gchar *message,
1115 const gchar *button_accept,
1116 const gchar *button_cancel)
1121 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1122 button_accept, GTK_RESPONSE_ACCEPT,
1123 button_cancel, GTK_RESPONSE_CANCEL,
1126 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1127 GTK_WINDOW (dialog), parent_window);
1129 response = gtk_dialog_run (GTK_DIALOG (dialog));
1131 on_destroy_dialog (dialog);
1137 modest_platform_run_information_dialog (GtkWindow *parent_window,
1138 const gchar *message,
1143 note = hildon_note_new_information (parent_window, message);
1145 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1146 GTK_WINDOW (note), parent_window);
1149 gtk_dialog_run (GTK_DIALOG (note));
1151 on_destroy_dialog (note);
1153 g_signal_connect_swapped (note,
1155 G_CALLBACK (on_destroy_dialog),
1158 gtk_widget_show_all (note);
1162 typedef struct _ConnectAndWaitData {
1164 GMainLoop *wait_loop;
1165 gboolean has_callback;
1167 } ConnectAndWaitData;
1171 quit_wait_loop (TnyAccount *account,
1172 ConnectAndWaitData *data)
1174 /* Set the has_callback to TRUE (means that the callback was
1175 executed and wake up every code waiting for cond to be
1177 g_mutex_lock (data->mutex);
1178 data->has_callback = TRUE;
1179 if (data->wait_loop)
1180 g_main_loop_quit (data->wait_loop);
1181 g_mutex_unlock (data->mutex);
1185 on_connection_status_changed (TnyAccount *account,
1186 TnyConnectionStatus status,
1189 TnyConnectionStatus conn_status;
1190 ConnectAndWaitData *data;
1192 /* Ignore if reconnecting or disconnected */
1193 conn_status = tny_account_get_connection_status (account);
1194 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1195 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1198 /* Remove the handler */
1199 data = (ConnectAndWaitData *) user_data;
1200 g_signal_handler_disconnect (account, data->handler);
1202 /* Quit from wait loop */
1203 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1207 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1212 /* Quit from wait loop */
1213 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1217 modest_platform_connect_and_wait (GtkWindow *parent_window,
1218 TnyAccount *account)
1220 ConnectAndWaitData *data = NULL;
1221 gboolean device_online;
1223 TnyConnectionStatus conn_status;
1224 gboolean user_requested;
1226 device = modest_runtime_get_device();
1227 device_online = tny_device_is_online (device);
1229 /* Whether the connection is user requested or automatically
1230 requested, for example via D-Bus */
1231 user_requested = (parent_window) ? TRUE : FALSE;
1233 /* If there is no account check only the device status */
1238 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1239 NULL, user_requested);
1242 /* Return if the account is already connected */
1243 conn_status = tny_account_get_connection_status (account);
1244 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1247 /* Create the helper */
1248 data = g_slice_new0 (ConnectAndWaitData);
1249 data->mutex = g_mutex_new ();
1250 data->has_callback = FALSE;
1252 /* Connect the device */
1253 if (!device_online) {
1254 /* Track account connection status changes */
1255 data->handler = g_signal_connect (account, "connection-status-changed",
1256 G_CALLBACK (on_connection_status_changed),
1258 /* Try to connect the device */
1259 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1260 NULL, user_requested);
1262 /* If the device connection failed then exit */
1263 if (!device_online && data->handler)
1266 /* Force a reconnection of the account */
1267 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1268 on_tny_camel_account_set_online_cb, data);
1271 /* Wait until the callback is executed */
1272 g_mutex_lock (data->mutex);
1273 if (!data->has_callback) {
1274 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1275 gdk_threads_leave ();
1276 g_mutex_unlock (data->mutex);
1277 g_main_loop_run (data->wait_loop);
1278 g_mutex_lock (data->mutex);
1279 gdk_threads_enter ();
1281 g_mutex_unlock (data->mutex);
1285 if (g_signal_handler_is_connected (account, data->handler))
1286 g_signal_handler_disconnect (account, data->handler);
1287 g_mutex_free (data->mutex);
1288 g_main_loop_unref (data->wait_loop);
1289 g_slice_free (ConnectAndWaitData, data);
1292 conn_status = tny_account_get_connection_status (account);
1293 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1297 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1299 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1300 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1301 /* This must be a maildir account, which does not require a connection: */
1306 return modest_platform_connect_and_wait (parent_window, account);
1310 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1313 return TRUE; /* Maybe it is something local. */
1315 gboolean result = TRUE;
1316 if (TNY_IS_FOLDER (folder_store)) {
1317 /* Get the folder's parent account: */
1318 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1319 if (account != NULL) {
1320 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1321 g_object_unref (account);
1323 } else if (TNY_IS_ACCOUNT (folder_store)) {
1324 /* Use the folder store as an account: */
1325 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1332 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1336 dialog = modest_hildon2_sort_dialog_new (parent_window);
1343 modest_platform_set_update_interval (guint minutes)
1345 #ifdef MODEST_HAVE_LIBALARM
1347 ModestConf *conf = modest_runtime_get_conf ();
1351 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1353 /* Delete any existing alarm,
1354 * because we will replace it: */
1356 if (alarmd_event_del(alarm_cookie) != 0)
1357 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1359 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1362 /* 0 means no updates: */
1367 /* Register alarm: */
1369 /* Set the interval in alarm_event_t structure: */
1370 alarm_event_t *event = alarm_event_create ();
1371 alarm_event_add_actions (event, 1);
1372 alarm_action_t *action = alarm_event_get_action (event, 0);
1373 alarm_event_set_alarm_appid (event, MODEST_ALARMD_APPID);
1374 event->alarm_time = minutes * 60; /* seconds */
1376 /* Set recurrence every few minutes: */
1377 event->recur_secs = minutes*60;
1378 event->recur_count = -1; /* Means infinite */
1380 /* Specify what should happen when the alarm happens:
1381 * It should call this D-Bus method: */
1383 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1384 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1385 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1386 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1387 action->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1389 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1390 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1391 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1392 * This is why we want to use the Alarm API instead of just g_timeout_add().
1393 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1394 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1396 event->flags = ALARM_EVENT_CONNECTED;
1398 alarm_cookie = alarmd_event_add (event);
1401 alarm_event_delete (event);
1403 /* Store the alarm ID in GConf, so we can remove it later:
1404 * This is apparently valid between application instances. */
1405 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1407 if (!alarm_cookie) {
1409 g_debug ("Error setting alarm event. \n");
1413 #endif /* MODEST_HAVE_LIBALARM */
1418 modest_platform_push_email_notification(void)
1420 gboolean screen_on, app_in_foreground;
1422 /* Get the window status */
1423 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1425 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1427 /* If the screen is on and the app is in the
1428 foreground we don't show anything */
1429 if (!(screen_on && app_in_foreground)) {
1431 _modest_platform_play_email_tone ();
1433 /* Activate LED. This must be deactivated by
1434 modest_platform_remove_new_mail_notifications */
1435 #ifdef MODEST_HAVE_MCE
1436 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1440 MCE_ACTIVATE_LED_PATTERN,
1442 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1449 modest_platform_on_new_headers_received (TnyList *header_list,
1450 gboolean show_visual)
1452 g_return_if_fail (TNY_IS_LIST(header_list));
1454 if (tny_list_get_length(header_list) == 0) {
1455 g_warning ("%s: header list is empty", __FUNCTION__);
1460 modest_platform_push_email_notification ();
1461 /* We do a return here to avoid indentation with an else */
1465 #ifdef MODEST_HAVE_HILDON_NOTIFY
1466 HildonNotification *notification;
1468 GSList *notifications_list = NULL;
1470 /* Get previous notifications ids */
1471 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1472 MODEST_CONF_NOTIFICATION_IDS,
1473 MODEST_CONF_VALUE_INT, NULL);
1475 iter = tny_list_create_iterator (header_list);
1476 while (!tny_iterator_is_done (iter)) {
1477 gchar *url = NULL, *display_address = NULL;
1478 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1479 TnyFolder *folder = tny_header_get_folder (header);
1480 gboolean first_notification = TRUE;
1484 display_address = tny_header_dup_from (header);
1485 /* string is changed in-place */
1486 modest_text_utils_get_display_address (display_address);
1488 str = tny_header_dup_subject (header);
1489 notification = hildon_notification_new (display_address,
1491 "qgn_list_messagin",
1492 MODEST_NOTIFICATION_CATEGORY);
1494 /* Create the message URL */
1495 str = tny_header_dup_uid (header);
1496 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1500 hildon_notification_add_dbus_action(notification,
1503 MODEST_DBUS_SERVICE,
1506 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1510 /* Play sound if the user wants. Show the LED
1511 pattern. Show and play just one */
1512 if (G_UNLIKELY (first_notification)) {
1514 first_notification = FALSE;
1516 /* Set the led pattern */
1517 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1519 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1521 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1524 /* Notify. We need to do this in an idle because this function
1525 could be called from a thread */
1526 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1528 /* Save id in the list */
1529 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1530 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1531 /* We don't listen for the "closed" signal, because we
1532 don't care about if the notification was removed or
1533 not to store the list in gconf */
1535 /* Free & carry on */
1536 g_free (display_address);
1538 g_object_unref (folder);
1539 g_object_unref (header);
1540 tny_iterator_next (iter);
1542 g_object_unref (iter);
1545 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1546 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1548 g_slist_free (notifications_list);
1550 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1554 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1557 #ifdef MODEST_HAVE_MCE
1558 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1562 MCE_DEACTIVATE_LED_PATTERN,
1564 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1570 #ifdef MODEST_HAVE_HILDON_NOTIFY
1571 GSList *notif_list = NULL;
1573 /* Get previous notifications ids */
1574 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1575 MODEST_CONF_NOTIFICATION_IDS,
1576 MODEST_CONF_VALUE_INT, NULL);
1578 while (notif_list) {
1580 NotifyNotification *notif;
1582 /* Nasty HACK to remove the notifications, set the id
1583 of the existing ones and then close them */
1584 notif_id = GPOINTER_TO_INT(notif_list->data);
1585 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1586 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1588 /* Close the notification, note that some ids could be
1589 already invalid, but we don't care because it does
1591 notify_notification_close(notif, NULL);
1592 g_object_unref(notif);
1594 /* Delete the link, it's like going to the next */
1595 notif_list = g_slist_delete_link (notif_list, notif_list);
1599 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1600 notif_list, MODEST_CONF_VALUE_INT, NULL);
1602 g_slist_free (notif_list);
1604 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1610 modest_platform_get_global_settings_dialog ()
1612 return modest_hildon2_global_settings_dialog_new ();
1616 modest_platform_show_help (GtkWindow *parent_window,
1617 const gchar *help_id)
1623 modest_platform_show_search_messages (GtkWindow *parent_window)
1625 osso_return_t result = OSSO_ERROR;
1627 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1628 "osso_global_search",
1629 "search_email", NULL, DBUS_TYPE_INVALID);
1631 if (result != OSSO_OK) {
1632 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1637 modest_platform_show_addressbook (GtkWindow *parent_window)
1639 osso_return_t result = OSSO_ERROR;
1641 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1643 "top_application", NULL, DBUS_TYPE_INVALID);
1645 if (result != OSSO_OK) {
1646 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1651 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1653 GtkWidget *widget = modest_folder_view_new (query);
1655 /* Show one account by default */
1656 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1657 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1659 /* Restore settings */
1660 modest_widget_memory_restore (modest_runtime_get_conf(),
1662 MODEST_CONF_FOLDER_VIEW_KEY);
1668 banner_finish (gpointer data, GObject *object)
1670 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1671 modest_window_mgr_unregister_banner (mgr);
1672 g_object_unref (mgr);
1676 modest_platform_information_banner (GtkWidget *parent,
1677 const gchar *icon_name,
1680 GtkWidget *banner, *banner_parent = NULL;
1681 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1683 if (modest_window_mgr_get_num_windows (mgr) == 0)
1686 if (parent && GTK_IS_WINDOW (parent)) {
1687 /* If the window is the active one then show the
1688 banner on top of this window */
1689 if (gtk_window_is_active (GTK_WINDOW (parent)))
1690 banner_parent = parent;
1691 /* If the window is not the topmost but it's visible
1692 (it's minimized for example) then show the banner
1694 else if (GTK_WIDGET_VISIBLE (parent))
1695 banner_parent = NULL;
1696 /* If the window is hidden (like the main window when
1697 running in the background) then do not show
1704 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1706 modest_window_mgr_register_banner (mgr);
1708 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1712 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1713 const gchar *icon_name,
1719 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1722 banner = hildon_banner_show_information (parent, icon_name, text);
1723 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1727 modest_platform_animation_banner (GtkWidget *parent,
1728 const gchar *animation_name,
1731 GtkWidget *inf_note = NULL;
1733 g_return_val_if_fail (text != NULL, NULL);
1735 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1738 /* If the parent is not visible then do not show */
1739 if (parent && !GTK_WIDGET_VISIBLE (parent))
1742 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1750 TnyAccount *account;
1753 } CheckAccountIdleData;
1755 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1758 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1760 gboolean stop_trying = FALSE;
1761 g_return_val_if_fail (data && data->account, FALSE);
1763 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1764 tny_account_get_connection_status (data->account));
1766 if (data && data->account &&
1767 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1768 * after which the account is likely to be usable, or never likely to be usable soon: */
1769 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1771 data->is_online = TRUE;
1775 /* Give up if we have tried too many times: */
1776 if (data->count_tries >= NUMBER_OF_TRIES) {
1779 /* Wait for another timeout: */
1780 ++(data->count_tries);
1785 /* Allow the function that requested this idle callback to continue: */
1787 g_main_loop_quit (data->loop);
1790 g_object_unref (data->account);
1792 return FALSE; /* Don't call this again. */
1794 return TRUE; /* Call this timeout callback again. */
1798 /* Return TRUE immediately if the account is already online,
1799 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1800 * soon as the account is online, or FALSE if the account does
1801 * not become online in the NUMBER_OF_TRIES seconds.
1802 * This is useful when the D-Bus method was run immediately after
1803 * the application was started (when using D-Bus activation),
1804 * because the account usually takes a short time to go online.
1805 * The return value is maybe not very useful.
1808 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1812 g_return_val_if_fail (account, FALSE);
1814 if (!tny_device_is_online (modest_runtime_get_device())) {
1815 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1819 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1820 * so we avoid wait unnecessarily: */
1821 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1824 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1825 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1826 * we want to avoid. */
1827 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1830 /* This blocks on the result: */
1831 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1832 data->is_online = FALSE;
1833 data->account = account;
1834 g_object_ref (data->account);
1835 data->count_tries = 0;
1837 GMainContext *context = NULL; /* g_main_context_new (); */
1838 data->loop = g_main_loop_new (context, FALSE /* not running */);
1840 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1842 /* This main loop will run until the idle handler has stopped it: */
1843 g_main_loop_run (data->loop);
1845 g_main_loop_unref (data->loop);
1846 /* g_main_context_unref (context); */
1848 is_online = data->is_online;
1849 g_slice_free (CheckAccountIdleData, data);
1857 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1859 /* GTK_RESPONSE_HELP means we need to show the certificate */
1860 if (response_id == GTK_RESPONSE_APPLY) {
1864 /* Do not close the dialog */
1865 g_signal_stop_emission_by_name (dialog, "response");
1867 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1868 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1869 gtk_dialog_run (GTK_DIALOG(note));
1870 gtk_widget_destroy (note);
1876 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1877 const gchar *certificate)
1882 HildonWindowStack *stack;
1884 stack = hildon_window_stack_get_default ();
1885 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1888 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1893 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1896 /* We use GTK_RESPONSE_APPLY because we want the button in the
1897 middle of OK and CANCEL the same as the browser does for
1898 example. With GTK_RESPONSE_HELP the view button is aligned
1899 to the left while the other two to the right */
1900 note = hildon_note_new_confirmation_add_buttons (
1903 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1904 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1905 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1908 g_signal_connect (G_OBJECT(note), "response",
1909 G_CALLBACK(on_cert_dialog_response),
1910 (gpointer) certificate);
1912 response = gtk_dialog_run(GTK_DIALOG(note));
1914 on_destroy_dialog (note);
1917 return response == GTK_RESPONSE_OK;
1921 modest_platform_run_alert_dialog (const gchar* prompt,
1922 gboolean is_question)
1924 ModestWindow *top_win;
1925 HildonWindowStack *stack;
1927 stack = hildon_window_stack_get_default ();
1928 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
1931 g_warning ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
1936 gboolean retval = TRUE;
1938 /* The Tinymail documentation says that we should show Yes and No buttons,
1939 * when it is a question.
1940 * Obviously, we need tinymail to use more specific error codes instead,
1941 * so we know what buttons to show. */
1942 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
1944 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1945 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
1947 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1948 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1950 on_destroy_dialog (dialog);
1952 /* Just show the error text and use the default response: */
1953 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
1961 GtkWindow *parent_window;
1962 ModestConnectedPerformer callback;
1963 TnyAccount *account;
1970 on_went_online_info_free (OnWentOnlineInfo *info)
1972 /* And if we cleanup, we DO cleanup :-) */
1975 g_object_unref (info->device);
1978 if (info->parent_window)
1979 g_object_unref (info->parent_window);
1981 g_object_unref (info->account);
1983 g_slice_free (OnWentOnlineInfo, info);
1985 /* We're done ... */
1991 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
1993 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1995 /* Now it's really time to callback to the caller. If going online didn't succeed,
1996 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
1997 * canceled will be set. Etcetera etcetera. */
1999 if (info->callback) {
2000 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2003 /* This is our last call, we must cleanup here if we didn't yet do that */
2004 on_went_online_info_free (info);
2011 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2013 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2014 info->iap = g_strdup (iap_id);
2016 if (canceled || err || !info->account) {
2018 /* If there's a problem or if there's no account (then that's it for us, we callback
2019 * the caller's callback now. He'll have to handle err or canceled, of course.
2020 * We are not really online, as the account is not really online here ... */
2022 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2023 * this info. We don't cleanup err, Tinymail does that! */
2025 if (info->callback) {
2027 /* info->account can be NULL here, this means that the user did not
2028 * provide a nice account instance. We'll assume that the user knows
2029 * what he's doing and is happy with just the device going online.
2031 * We can't do magic, we don't know what account the user wants to
2032 * see going online. So just the device goes online, end of story */
2034 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2037 } else if (info->account) {
2039 /* If there's no problem and if we have an account, we'll put the account
2040 * online too. When done, the callback of bringing the account online
2041 * will callback the caller's callback. This is the most normal case. */
2043 info->device = TNY_DEVICE (g_object_ref (device));
2045 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2046 on_account_went_online, info);
2048 /* The on_account_went_online cb frees up the info, go look if you
2049 * don't believe me! (so we return here) */
2054 /* We cleanup if we are not bringing the account online too */
2055 on_went_online_info_free (info);
2061 modest_platform_connect_and_perform (GtkWindow *parent_window,
2063 TnyAccount *account,
2064 ModestConnectedPerformer callback,
2067 gboolean device_online;
2069 TnyConnectionStatus conn_status;
2070 OnWentOnlineInfo *info;
2072 device = modest_runtime_get_device();
2073 device_online = tny_device_is_online (device);
2075 /* If there is no account check only the device status */
2078 if (device_online) {
2080 /* We promise to instantly perform the callback, so ... */
2082 callback (FALSE, NULL, parent_window, account, user_data);
2087 info = g_slice_new0 (OnWentOnlineInfo);
2090 info->device = NULL;
2091 info->account = NULL;
2094 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2096 info->parent_window = NULL;
2097 info->user_data = user_data;
2098 info->callback = callback;
2100 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2101 force, on_conic_device_went_online,
2104 /* We'll cleanup in on_conic_device_went_online */
2107 /* The other code has no more reason to run. This is all that we can do for the
2108 * caller (he should have given us a nice and clean account instance!). We
2109 * can't do magic, we don't know what account he intends to bring online. So
2110 * we'll just bring the device online (and await his false bug report). */
2116 /* Return if the account is already connected */
2118 conn_status = tny_account_get_connection_status (account);
2119 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2121 /* We promise to instantly perform the callback, so ... */
2123 callback (FALSE, NULL, parent_window, account, user_data);
2129 /* Else, we are in a state that requires that we go online before we
2130 * call the caller's callback. */
2132 info = g_slice_new0 (OnWentOnlineInfo);
2134 info->device = NULL;
2136 info->account = TNY_ACCOUNT (g_object_ref (account));
2139 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2141 info->parent_window = NULL;
2143 /* So we'll put the callback away for later ... */
2145 info->user_data = user_data;
2146 info->callback = callback;
2148 if (!device_online) {
2150 /* If also the device is offline, then we connect both the device
2151 * and the account */
2153 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2154 force, on_conic_device_went_online,
2159 /* If the device is online, we'll just connect the account */
2161 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2162 on_account_went_online, info);
2165 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2166 * in both situations, go look if you don't believe me! */
2172 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2174 TnyFolderStore *folder_store,
2175 ModestConnectedPerformer callback,
2178 TnyAccount *account = NULL;
2180 if (!folder_store ||
2181 (TNY_IS_MERGE_FOLDER (folder_store) &&
2182 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2184 /* We promise to instantly perform the callback, so ... */
2186 GError *error = NULL;
2187 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2188 "Unable to move or not found folder");
2189 callback (FALSE, error, parent_window, NULL, user_data);
2190 g_error_free (error);
2194 } else if (TNY_IS_FOLDER (folder_store)) {
2195 /* Get the folder's parent account: */
2196 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2197 } else if (TNY_IS_ACCOUNT (folder_store)) {
2198 /* Use the folder store as an account: */
2199 account = TNY_ACCOUNT (g_object_ref (folder_store));
2202 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
2203 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2204 /* No need to connect a local account */
2206 callback (FALSE, NULL, parent_window, account, user_data);
2211 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2215 g_object_unref (account);
2219 src_account_connect_performer (gboolean canceled,
2221 GtkWindow *parent_window,
2222 TnyAccount *src_account,
2225 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2227 if (canceled || err) {
2228 /* If there was any error call the user callback */
2229 info->callback (canceled, err, parent_window, src_account, info->data);
2231 /* Connect the destination account */
2232 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2233 TNY_FOLDER_STORE (info->dst_account),
2234 info->callback, info->data);
2237 /* Free the info object */
2238 g_object_unref (info->dst_account);
2239 g_slice_free (DoubleConnectionInfo, info);
2244 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2246 TnyFolderStore *folder_store,
2247 DoubleConnectionInfo *connect_info)
2249 modest_platform_connect_if_remote_and_perform(parent_window,
2252 src_account_connect_performer,
2257 modest_platform_get_account_settings_wizard (void)
2259 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2261 return GTK_WIDGET (dialog);
2265 modest_platform_get_current_connection (void)
2267 TnyDevice *device = NULL;
2268 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2270 device = modest_runtime_get_device ();
2272 if (!tny_device_is_online (device))
2273 return MODEST_CONNECTED_VIA_ANY;
2275 #ifdef MODEST_HAVE_CONIC
2277 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2279 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2280 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2281 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2283 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2284 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2285 !strcmp (bearer_type, "WIMAX")) {
2286 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2288 retval = MODEST_CONNECTED_VIA_ANY;
2291 g_object_unref (iap);
2294 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2295 #endif /* MODEST_HAVE_CONIC */
2302 modest_platform_check_memory_low (ModestWindow *win,
2307 /* are we in low memory state? */
2308 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2310 if (win && lowmem && visuals)
2311 modest_platform_run_information_dialog (
2313 _KR("memr_ib_operation_disabled"),
2317 g_debug ("%s: low memory reached. disallowing some operations",
2324 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2330 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2333 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2334 GTK_WINDOW (dialog),
2336 gtk_widget_show_all (dialog);
2338 g_signal_connect_swapped (dialog, "response",
2339 G_CALLBACK (gtk_widget_destroy),
2344 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2350 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2353 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2354 GTK_WINDOW (dialog),
2356 gtk_widget_show_all (dialog);
2358 g_signal_connect_swapped (dialog, "response",
2359 G_CALLBACK (gtk_widget_destroy),
2364 modest_platform_get_osso_context (void)
2366 return modest_maemo_utils_get_osso_context ();
2370 _modest_platform_play_email_tone (void)
2372 gchar *active_profile;
2375 gint mail_volume_int;
2377 ca_context *ca_con = NULL;
2378 ca_proplist *pl = NULL;
2380 active_profile = profile_get_profile ();
2381 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2382 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2383 mail_volume_int = profile_parse_int (mail_volume);
2385 if (mail_volume_int > 0) {
2387 if ((ret = ca_context_create(&ca_con)) != CA_SUCCESS) {
2388 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2392 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2393 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2394 ca_context_destroy(ca_con);
2398 ca_proplist_create(&pl);
2399 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2400 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", (gfloat) mail_volume_int);
2402 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2403 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2405 ca_proplist_destroy(pl);
2406 ca_context_destroy(ca_con);
2409 g_free (mail_volume);
2411 g_free (active_profile);
2414 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
2415 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
2416 #define MOVE_TO_DIALOG_SELECTION_LABEL "selection-label"
2417 #define MOVE_TO_DIALOG_SHOWING_FOLDERS "showing-folders"
2418 #define MOVE_TO_DIALOG_PANNABLE "pannable"
2421 move_to_dialog_show_accounts (GtkWidget *dialog)
2423 GtkWidget *selection_label;
2424 GtkWidget *back_button;
2425 GtkWidget *folder_view;
2426 GtkWidget *pannable;
2428 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2429 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2430 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2431 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2433 gtk_widget_set_sensitive (back_button, FALSE);
2435 gtk_label_set_text (GTK_LABEL (selection_label), "");
2436 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2437 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
2438 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2439 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2440 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2442 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (FALSE));
2446 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
2448 GtkWidget *selection_label;
2449 GtkWidget *back_button;
2450 GtkWidget *folder_view;
2451 TnyAccount *account;
2452 const gchar *account_id;
2453 gchar *selection_label_text;
2454 GtkWidget *pannable;
2456 selection_label = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL));
2457 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2458 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2459 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2461 gtk_widget_set_sensitive (back_button, TRUE);
2463 account = TNY_ACCOUNT (folder_store);
2464 if (modest_tny_account_is_virtual_local_folders (account)) {
2465 account_id = tny_account_get_id (account);
2466 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2467 } else if (modest_tny_account_is_memory_card_account (account)) {
2468 account_id = tny_account_get_id (account);
2469 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2471 account_id = tny_account_get_id (account);
2473 selection_label_text = g_strconcat (tny_account_get_name (account), "/", NULL);
2474 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2475 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2477 gtk_label_set_text (GTK_LABEL (selection_label), selection_label_text);
2478 g_free (selection_label_text);
2480 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
2483 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
2484 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
2485 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2486 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2488 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (TRUE));
2492 on_move_to_dialog_back_clicked (GtkButton *button,
2495 GtkWidget *dialog = (GtkWidget *) userdata;
2497 move_to_dialog_show_accounts (dialog);
2501 on_move_to_dialog_folder_activated (GtkTreeView *tree_view,
2503 GtkTreeViewColumn *column,
2506 TnyFolderStore *selected;
2508 GtkWidget *folder_view;
2509 gboolean showing_folders;
2511 dialog = (GtkWidget *) user_data;
2512 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2513 if (showing_folders) {
2514 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_OK);
2516 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2518 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2520 move_to_dialog_show_folders (dialog, selected);
2526 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
2527 GtkWidget **folder_view)
2529 GtkWidget *dialog, *folder_view_container;
2530 GtkWidget *buttons_hbox;
2531 GtkWidget *back_button, *selection_label;
2532 GdkPixbuf *back_pixbuf;
2534 /* Create dialog. We cannot use a touch selector because we
2535 need to use here the folder view widget directly */
2536 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2537 GTK_WINDOW (parent_window),
2538 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
2539 GTK_DIALOG_DESTROY_WITH_PARENT,
2540 _HL("wdgt_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
2543 /* Create folder view */
2544 *folder_view = modest_platform_create_folder_view (NULL);
2546 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
2547 (TnyAccountStore *) modest_runtime_get_account_store ());
2549 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
2550 back_button = gtk_button_new ();
2551 back_pixbuf = modest_platform_get_icon (_FM("filemanager_folder_up"), MODEST_ICON_SIZE_BIG);
2553 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
2554 g_object_unref (back_pixbuf);
2556 selection_label = gtk_label_new ("");
2557 gtk_misc_set_alignment (GTK_MISC (selection_label), 0.0, 0.5);
2558 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
2559 gtk_box_pack_start (GTK_BOX (buttons_hbox), selection_label, TRUE, TRUE, 0);
2560 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
2561 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), buttons_hbox, FALSE, FALSE, 0);
2563 /* Create pannable and add it to the dialog */
2564 folder_view_container = hildon_pannable_area_new ();
2565 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), folder_view_container, TRUE, TRUE, 0);
2566 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
2568 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
2570 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
2571 gtk_widget_show (folder_view_container);
2572 gtk_widget_show (*folder_view);
2573 gtk_widget_show_all (back_button);
2574 gtk_widget_show (selection_label);
2575 gtk_widget_show (buttons_hbox);
2577 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
2578 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
2579 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SELECTION_LABEL, selection_label);
2580 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE, folder_view_container);
2582 /* Simulate the behaviour of a HildonPickerDialog by emitting
2583 a response when a folder is selected */
2584 g_signal_connect (*folder_view, "row-activated",
2585 G_CALLBACK (on_move_to_dialog_folder_activated),
2588 g_signal_connect (back_button, "clicked",
2589 G_CALLBACK (on_move_to_dialog_back_clicked),
2592 move_to_dialog_show_accounts (dialog);
2598 modest_platform_get_list_to_move (ModestWindow *window)
2600 TnyList *list = NULL;
2602 if (MODEST_IS_HEADER_WINDOW (window)) {
2603 ModestHeaderView *header_view;
2605 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
2606 list = modest_header_view_get_selected_headers (header_view);
2607 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
2608 ModestFolderView *folder_view;
2609 TnyFolderStore *selected_folder;
2611 list = TNY_LIST (tny_simple_list_new ());
2612 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
2613 selected_folder = modest_folder_view_get_selected (folder_view);
2614 if (selected_folder) {
2615 tny_list_prepend (list, G_OBJECT (selected_folder));
2616 g_object_unref (selected_folder);
2619 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2622 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
2624 list = TNY_LIST (tny_simple_list_new ());
2625 tny_list_prepend (list, G_OBJECT (header));
2626 g_object_unref (header);
2629 g_return_val_if_reached (NULL);