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 <modest-utils.h>
43 #include <dbus_api/modest-dbus-callbacks.h>
44 #include <modest-osso-autosave-callbacks.h>
46 #include <tny-maemo-conic-device.h>
47 #include <tny-camel-folder.h>
48 #include <tny-simple-list.h>
49 #include <tny-merge-folder.h>
50 #include <tny-error.h>
51 #include <tny-folder.h>
52 #include <tny-account-store-view.h>
53 #include <gtk/gtkicontheme.h>
54 #include <gtk/gtkmenuitem.h>
55 #include <gtk/gtkmain.h>
56 #include <modest-text-utils.h>
57 #include "modest-tny-folder.h"
58 #include "modest-tny-account.h"
60 #include <libgnomevfs/gnome-vfs-mime-utils.h>
61 #include <modest-account-settings-dialog.h>
62 #include <modest-easysetup-wizard-dialog.h>
63 #include "modest-hildon2-sort-dialog.h"
64 #include <hildon/hildon.h>
66 #include "hildon2/modest-hildon2-details-dialog.h"
67 #include "hildon2/modest-hildon2-window-mgr.h"
68 #ifdef MODEST_USE_PROFILE
69 #include <keys_nokia.h>
70 #include <libprofile.h>
73 #include <modest-datetime-formatter.h>
74 #include "modest-header-window.h"
75 #include <modest-folder-window.h>
76 #include <modest-account-mgr.h>
77 #include <modest-account-mgr-helpers.h>
78 #include <modest-ui-constants.h>
79 #include <modest-selector-picker.h>
80 #include <modest-icon-names.h>
81 #include <modest-count-stream.h>
84 #ifdef MODEST_HAVE_MCE
85 #include <mce/dbus-names.h>
86 #endif /*MODEST_HAVE_MCE*/
88 #ifdef MODEST_HAVE_ABOOK
89 #include <libosso-abook/osso-abook.h>
90 #endif /*MODEST_HAVE_ABOOK*/
92 #ifdef MODEST_HAVE_LIBALARM
93 #include <alarmd/libalarm.h> /* For alarm_event_add(), etc. */
94 #endif /*MODEST_HAVE_LIBALARM*/
97 #define HILDON_OSSO_URI_ACTION "uri-action"
98 #define URI_ACTION_COPY "copy:"
99 #define MODEST_NOTIFICATION_CATEGORY "email-message"
100 #define MODEST_NEW_MAIL_LIGHTING_PATTERN "PatternChatAndEmail"
101 #ifdef MODEST_USE_PROFILE
102 #define PROFILE_MAIL_TONE PROFILEKEY_EMAIL_ALERT_TONE
103 #define PROFILE_MAIL_VOLUME PROFILEKEY_EMAIL_ALERT_VOLUME
105 #define MAIL_TONE "message-new-email"
108 #define COMMON_FOLDER_DIALOG_ENTRY "entry"
109 #define COMMON_FOLDER_DIALOG_ACCOUNT_PICKER "account-picker"
110 #define FOLDER_PICKER_CURRENT_FOLDER "current-folder"
111 #define FOLDER_PICKER_ORIGINAL_ACCOUNT "original-account"
112 #define MODEST_ALARMD_APPID PACKAGE_NAME
114 static ca_context *ca_con = NULL;
115 static gboolean ca_con_opened = FALSE;
118 static void modest_platform_play_email_tone (void);
122 on_modest_conf_update_interval_changed (ModestConf* self,
124 ModestConfEvent event,
125 ModestConfNotificationId id,
128 g_return_if_fail (key);
130 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
131 const guint update_interval_minutes =
132 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
133 modest_platform_set_update_interval (update_interval_minutes);
140 check_required_files (void)
142 FILE *mcc_file = modest_utils_open_mcc_mapping_file ();
145 g_printerr ("modest: check for mcc file (for LANG) failed\n");
151 if (access(MODEST_PROVIDER_DATA_FILE, R_OK) != 0 &&
152 access(MODEST_FALLBACK_PROVIDER_DATA_FILE, R_OK) != 0) {
153 g_printerr ("modest: cannot find providers data\n");
161 /* the gpointer here is the osso_context. */
163 modest_platform_init (int argc, char *argv[])
165 osso_context_t *osso_context;
166 osso_hw_state_t hw_state = { 0 };
170 if (!check_required_files ()) {
171 g_printerr ("modest: missing required files\n");
175 osso_context = modest_maemo_utils_get_osso_context();
177 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
178 g_printerr ("modest: could not get dbus connection\n");
182 /* Add a D-Bus handler to be used when the main osso-rpc
183 * D-Bus handler has not handled something.
184 * We use this for D-Bus methods that need to use more complex types
185 * than osso-rpc supports.
187 if (!dbus_connection_add_filter (con,
188 modest_dbus_req_filter,
192 g_printerr ("modest: Could not add D-Bus filter\n");
196 /* Register our simple D-Bus callbacks, via the osso API: */
197 osso_return_t result = osso_rpc_set_cb_f(osso_context,
201 modest_dbus_req_handler, NULL /* user_data */);
202 if (result != OSSO_OK) {
203 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
207 /* Register hardware event dbus callback: */
208 hw_state.shutdown_ind = TRUE;
209 osso_hw_set_event_cb(osso_context, NULL, NULL, NULL);
211 /* Register osso auto-save callbacks: */
212 result = osso_application_set_autosave_cb (osso_context,
213 modest_on_osso_application_autosave, NULL /* user_data */);
214 if (result != OSSO_OK) {
215 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
220 /* Make sure that the update interval is changed whenever its gconf key
222 /* CAUTION: we're not using here the
223 modest_conf_listen_to_namespace because we know that there
224 are other parts of Modest listening for this namespace, so
225 we'll receive the notifications anyway. We basically do not
226 use it because there is no easy way to do the
227 modest_conf_forget_namespace */
228 ModestConf *conf = modest_runtime_get_conf ();
229 g_signal_connect (G_OBJECT(conf),
231 G_CALLBACK (on_modest_conf_update_interval_changed),
234 /* only force the setting of the default interval, if there are actually
236 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
238 /* Get the initial update interval from gconf: */
239 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
240 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
241 modest_account_mgr_free_account_names (acc_names);
245 #ifdef MODEST_HAVE_ABOOK
246 /* initialize the addressbook */
247 if (!osso_abook_init (&argc, &argv, osso_context)) {
248 g_printerr ("modest: failed to initialized addressbook\n");
251 #endif /*MODEST_HAVE_ABOOK*/
257 modest_platform_uninit (void)
259 osso_context_t *osso_context =
260 modest_maemo_utils_get_osso_context ();
262 osso_deinitialize (osso_context);
271 modest_platform_get_new_device (void)
273 return TNY_DEVICE (tny_maemo_conic_device_new ());
277 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
278 gchar **effective_mime_type)
280 GString *mime_str = NULL;
281 gchar *icon_name = NULL;
282 gchar **icons, **cursor;
284 if (!mime_type || g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0)
285 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
287 mime_str = g_string_new (mime_type);
288 g_string_ascii_down (mime_str);
291 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
293 for (cursor = icons; cursor; ++cursor) {
294 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
295 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
296 icon_name = g_strdup ("qgn_list_messagin");
298 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
299 icon_name = g_strdup (*cursor);
305 if (effective_mime_type)
306 *effective_mime_type = g_string_free (mime_str, FALSE);
308 g_string_free (mime_str, TRUE);
315 checked_hildon_uri_open (const gchar *uri, HildonURIAction *action)
320 g_return_val_if_fail (uri, FALSE);
322 result = hildon_uri_open (uri, action, &err);
324 g_printerr ("modest: hildon_uri_open ('%s', %p) failed: %s",
325 uri, action, err && err->message ? err->message : "unknown error");
335 modest_platform_activate_uri (const gchar *uri)
337 HildonURIAction *action;
338 gboolean result = FALSE;
339 GSList *actions, *iter = NULL;
341 g_return_val_if_fail (uri, FALSE);
345 /* don't try to activate file: uri's -- they might confuse the user,
346 * and/or might have security implications */
347 if (!g_str_has_prefix (uri, "file:")) {
349 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
351 for (iter = actions; iter; iter = g_slist_next (iter)) {
352 action = (HildonURIAction*) iter->data;
353 if (action && strcmp (hildon_uri_action_get_service (action),
354 "com.nokia.modest") == 0) {
355 result = checked_hildon_uri_open (uri, action);
360 /* if we could not open it with email, try something else */
362 result = checked_hildon_uri_open (uri, NULL);
366 ModestWindow *parent =
367 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
368 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
369 _("mcen_ib_unsupported_link"));
370 g_debug ("%s: cannot open uri '%s'", __FUNCTION__,uri);
377 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
381 gchar *uri_path = NULL;
383 uri_path = gnome_vfs_get_uri_from_local_path (path);
384 con = osso_get_dbus_connection (modest_maemo_utils_get_osso_context());
387 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
389 result = hildon_mime_open_file (con, uri_path);
391 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"), FALSE);
399 } ModestPlatformPopupInfo;
402 delete_uri_popup (GtkWidget *menu,
406 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
408 g_free (popup_info->uri);
409 hildon_uri_free_actions (popup_info->actions);
415 activate_uri_popup_item (GtkMenuItem *menu_item,
419 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
420 const gchar* action_name;
422 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
424 g_printerr ("modest: no action name defined\n");
428 /* special handling for the copy menu item -- copy the uri to the clipboard */
429 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
430 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
431 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
432 const gchar *uri = (const gchar *) popup_info->uri;
434 /* Special case: ignore "mailto:" prefixes */
435 if (g_str_has_prefix (uri, "mailto:"))
436 uri = popup_info->uri + strlen ("mailto:");
438 gtk_clipboard_set_text (clipboard, uri, strlen (uri));
439 modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
440 return; /* we're done */
443 /* now, the real uri-actions... */
444 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
445 HildonURIAction *action = (HildonURIAction *) node->data;
446 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
447 if (!checked_hildon_uri_open (popup_info->uri, action)) {
448 ModestWindow *parent =
449 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
450 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
451 _("mcen_ib_unsupported_link"));
459 modest_platform_show_uri_popup (const gchar *uri)
461 GSList *actions_list, *node;
463 ModestPlatformPopupInfo *popup_info;
464 GtkWidget *menu_item;
470 menu = gtk_menu_new ();
471 popup_info = g_new0 (ModestPlatformPopupInfo, 1);
472 popup_info->uri = g_strdup (uri);
474 /* don't add actions for file: uri's -- they might confuse the user,
475 * and/or might have security implications
476 * we still allow to copy the url though
478 if (g_str_has_prefix (uri, "file:"))
481 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
485 popup_info->actions = actions_list;
486 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
487 const gchar *action_name;
488 const gchar *translation_domain;
489 HildonURIAction *action = (HildonURIAction *) node->data;
490 action_name = hildon_uri_action_get_name (action);
491 translation_domain = hildon_uri_action_get_translation_domain (action);
492 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
493 hildon_gtk_widget_set_theme_size (menu_item, MODEST_EDITABLE_SIZE);
494 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
495 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
498 if (hildon_uri_is_default_action (action, NULL)) {
499 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
501 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
503 gtk_widget_show (menu_item);
507 /* Add the "Copy link" menu option */
508 menu_item = gtk_menu_item_new_with_label (_UR("uri_link_copy_link_location"));
509 hildon_gtk_widget_set_theme_size (menu_item, MODEST_EDITABLE_SIZE);
510 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer) URI_ACTION_COPY);
511 g_signal_connect (G_OBJECT (menu_item), "activate", (GCallback) activate_uri_popup_item, popup_info);
512 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
513 gtk_widget_show (menu_item);
515 /* and what to do when the link is deleted */
516 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
517 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
524 modest_platform_get_icon (const gchar *name, guint icon_size)
527 GdkPixbuf* pixbuf = NULL;
528 GtkIconTheme *current_theme = NULL;
530 g_return_val_if_fail (name, NULL);
532 /* strlen == 0 is not really an error; it just
533 * means the icon is not available
535 if (!name || strlen(name) == 0)
538 current_theme = gtk_icon_theme_get_default ();
539 pixbuf = gtk_icon_theme_load_icon (current_theme, name, icon_size,
540 GTK_ICON_LOOKUP_NO_SVG,
543 g_warning ("Error loading theme icon '%s': %s\n",
551 modest_platform_get_app_name (void)
553 return _("mcen_ap_name");
557 entry_insert_text (GtkEditable *editable,
566 chars = gtk_editable_get_chars (editable, 0, -1);
567 chars_length = g_utf8_strlen (chars, -1);
570 /* Show WID-INF036 */
571 if (chars_length >= 20) {
572 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
573 _CS("ckdg_ib_maximum_characters_reached"));
575 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
579 tmp = g_strndup (folder_name_forbidden_chars,
580 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
581 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
582 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
588 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
589 _CS("ckdg_ib_maximum_characters_reached"));
591 /* Write the text in the entry if it's valid */
592 g_signal_handlers_block_by_func (editable,
593 (gpointer) entry_insert_text, data);
594 gtk_editable_insert_text (editable, text, length, position);
595 g_signal_handlers_unblock_by_func (editable,
596 (gpointer) entry_insert_text, data);
599 /* Do not allow further processing */
600 g_signal_stop_emission_by_name (editable, "insert_text");
604 entry_changed (GtkEditable *editable,
608 GtkWidget *ok_button;
611 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
612 ok_button = GTK_WIDGET (buttons->data);
614 chars = gtk_editable_get_chars (editable, 0, -1);
615 g_return_if_fail (chars != NULL);
618 if (g_utf8_strlen (chars,-1) >= 20) {
619 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
620 _CS("ckdg_ib_maximum_characters_reached"));
622 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
625 g_list_free (buttons);
632 on_response (GtkDialog *dialog,
636 GtkWidget *entry, *picker;
637 TnyFolderStore *parent;
638 const gchar *new_name;
641 if (response != GTK_RESPONSE_ACCEPT)
645 entry = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY);
646 picker = g_object_get_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER);
648 parent = TNY_FOLDER_STORE (user_data);
649 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
653 parent = g_object_get_data (G_OBJECT (picker), FOLDER_PICKER_CURRENT_FOLDER);
655 /* Look for another folder with the same name */
656 if (!TNY_IS_MERGE_FOLDER (parent) &&
657 modest_tny_folder_has_subfolder_with_name (parent, new_name, TRUE))
661 if (TNY_IS_ACCOUNT (parent) &&
662 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
663 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
671 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
672 NULL, _CS("ckdg_ib_folder_already_exists"));
673 /* Select the text */
674 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
675 gtk_widget_grab_focus (entry);
676 /* Do not close the dialog */
677 g_signal_stop_emission_by_name (dialog, "response");
681 typedef struct _FolderChooserData {
682 TnyFolderStore *store;
687 folder_chooser_activated (ModestFolderView *folder_view,
688 TnyFolderStore *folder,
689 FolderChooserData *userdata)
691 userdata->store = folder;
692 gtk_dialog_response (GTK_DIALOG (userdata->dialog), GTK_RESPONSE_OK);
695 static TnyFolderStore *
696 folder_chooser_dialog_run (ModestFolderView *original,
697 TnyFolderStore *current,
700 GtkWidget *folder_view;
701 FolderChooserData userdata = {NULL, NULL};
703 const gchar *visible_id = NULL;
705 userdata.dialog = gtk_dialog_new ();
706 pannable = hildon_pannable_area_new ();
707 folder_view = modest_platform_create_folder_view (NULL);
709 gtk_window_set_title (GTK_WINDOW (userdata.dialog), _FM("ckdg_ti_change_folder"));
711 modest_folder_view_copy_model (MODEST_FOLDER_VIEW (original),
712 MODEST_FOLDER_VIEW (folder_view));
714 if (TNY_IS_ACCOUNT (current)) {
715 /* Local folders and MMC account are always shown
716 along with the currently visible server account */
717 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (current)) ||
718 modest_tny_account_is_memory_card_account (TNY_ACCOUNT (current)))
719 visible_id = g_object_get_data ((GObject *) picker, FOLDER_PICKER_ORIGINAL_ACCOUNT);
721 visible_id = tny_account_get_id (TNY_ACCOUNT (current));
722 } else if (TNY_IS_FOLDER (current)) {
724 account = modest_tny_folder_get_account ((TnyFolder *) current);
726 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (account)) ||
727 modest_tny_account_is_memory_card_account (TNY_ACCOUNT (account))) {
728 visible_id = g_object_get_data ((GObject *) picker, FOLDER_PICKER_ORIGINAL_ACCOUNT);
730 visible_id = tny_account_get_id (account);
732 g_object_unref (account);
736 modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(original));
739 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view),
742 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (userdata.dialog)->vbox), pannable);
743 gtk_container_add (GTK_CONTAINER (pannable), folder_view);
744 gtk_widget_set_size_request (pannable, -1, 320);
746 gtk_widget_show (folder_view);
747 gtk_widget_show (pannable);
748 gtk_widget_show (userdata.dialog);
749 g_signal_connect (G_OBJECT (folder_view), "folder-activated",
750 G_CALLBACK (folder_chooser_activated),
751 (gpointer) &userdata);
753 gtk_dialog_run (GTK_DIALOG (userdata.dialog));
754 gtk_widget_destroy (userdata.dialog);
756 return userdata.store;
760 folder_store_get_display_name (TnyFolderStore *store)
762 if (TNY_IS_ACCOUNT (store)) {
763 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
764 return modest_conf_get_string (modest_runtime_get_conf(),
765 MODEST_CONF_DEVICE_NAME, NULL);
767 return g_strdup (tny_account_get_name (TNY_ACCOUNT (store)));
770 TnyFolderType type = TNY_FOLDER_TYPE_UNKNOWN;
772 fname = g_strdup (tny_folder_get_name (TNY_FOLDER (store)));
773 type = tny_folder_get_folder_type (TNY_FOLDER (store));
774 if (modest_tny_folder_is_local_folder (TNY_FOLDER (store)) ||
775 modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
776 type = modest_tny_folder_get_local_or_mmc_folder_type (TNY_FOLDER (store));
777 if (type != TNY_FOLDER_TYPE_UNKNOWN) {
779 fname = g_strdup (modest_local_folder_info_get_type_display_name (type));
782 /* Sometimes an special folder is reported by the server as
783 NORMAL, like some versions of Dovecot */
784 if (type == TNY_FOLDER_TYPE_NORMAL ||
785 type == TNY_FOLDER_TYPE_UNKNOWN) {
786 type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
790 if (type == TNY_FOLDER_TYPE_INBOX) {
792 fname = g_strdup (_("mcen_me_folder_inbox"));
799 get_image_for_folder_store (TnyFolderStore *store,
803 const gchar *icon_name = NULL;
804 GtkWidget *image = NULL;
806 if (TNY_IS_ACCOUNT (store)) {
807 if (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (store)))
808 icon_name = MODEST_FOLDER_ICON_LOCAL_FOLDERS;
809 else if (modest_tny_account_is_memory_card_account (TNY_ACCOUNT (store)))
810 icon_name = MODEST_FOLDER_ICON_MMC;
812 icon_name = MODEST_FOLDER_ICON_ACCOUNT;
814 TnyFolderType type = modest_tny_folder_guess_folder_type (TNY_FOLDER (store));
815 if (modest_tny_folder_is_remote_folder (TNY_FOLDER (store))) {
817 case TNY_FOLDER_TYPE_INBOX:
818 icon_name = MODEST_FOLDER_ICON_INBOX;
821 icon_name = MODEST_FOLDER_ICON_REMOTE_FOLDER;
823 } else if (modest_tny_folder_is_local_folder (TNY_FOLDER (store))) {
825 case TNY_FOLDER_TYPE_OUTBOX:
826 icon_name = MODEST_FOLDER_ICON_OUTBOX;
828 case TNY_FOLDER_TYPE_DRAFTS:
829 icon_name = MODEST_FOLDER_ICON_DRAFTS;
831 case TNY_FOLDER_TYPE_SENT:
832 icon_name = MODEST_FOLDER_ICON_SENT;
835 icon_name = MODEST_FOLDER_ICON_NORMAL;
837 } else if (modest_tny_folder_is_memory_card_folder (TNY_FOLDER (store))) {
838 icon_name = MODEST_FOLDER_ICON_MMC_FOLDER;
843 pixbuf = modest_platform_get_icon (icon_name, size);
846 image = gtk_image_new_from_pixbuf (pixbuf);
847 g_object_unref (pixbuf);
854 folder_picker_set_store (GtkButton *button, TnyFolderStore *store)
859 g_object_set_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER, NULL);
863 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER,
864 g_object_ref (store),
865 (GDestroyNotify) g_object_unref);
866 name = folder_store_get_display_name (store);
867 hildon_button_set_value (HILDON_BUTTON (button), name);
871 image = get_image_for_folder_store (store, MODEST_ICON_SIZE_SMALL);
873 hildon_button_set_image (HILDON_BUTTON (button), image);
877 /* Always returns DUPs so you must free the returned value */
879 get_next_folder_name (const gchar *suggested_name,
880 TnyFolderStore *suggested_folder)
882 const gchar *default_name = _FM("ckdg_va_new_folder_name_stub");
884 gchar *real_suggested_name;
886 if (suggested_name !=NULL) {
887 return g_strdup (suggested_name);
890 for(i = 0; i < 100; ++ i) {
891 gboolean exists = FALSE;
894 real_suggested_name = g_strdup (default_name);
896 real_suggested_name = g_strdup_printf ("%s(%d)",
897 _FM("ckdg_va_new_folder_name_stub"),
899 exists = modest_tny_folder_has_subfolder_with_name (suggested_folder,
906 g_free (real_suggested_name);
909 /* Didn't find a free number */
911 real_suggested_name = g_strdup (default_name);
913 return real_suggested_name;
917 ModestFolderView *folder_view;
919 } FolderPickerHelper;
922 folder_picker_clicked (GtkButton *button,
923 FolderPickerHelper *helper)
925 TnyFolderStore *store, *current;
927 current = g_object_get_data (G_OBJECT (button), FOLDER_PICKER_CURRENT_FOLDER);
929 store = folder_chooser_dialog_run (helper->folder_view, current, button);
931 const gchar *current_name;
932 gboolean exists = FALSE;
934 folder_picker_set_store (GTK_BUTTON (button), store);
936 /* Update the name of the folder */
937 current_name = gtk_entry_get_text (helper->entry);
939 if (TNY_IS_FOLDER_STORE (store))
940 exists = modest_tny_folder_has_subfolder_with_name (store,
944 gchar *new_name = get_next_folder_name (NULL, store);
945 gtk_entry_set_text (helper->entry, new_name);
952 folder_picker_new (TnyFolderStore *suggested, FolderPickerHelper *helper)
955 const gchar *acc_id = NULL;
957 button = hildon_button_new (MODEST_EDITABLE_SIZE,
958 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
960 hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 1.0);
964 folder_picker_set_store (GTK_BUTTON (button), suggested);
966 if (TNY_IS_ACCOUNT (suggested)) {
967 if (!modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (suggested)) &&
968 !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (suggested)))
969 acc_id = tny_account_get_id ((TnyAccount *) suggested);
971 TnyAccount *account = modest_tny_folder_get_account ((TnyFolder *) suggested);
973 acc_id = tny_account_get_id ((TnyAccount *) account);
974 g_object_unref (account);
980 acc_id = modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(helper->folder_view));
982 g_object_set_data_full (G_OBJECT (button), FOLDER_PICKER_ORIGINAL_ACCOUNT,
983 g_strdup (acc_id), (GDestroyNotify) g_free);
986 g_signal_connect (G_OBJECT (button), "clicked",
987 G_CALLBACK (folder_picker_clicked),
995 modest_platform_run_folder_common_dialog (GtkWindow *parent_window,
996 TnyFolderStore *suggested_parent,
997 const gchar *dialog_title,
998 const gchar *label_text,
999 const gchar *suggested_name,
1001 gboolean show_parent,
1002 gchar **folder_name,
1003 TnyFolderStore **parent)
1005 GtkWidget *accept_btn = NULL;
1006 GtkWidget *dialog, *entry = NULL, *label_entry = NULL, *label_location = NULL, *hbox;
1007 GtkWidget *account_picker = NULL;
1008 GList *buttons = NULL;
1010 GtkSizeGroup *sizegroup;
1011 ModestFolderView *folder_view;
1012 ModestWindow *folder_window;
1013 ModestHildon2WindowMgr *window_mgr;
1014 FolderPickerHelper *helper = NULL;
1015 GtkWidget *top_vbox, *top_align;
1017 window_mgr = (ModestHildon2WindowMgr *) modest_runtime_get_window_mgr ();
1018 folder_window = modest_hildon2_window_mgr_get_folder_window (window_mgr);
1019 g_return_val_if_fail (MODEST_IS_FOLDER_WINDOW (folder_window), GTK_RESPONSE_NONE);
1021 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (folder_window));
1023 top_vbox = gtk_vbox_new (FALSE, 0);
1024 top_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1025 gtk_alignment_set_padding (GTK_ALIGNMENT (top_align), 0, 0, MODEST_MARGIN_DOUBLE, 0);
1027 /* Ask the user for the folder name */
1028 dialog = gtk_dialog_new_with_buttons (dialog_title,
1030 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
1031 _FM("ckdg_bd_new_folder_dialog_ok"),
1032 GTK_RESPONSE_ACCEPT,
1035 /* Add accept button (with unsensitive handler) */
1036 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
1037 accept_btn = GTK_WIDGET (buttons->data);
1039 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
1042 label_entry = gtk_label_new (label_text);
1043 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
1044 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
1046 gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
1047 gtk_size_group_add_widget (sizegroup, label_entry);
1050 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
1052 gtk_entry_set_text (GTK_ENTRY (entry), _FM("ckdg_va_new_folder_name_stub"));
1053 gtk_entry_set_width_chars (GTK_ENTRY (entry),
1054 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
1055 g_utf8_strlen (_FM("ckdg_va_new_folder_name_stub"), -1)));
1056 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
1061 label_location = gtk_label_new (_FM("ckdg_fi_new_folder_location"));
1063 gtk_misc_set_alignment (GTK_MISC (label_location), 0.0, 0.5);
1064 gtk_size_group_add_widget (sizegroup, label_location);
1066 helper = g_slice_new0 (FolderPickerHelper);
1067 helper->folder_view = folder_view;
1068 helper->entry = (GtkEntry *) entry;
1070 account_picker = folder_picker_new (suggested_parent, helper);
1073 g_object_unref (sizegroup);
1075 /* Connect to the response method to avoid closing the dialog
1076 when an invalid name is selected*/
1077 g_signal_connect (dialog,
1079 G_CALLBACK (on_response),
1083 /* Track entry changes */
1084 g_signal_connect (entry,
1086 G_CALLBACK (entry_insert_text),
1088 g_signal_connect (entry,
1090 G_CALLBACK (entry_changed),
1095 /* Some locales like pt_BR need this to get the full window
1097 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
1099 /* Create the hbox */
1101 hbox = gtk_hbox_new (FALSE, 12);
1102 gtk_box_pack_start (GTK_BOX (hbox), label_entry, FALSE, FALSE, 0);
1103 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
1105 /* Add hbox to dialog */
1106 gtk_box_pack_start (GTK_BOX (top_vbox),
1107 hbox, FALSE, FALSE, 0);
1108 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ENTRY, entry);
1112 hbox = gtk_hbox_new (FALSE, 12);
1113 gtk_box_pack_start (GTK_BOX (hbox), label_location, FALSE, FALSE, 0);
1114 gtk_box_pack_start (GTK_BOX (hbox), account_picker, TRUE, TRUE, 0);
1116 /* Add hbox to dialog */
1117 gtk_box_pack_start (GTK_BOX (top_vbox),
1118 hbox, FALSE, FALSE, 0);
1119 g_object_set_data (G_OBJECT (dialog), COMMON_FOLDER_DIALOG_ACCOUNT_PICKER, account_picker);
1121 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1122 GTK_WINDOW (dialog), parent_window);
1124 gtk_container_add (GTK_CONTAINER (top_align), top_vbox);
1125 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), top_align, TRUE, TRUE, 0);
1127 gtk_widget_show_all (GTK_WIDGET(dialog));
1129 result = gtk_dialog_run (GTK_DIALOG(dialog));
1130 if (result == GTK_RESPONSE_ACCEPT) {
1132 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1134 *parent = g_object_get_data (G_OBJECT (account_picker), FOLDER_PICKER_CURRENT_FOLDER);
1136 g_object_ref (*parent);
1140 gtk_widget_destroy (dialog);
1143 g_slice_free (FolderPickerHelper, helper);
1145 while (gtk_events_pending ())
1146 gtk_main_iteration ();
1152 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
1153 TnyFolderStore *suggested_folder,
1154 gchar *suggested_name,
1155 gchar **folder_name,
1156 TnyFolderStore **parent_folder)
1158 gchar *real_suggested_name = NULL;
1160 ModestTnyAccountStore *acc_store;
1161 TnyAccount *account;
1162 gboolean do_free = FALSE;
1164 real_suggested_name = get_next_folder_name ((const gchar *) suggested_name,
1167 /* In hildon 2.2 we always suggest the archive folder as parent */
1168 if (!suggested_folder) {
1169 acc_store = modest_runtime_get_account_store ();
1170 account = modest_tny_account_store_get_mmc_folders_account (acc_store);
1172 suggested_folder = (TnyFolderStore *)
1173 modest_tny_account_get_special_folder (account,
1174 TNY_FOLDER_TYPE_ARCHIVE);
1175 g_object_unref (account);
1180 /* If there is not archive folder then fallback to local folders account */
1181 if (!suggested_folder) {
1183 suggested_folder = (TnyFolderStore *)
1184 modest_tny_account_store_get_local_folders_account (acc_store);
1187 result = modest_platform_run_folder_common_dialog (parent_window,
1189 _HL("ckdg_ti_new_folder"),
1190 _FM("ckdg_fi_new_folder_name"),
1191 real_suggested_name,
1198 g_object_unref (suggested_folder);
1200 g_free(real_suggested_name);
1206 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
1207 TnyFolderStore *parent_folder,
1208 const gchar *suggested_name,
1209 gchar **folder_name)
1211 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
1213 return modest_platform_run_folder_common_dialog (parent_window,
1215 _HL("ckdg_ti_rename_folder"),
1216 _HL("ckdg_fi_rename_name"),
1227 on_destroy_dialog (GtkWidget *dialog)
1229 /* This could happen when the dialogs get programatically
1230 hidden or destroyed (for example when closing the
1231 application while a dialog is being shown) */
1232 if (!GTK_IS_WIDGET (dialog))
1235 gtk_widget_destroy (dialog);
1237 if (gtk_events_pending ())
1238 gtk_main_iteration ();
1242 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
1243 const gchar *message)
1248 dialog = hildon_note_new_confirmation (parent_window, message);
1249 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1250 GTK_WINDOW (dialog), parent_window);
1252 response = gtk_dialog_run (GTK_DIALOG (dialog));
1254 on_destroy_dialog (dialog);
1260 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
1261 const gchar *message,
1262 const gchar *button_accept,
1263 const gchar *button_cancel)
1268 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
1269 button_accept, GTK_RESPONSE_ACCEPT,
1270 button_cancel, GTK_RESPONSE_CANCEL,
1273 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1274 GTK_WINDOW (dialog), parent_window);
1276 response = gtk_dialog_run (GTK_DIALOG (dialog));
1278 on_destroy_dialog (dialog);
1284 modest_platform_run_information_dialog (GtkWindow *parent_window,
1285 const gchar *message,
1290 note = hildon_note_new_information (parent_window, message);
1292 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1293 GTK_WINDOW (note), parent_window);
1296 gtk_dialog_run (GTK_DIALOG (note));
1298 on_destroy_dialog (note);
1300 g_signal_connect_swapped (note,
1302 G_CALLBACK (on_destroy_dialog),
1305 gtk_widget_show_all (note);
1309 typedef struct _ConnectAndWaitData {
1311 GMainLoop *wait_loop;
1312 gboolean has_callback;
1314 } ConnectAndWaitData;
1318 quit_wait_loop (TnyAccount *account,
1319 ConnectAndWaitData *data)
1321 /* Set the has_callback to TRUE (means that the callback was
1322 executed and wake up every code waiting for cond to be
1324 g_mutex_lock (data->mutex);
1325 data->has_callback = TRUE;
1326 if (data->wait_loop)
1327 g_main_loop_quit (data->wait_loop);
1328 g_mutex_unlock (data->mutex);
1332 on_connection_status_changed (TnyAccount *account,
1333 TnyConnectionStatus status,
1336 TnyConnectionStatus conn_status;
1337 ConnectAndWaitData *data;
1339 /* Ignore if reconnecting or disconnected */
1340 conn_status = tny_account_get_connection_status (account);
1341 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
1342 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
1345 /* Remove the handler */
1346 data = (ConnectAndWaitData *) user_data;
1347 g_signal_handler_disconnect (account, data->handler);
1349 /* Quit from wait loop */
1350 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
1354 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
1359 /* Quit from wait loop */
1360 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
1364 modest_platform_connect_and_wait (GtkWindow *parent_window,
1365 TnyAccount *account)
1367 ConnectAndWaitData *data = NULL;
1368 gboolean device_online;
1370 TnyConnectionStatus conn_status;
1371 gboolean user_requested;
1373 device = modest_runtime_get_device();
1374 device_online = tny_device_is_online (device);
1376 /* Whether the connection is user requested or automatically
1377 requested, for example via D-Bus */
1378 user_requested = (parent_window) ? TRUE : FALSE;
1380 /* If there is no account check only the device status */
1385 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1386 NULL, user_requested);
1389 /* Return if the account is already connected */
1390 conn_status = tny_account_get_connection_status (account);
1391 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1394 /* Create the helper */
1395 data = g_slice_new0 (ConnectAndWaitData);
1396 data->mutex = g_mutex_new ();
1397 data->has_callback = FALSE;
1399 /* Connect the device */
1400 if (!device_online) {
1401 /* Track account connection status changes */
1402 data->handler = g_signal_connect (account, "connection-status-changed",
1403 G_CALLBACK (on_connection_status_changed),
1405 /* Try to connect the device */
1406 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
1407 NULL, user_requested);
1409 /* If the device connection failed then exit */
1410 if (!device_online && data->handler)
1413 /* Force a reconnection of the account */
1414 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1415 on_tny_camel_account_set_online_cb, data);
1418 /* Wait until the callback is executed */
1419 g_mutex_lock (data->mutex);
1420 if (!data->has_callback) {
1421 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1422 gdk_threads_leave ();
1423 g_mutex_unlock (data->mutex);
1424 g_main_loop_run (data->wait_loop);
1425 g_mutex_lock (data->mutex);
1426 gdk_threads_enter ();
1428 g_mutex_unlock (data->mutex);
1431 if (g_signal_handler_is_connected (account, data->handler))
1432 g_signal_handler_disconnect (account, data->handler);
1433 g_mutex_free (data->mutex);
1434 g_main_loop_unref (data->wait_loop);
1435 g_slice_free (ConnectAndWaitData, data);
1437 conn_status = tny_account_get_connection_status (account);
1438 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1442 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1444 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1445 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1446 /* This must be a maildir account, which does not require a connection: */
1451 return modest_platform_connect_and_wait (parent_window, account);
1455 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1458 return TRUE; /* Maybe it is something local. */
1460 gboolean result = TRUE;
1461 if (TNY_IS_FOLDER (folder_store)) {
1462 /* Get the folder's parent account: */
1463 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1464 if (account != NULL) {
1465 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1466 g_object_unref (account);
1468 } else if (TNY_IS_ACCOUNT (folder_store)) {
1469 /* Use the folder store as an account: */
1470 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1477 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1481 dialog = modest_hildon2_sort_dialog_new (parent_window);
1488 modest_platform_set_update_interval (guint minutes)
1490 #ifdef MODEST_HAVE_LIBALARM
1492 cookie_t alarm_cookie, *alarm_cookies;
1493 ModestConf *conf = modest_runtime_get_conf ();
1498 GSList *acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1502 modest_account_mgr_free_account_names (acc_names);
1506 /* cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL); */
1508 /* Delete any existing alarm, because we will replace it: */
1509 alarm_cookies = alarmd_event_query (0,0, 0,0, MODEST_ALARMD_APPID);
1510 if (alarm_cookies) {
1511 /* alarmd_event_query returns a zero terminated array */
1512 for (; *alarm_cookies != 0; alarm_cookies++) {
1513 alarmd_event_del (*alarm_cookies);
1515 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1518 /* 0 means no updates: */
1522 /* Register alarm: */
1524 /* Set the interval in alarm_event_t structure: */
1525 alarm_event_t *event = alarm_event_create ();
1526 alarm_event_add_actions (event, 1);
1527 alarm_action_t *action = alarm_event_get_action (event, 0);
1528 alarm_event_set_alarm_appid (event, MODEST_ALARMD_APPID);
1529 event->alarm_time = minutes * 60; /* seconds */
1531 /* Set recurrence every few minutes: */
1532 event->recur_secs = minutes*60;
1533 event->recur_count = -1; /* Means infinite */
1535 /* Specify what should happen when the alarm happens:
1536 * It should call this D-Bus method: */
1538 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1539 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1540 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1541 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1542 action->flags = ALARM_ACTION_WHEN_TRIGGERED | ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1544 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1545 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1546 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1547 * This is why we want to use the Alarm API instead of just g_timeout_add().
1548 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1549 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1551 event->flags = ALARM_EVENT_CONNECTED | ALARM_EVENT_RUN_DELAYED;
1553 alarm_cookie = alarmd_event_add (event);
1556 alarm_event_delete (event);
1558 /* Store the alarm ID in GConf, so we can remove it later:
1559 * This is apparently valid between application instances. */
1560 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1562 if (!alarm_cookie) {
1564 g_warning ("Error setting alarm event. \n");
1568 #endif /* MODEST_HAVE_LIBALARM */
1573 modest_platform_push_email_notification(void)
1575 gboolean screen_on, app_in_foreground;
1577 /* Get the window status */
1578 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1580 screen_on = modest_window_mgr_screen_is_on (modest_runtime_get_window_mgr ());
1582 /* If the screen is on and the app is in the
1583 foreground we don't show anything */
1584 if (!(screen_on && app_in_foreground)) {
1586 modest_platform_play_email_tone ();
1588 /* Activate LED. This must be deactivated by
1589 modest_platform_remove_new_mail_notifications */
1590 #ifdef MODEST_HAVE_MCE
1591 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1595 MCE_ACTIVATE_LED_PATTERN,
1597 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1604 modest_platform_on_new_headers_received (GList *URI_list,
1605 gboolean show_visual)
1607 if (g_list_length (URI_list) == 0)
1610 #ifdef MODEST_HAVE_HILDON_NOTIFY
1611 /* For any other case issue a notification */
1612 HildonNotification *notification;
1613 ModestMsgNotificationData *data;
1616 TnyAccountStore *acc_store;
1617 TnyAccount *account;
1619 data = (ModestMsgNotificationData *) URI_list->data;
1621 /* String is changed in-place. There is no need to
1622 actually dup the data->from string but we just do
1623 it in order not to modify the original contents */
1624 from = g_strdup (data->from);
1625 modest_text_utils_get_display_address (from);
1627 /* Create notification */
1628 notification = hildon_notification_new (from,
1630 "qgn_list_messagin",
1631 MODEST_NOTIFICATION_CATEGORY);
1634 /* Add DBus action */
1635 hildon_notification_add_dbus_action(notification,
1638 MODEST_DBUS_SERVICE,
1641 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1642 G_TYPE_STRING, data->uri,
1645 /* Set the led pattern */
1647 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1648 "time", data->time);
1650 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1652 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1654 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1656 /* Make the notification persistent */
1657 notify_notification_set_hint_byte (NOTIFY_NOTIFICATION (notification),
1658 "persistent", TRUE);
1660 /* Set the number of new notifications */
1661 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1662 "amount", g_list_length (URI_list));
1664 /* Set the account of the headers */
1665 acc_store = (TnyAccountStore *) modest_runtime_get_account_store ();
1666 account = tny_account_store_find_account (acc_store, data->uri);
1668 const gchar *acc_name;
1670 modest_tny_account_get_parent_modest_account_name_for_server_account (account);
1671 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1674 g_object_unref (account);
1677 if (notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL)) {
1678 GSList *notifications_list = NULL;
1680 /* Get previous notifications ids */
1681 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1682 MODEST_CONF_NOTIFICATION_IDS,
1683 MODEST_CONF_VALUE_INT, NULL);
1685 /* Save id in the list */
1686 g_object_get(G_OBJECT (notification), "id", ¬if_id, NULL);
1687 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1689 /* We don't listen for the "closed" signal, because we
1690 don't care about if the notification was removed or
1691 not to store the list in gconf */
1694 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1695 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1697 g_slist_free (notifications_list);
1699 g_warning ("Failed to send notification");
1702 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1706 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1709 #ifdef MODEST_HAVE_MCE
1710 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1714 MCE_DEACTIVATE_LED_PATTERN,
1716 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1722 #ifdef MODEST_HAVE_HILDON_NOTIFY
1723 GSList *notif_list = NULL;
1725 /* Get previous notifications ids */
1726 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1727 MODEST_CONF_NOTIFICATION_IDS,
1728 MODEST_CONF_VALUE_INT, NULL);
1730 while (notif_list) {
1732 NotifyNotification *notif;
1734 /* Nasty HACK to remove the notifications, set the id
1735 of the existing ones and then close them */
1736 notif_id = GPOINTER_TO_INT(notif_list->data);
1737 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1738 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1740 /* Close the notification, note that some ids could be
1741 already invalid, but we don't care because it does
1743 notify_notification_close(notif, NULL);
1744 g_object_unref(notif);
1746 /* Delete the link, it's like going to the next */
1747 notif_list = g_slist_delete_link (notif_list, notif_list);
1751 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1752 notif_list, MODEST_CONF_VALUE_INT, NULL);
1754 g_slist_free (notif_list);
1756 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1762 modest_platform_get_global_settings_dialog ()
1764 return modest_hildon2_global_settings_dialog_new ();
1768 modest_platform_show_help (GtkWindow *parent_window,
1769 const gchar *help_id)
1775 modest_platform_show_search_messages (GtkWindow *parent_window)
1777 osso_return_t result = OSSO_ERROR;
1779 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1780 "osso_global_search",
1781 "search_email", NULL, DBUS_TYPE_INVALID);
1783 if (result != OSSO_OK) {
1784 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1789 modest_platform_show_addressbook (GtkWindow *parent_window)
1791 osso_return_t result = OSSO_ERROR;
1793 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1795 "top_application", NULL, DBUS_TYPE_INVALID);
1797 if (result != OSSO_OK) {
1798 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1803 modest_platform_create_folder_view_full (TnyFolderStoreQuery *query, gboolean do_refresh)
1805 GtkWidget *widget = modest_folder_view_new_full (query, do_refresh);
1807 /* Show one account by default */
1808 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1809 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1815 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1817 return modest_platform_create_folder_view_full (query, TRUE);
1821 banner_finish (gpointer data, GObject *object)
1823 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1824 modest_window_mgr_unregister_banner (mgr);
1825 g_object_unref (mgr);
1829 modest_platform_information_banner (GtkWidget *parent,
1830 const gchar *icon_name,
1833 GtkWidget *banner_parent = NULL;
1834 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1836 if (modest_window_mgr_get_num_windows (mgr) == 0)
1839 if (parent && GTK_IS_WINDOW (parent)) {
1840 /* If the window is the active one then show the
1841 banner on top of this window */
1842 if (gtk_window_is_active (GTK_WINDOW (parent)))
1843 banner_parent = parent;
1844 /* If the window is not the topmost but it's visible
1845 (it's minimized for example) then show the banner
1847 else if (GTK_WIDGET_VISIBLE (parent))
1848 banner_parent = NULL;
1849 /* If the window is hidden (like the main window when
1850 running in the background) then do not show
1856 modest_platform_system_banner (banner_parent, icon_name, text);
1860 modest_platform_system_banner (GtkWidget *parent,
1861 const gchar *icon_name,
1864 GtkWidget *banner = NULL;
1865 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1867 if (parent && GTK_IS_WINDOW (parent)) {
1868 if (!gtk_window_is_active (GTK_WINDOW (parent)))
1872 banner = hildon_banner_show_information (parent, icon_name, text);
1874 modest_window_mgr_register_banner (mgr);
1876 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1880 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1881 const gchar *icon_name,
1887 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1890 banner = hildon_banner_show_information (parent, icon_name, text);
1891 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1895 modest_platform_animation_banner (GtkWidget *parent,
1896 const gchar *animation_name,
1899 GtkWidget *inf_note = NULL;
1901 g_return_val_if_fail (text != NULL, NULL);
1903 if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0)
1906 /* If the parent is not visible then do not show */
1907 if (parent && !GTK_WIDGET_VISIBLE (parent))
1910 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1918 TnyAccount *account;
1921 } CheckAccountIdleData;
1923 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1926 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1928 gboolean stop_trying = FALSE;
1929 g_return_val_if_fail (data && data->account, FALSE);
1931 if (data && data->account &&
1932 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1933 * after which the account is likely to be usable, or never likely to be usable soon: */
1934 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1936 data->is_online = TRUE;
1940 /* Give up if we have tried too many times: */
1941 if (data->count_tries >= NUMBER_OF_TRIES) {
1944 /* Wait for another timeout: */
1945 ++(data->count_tries);
1950 /* Allow the function that requested this idle callback to continue: */
1952 g_main_loop_quit (data->loop);
1955 g_object_unref (data->account);
1957 return FALSE; /* Don't call this again. */
1959 return TRUE; /* Call this timeout callback again. */
1963 /* Return TRUE immediately if the account is already online,
1964 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1965 * soon as the account is online, or FALSE if the account does
1966 * not become online in the NUMBER_OF_TRIES seconds.
1967 * This is useful when the D-Bus method was run immediately after
1968 * the application was started (when using D-Bus activation),
1969 * because the account usually takes a short time to go online.
1970 * The return value is maybe not very useful.
1973 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1977 g_return_val_if_fail (account, FALSE);
1979 if (!tny_device_is_online (modest_runtime_get_device())) {
1980 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1984 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1985 * so we avoid wait unnecessarily: */
1986 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1989 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1990 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1991 * we want to avoid. */
1992 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1995 /* This blocks on the result: */
1996 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1997 data->is_online = FALSE;
1998 data->account = account;
1999 g_object_ref (data->account);
2000 data->count_tries = 0;
2002 GMainContext *context = NULL; /* g_main_context_new (); */
2003 data->loop = g_main_loop_new (context, FALSE /* not running */);
2005 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
2007 /* This main loop will run until the idle handler has stopped it: */
2008 g_main_loop_run (data->loop);
2010 g_main_loop_unref (data->loop);
2011 /* g_main_context_unref (context); */
2013 is_online = data->is_online;
2014 g_slice_free (CheckAccountIdleData, data);
2022 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
2024 /* GTK_RESPONSE_HELP means we need to show the certificate */
2025 if (response_id == GTK_RESPONSE_APPLY) {
2029 /* Do not close the dialog */
2030 g_signal_stop_emission_by_name (dialog, "response");
2032 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
2033 note = hildon_note_new_information (NULL, msg);
2034 gtk_dialog_run (GTK_DIALOG(note));
2035 gtk_widget_destroy (note);
2041 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
2042 const gchar *certificate)
2047 HildonWindowStack *stack;
2049 stack = hildon_window_stack_get_default ();
2050 win = MODEST_WINDOW (hildon_window_stack_peek (stack));
2053 g_debug ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
2058 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
2061 /* We use GTK_RESPONSE_APPLY because we want the button in the
2062 middle of OK and CANCEL the same as the browser does for
2063 example. With GTK_RESPONSE_HELP the view button is aligned
2064 to the left while the other two to the right */
2065 note = hildon_note_new_confirmation_add_buttons (
2068 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
2069 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
2070 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
2073 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2074 (GtkWindow *) note, (GtkWindow *) win);
2076 g_signal_connect (G_OBJECT(note), "response",
2077 G_CALLBACK(on_cert_dialog_response),
2078 (gpointer) certificate);
2080 response = gtk_dialog_run(GTK_DIALOG(note));
2082 on_destroy_dialog (note);
2085 return response == GTK_RESPONSE_OK;
2089 modest_platform_run_alert_dialog (const gchar* prompt,
2090 gboolean is_question)
2092 ModestWindow *top_win;
2093 HildonWindowStack *stack;
2095 stack = hildon_window_stack_get_default ();
2096 top_win = MODEST_WINDOW (hildon_window_stack_peek (stack));
2099 g_debug ("%s: don't show dialogs if there's no window shown; assuming 'Cancel'",
2104 gboolean retval = TRUE;
2106 /* The Tinymail documentation says that we should show Yes and No buttons,
2107 * when it is a question.
2108 * Obviously, we need tinymail to use more specific error codes instead,
2109 * so we know what buttons to show. */
2110 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (top_win),
2112 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2113 GTK_WINDOW (dialog), GTK_WINDOW (top_win));
2115 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
2116 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
2118 on_destroy_dialog (dialog);
2120 /* Just show the error text and use the default response: */
2121 modest_platform_run_information_dialog (GTK_WINDOW (top_win),
2129 GtkWindow *parent_window;
2130 ModestConnectedPerformer callback;
2131 TnyAccount *account;
2138 on_went_online_info_free (OnWentOnlineInfo *info)
2140 /* And if we cleanup, we DO cleanup :-) */
2143 g_object_unref (info->device);
2146 if (info->parent_window)
2147 g_object_unref (info->parent_window);
2149 g_object_unref (info->account);
2151 g_slice_free (OnWentOnlineInfo, info);
2153 /* We're done ... */
2159 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
2161 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2163 /* Now it's really time to callback to the caller. If going online didn't succeed,
2164 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
2165 * canceled will be set. Etcetera etcetera. */
2167 if (info->callback) {
2168 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2171 /* This is our last call, we must cleanup here if we didn't yet do that */
2172 on_went_online_info_free (info);
2179 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
2181 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
2182 info->iap = g_strdup (iap_id);
2184 if (canceled || err || !info->account) {
2186 /* If there's a problem or if there's no account (then that's it for us, we callback
2187 * the caller's callback now. He'll have to handle err or canceled, of course.
2188 * We are not really online, as the account is not really online here ... */
2190 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
2191 * this info. We don't cleanup err, Tinymail does that! */
2193 if (info->callback) {
2195 /* info->account can be NULL here, this means that the user did not
2196 * provide a nice account instance. We'll assume that the user knows
2197 * what he's doing and is happy with just the device going online.
2199 * We can't do magic, we don't know what account the user wants to
2200 * see going online. So just the device goes online, end of story */
2202 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
2205 } else if (info->account) {
2207 /* If there's no problem and if we have an account, we'll put the account
2208 * online too. When done, the callback of bringing the account online
2209 * will callback the caller's callback. This is the most normal case. */
2211 info->device = TNY_DEVICE (g_object_ref (device));
2213 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
2214 on_account_went_online, info);
2216 /* The on_account_went_online cb frees up the info, go look if you
2217 * don't believe me! (so we return here) */
2222 /* We cleanup if we are not bringing the account online too */
2223 on_went_online_info_free (info);
2229 modest_platform_connect_and_perform (GtkWindow *parent_window,
2231 TnyAccount *account,
2232 ModestConnectedPerformer callback,
2235 gboolean device_online;
2237 TnyConnectionStatus conn_status;
2238 OnWentOnlineInfo *info;
2240 device = modest_runtime_get_device();
2241 device_online = tny_device_is_online (device);
2243 /* If there is no account check only the device status */
2246 if (device_online) {
2248 /* We promise to instantly perform the callback, so ... */
2250 callback (FALSE, NULL, parent_window, account, user_data);
2255 info = g_slice_new0 (OnWentOnlineInfo);
2258 info->device = NULL;
2259 info->account = NULL;
2262 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2264 info->parent_window = NULL;
2265 info->user_data = user_data;
2266 info->callback = callback;
2268 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2269 force, on_conic_device_went_online,
2272 /* We'll cleanup in on_conic_device_went_online */
2275 /* The other code has no more reason to run. This is all that we can do for the
2276 * caller (he should have given us a nice and clean account instance!). We
2277 * can't do magic, we don't know what account he intends to bring online. So
2278 * we'll just bring the device online (and await his false bug report). */
2284 /* Return if the account is already connected */
2286 conn_status = tny_account_get_connection_status (account);
2287 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
2289 /* We promise to instantly perform the callback, so ... */
2291 callback (FALSE, NULL, parent_window, account, user_data);
2297 /* Else, we are in a state that requires that we go online before we
2298 * call the caller's callback. */
2300 info = g_slice_new0 (OnWentOnlineInfo);
2302 info->device = NULL;
2304 info->account = TNY_ACCOUNT (g_object_ref (account));
2307 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
2309 info->parent_window = NULL;
2311 /* So we'll put the callback away for later ... */
2313 info->user_data = user_data;
2314 info->callback = callback;
2316 if (!device_online) {
2318 /* If also the device is offline, then we connect both the device
2319 * and the account */
2321 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
2322 force, on_conic_device_went_online,
2327 /* If the device is online, we'll just connect the account */
2329 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
2330 on_account_went_online, info);
2333 /* The info gets freed by on_account_went_online or on_conic_device_went_online
2334 * in both situations, go look if you don't believe me! */
2340 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
2342 TnyFolderStore *folder_store,
2343 ModestConnectedPerformer callback,
2346 TnyAccount *account = NULL;
2348 if (!folder_store ||
2349 (TNY_IS_MERGE_FOLDER (folder_store) &&
2350 (tny_folder_get_folder_type (TNY_FOLDER(folder_store)) == TNY_FOLDER_TYPE_OUTBOX))) {
2352 /* We promise to instantly perform the callback, so ... */
2354 GError *error = NULL;
2355 g_set_error (&error, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
2356 "Unable to move or not found folder");
2357 callback (FALSE, error, parent_window, NULL, user_data);
2358 g_error_free (error);
2362 } else if (TNY_IS_FOLDER (folder_store)) {
2363 /* Get the folder's parent account: */
2364 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2365 } else if (TNY_IS_ACCOUNT (folder_store)) {
2366 /* Use the folder store as an account: */
2367 account = TNY_ACCOUNT (g_object_ref (folder_store));
2370 if (account && (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE)) {
2371 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
2372 /* No need to connect a local account */
2374 callback (FALSE, NULL, parent_window, account, user_data);
2379 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
2383 g_object_unref (account);
2387 src_account_connect_performer (gboolean canceled,
2389 GtkWindow *parent_window,
2390 TnyAccount *src_account,
2393 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
2395 if (canceled || err) {
2396 /* If there was any error call the user callback */
2397 info->callback (canceled, err, parent_window, src_account, info->data);
2399 /* Connect the destination account */
2400 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
2401 TNY_FOLDER_STORE (info->dst_account),
2402 info->callback, info->data);
2405 /* Free the info object */
2406 g_object_unref (info->dst_account);
2407 g_slice_free (DoubleConnectionInfo, info);
2412 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
2414 TnyFolderStore *folder_store,
2415 DoubleConnectionInfo *connect_info)
2417 modest_platform_connect_if_remote_and_perform(parent_window,
2420 src_account_connect_performer,
2425 modest_platform_get_account_settings_wizard (void)
2427 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2429 return GTK_WIDGET (dialog);
2433 modest_platform_get_current_connection (void)
2435 TnyDevice *device = NULL;
2436 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2438 device = modest_runtime_get_device ();
2440 if (!tny_device_is_online (device))
2441 return MODEST_CONNECTED_VIA_ANY;
2443 #ifdef MODEST_HAVE_CONIC
2445 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2447 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2448 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2449 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2451 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2452 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2453 !strcmp (bearer_type, "WIMAX")) {
2454 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2456 retval = MODEST_CONNECTED_VIA_ANY;
2459 g_object_unref (iap);
2462 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2463 #endif /* MODEST_HAVE_CONIC */
2470 modest_platform_check_memory_low (ModestWindow *win,
2475 /* are we in low memory state? */
2476 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2478 if (win && lowmem && visuals)
2479 modest_platform_run_information_dialog (
2481 _KR("memr_ib_operation_disabled"),
2485 g_debug ("%s: low memory reached. disallowing some operations",
2492 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2498 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2501 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2502 GTK_WINDOW (dialog),
2504 gtk_widget_show_all (dialog);
2506 g_signal_connect_swapped (dialog, "response",
2507 G_CALLBACK (gtk_widget_destroy),
2511 typedef struct _HeaderDetailsGetSizeInfo {
2515 } HeaderDetailsGetSizeInfo;
2518 header_details_dialog_destroy (gpointer userdata,
2521 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) userdata;
2523 info->dialog = NULL;
2527 idle_get_mime_part_size_cb (gpointer userdata)
2529 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) userdata;
2530 gdk_threads_enter ();
2532 if (info->dialog && GTK_WIDGET_VISIBLE (info->dialog)) {
2533 modest_details_dialog_set_message_size (MODEST_DETAILS_DIALOG (info->dialog),
2538 g_object_weak_unref (G_OBJECT (info->dialog), header_details_dialog_destroy, info);
2539 info->dialog = NULL;
2541 g_object_unref (info->part);
2542 g_slice_free (HeaderDetailsGetSizeInfo, info);
2544 gdk_threads_leave ();
2550 get_mime_part_size_thread (gpointer thr_user_data)
2552 HeaderDetailsGetSizeInfo *info = (HeaderDetailsGetSizeInfo *) thr_user_data;
2554 TnyStream *count_stream;
2556 count_stream = modest_count_stream_new ();
2557 result = tny_mime_part_decode_to_stream (info->part, count_stream, NULL);
2558 info->total = modest_count_stream_get_count(MODEST_COUNT_STREAM (count_stream));
2559 if (info->total == 0) {
2560 modest_count_stream_reset_count(MODEST_COUNT_STREAM (count_stream));
2561 result = tny_mime_part_write_to_stream (info->part, count_stream, NULL);
2562 info->total = modest_count_stream_get_count(MODEST_COUNT_STREAM (count_stream));
2565 /* if there was an error, don't set the size (this is pretty uncommon) */
2567 g_warning ("%s: error while writing mime part to stream\n", __FUNCTION__);
2569 g_idle_add (idle_get_mime_part_size_cb, info);
2575 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2577 gboolean async_get_size,
2583 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header, !async_get_size);
2585 if (async_get_size && msg && TNY_IS_MSG (msg)) {
2586 HeaderDetailsGetSizeInfo *info;
2587 info = g_slice_new (HeaderDetailsGetSizeInfo);
2588 info->dialog = dialog;
2590 info->part = TNY_MIME_PART (g_object_ref (msg));
2592 g_object_weak_ref (G_OBJECT (dialog), header_details_dialog_destroy, info);
2593 g_thread_create (get_mime_part_size_thread, info, FALSE, NULL);
2597 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2598 GTK_WINDOW (dialog),
2600 gtk_widget_show_all (dialog);
2602 g_signal_connect_swapped (dialog, "response",
2603 G_CALLBACK (gtk_widget_destroy),
2608 modest_platform_get_osso_context (void)
2610 return modest_maemo_utils_get_osso_context ();
2614 convert_volume_to_db (int linear_volume)
2616 gfloat linear_converted = linear_volume / 100.0;
2617 gfloat db_vol = 0.0;
2619 db_vol = 20 * log10 (linear_converted);
2620 if (isinf (db_vol) != 0)
2627 modest_platform_play_email_tone (void)
2630 gint mail_volume_int;
2632 ca_proplist *pl = NULL;
2635 #ifdef MODEST_USE_PROFILE
2636 gchar *active_profile;
2639 active_profile = profile_get_profile ();
2640 mail_tone = profile_get_value (active_profile, PROFILE_MAIL_TONE);
2641 mail_volume = profile_get_value (active_profile, PROFILE_MAIL_VOLUME);
2642 mail_volume_int = profile_parse_int (mail_volume);
2643 g_free (mail_volume);
2644 g_free (active_profile);
2646 mail_tone = g_strdup (MAIL_TONE);
2647 mail_volume_int = 100;
2650 if (mail_tone && !strstr (mail_tone, "/")) {
2653 tmp = g_strconcat ("/usr/share/sounds", mail_tone, NULL);
2658 if (mail_volume_int > 0) {
2660 if (ca_con == NULL) {
2661 if ((ret = ca_context_create (&ca_con)) != CA_SUCCESS) {
2662 g_warning("ca_context_create: %s\n", ca_strerror(ret));
2666 if ((ret = ca_context_set_driver (ca_con, "gstreamer")) != CA_SUCCESS) {
2667 g_warning ("ca_context_set_driver: %s\n", ca_strerror (ret));
2673 if (!ca_con_opened) {
2674 if ((ret = ca_context_open(ca_con)) != CA_SUCCESS) {
2675 g_warning("ca_context_open: %s\n", ca_strerror(ret));
2678 ca_con_opened = TRUE;
2682 ca_proplist_create(&pl);
2683 ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, mail_tone);
2684 db_volume = convert_volume_to_db (mail_volume_int);
2685 ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", db_volume);
2687 ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL);
2688 g_debug("ca_context_play_full (vol %f): %s\n", (gfloat) mail_volume_int, ca_strerror(ret));
2690 ca_proplist_destroy(pl);
2696 #define MOVE_TO_DIALOG_FOLDER_VIEW "folder-view"
2697 #define MOVE_TO_DIALOG_BACK_BUTTON "back-button"
2698 #define MOVE_TO_DIALOG_ACTION_BUTTON "action-button"
2699 #define MOVE_TO_DIALOG_SHOWING_FOLDERS "showing-folders"
2700 #define MOVE_TO_DIALOG_PANNABLE "pannable"
2701 #define MOVE_TO_FOLDER_SEPARATOR "/"
2704 translate_path (gchar **path)
2709 gboolean add_separator;
2711 parts = g_strsplit (*path, MOVE_TO_FOLDER_SEPARATOR, 0);
2715 output = g_string_new ("");
2716 add_separator = FALSE;
2718 while (*current != NULL) {
2719 TnyFolderType folder_type;
2722 if (add_separator) {
2723 output = g_string_append (output, MOVE_TO_FOLDER_SEPARATOR);
2725 add_separator = TRUE;
2728 downcase = g_ascii_strdown (*current, -1);
2729 folder_type = modest_local_folder_info_get_type (downcase);
2730 if (strcmp (downcase, "inbox") == 0) {
2731 output = g_string_append (output, _("mcen_me_folder_inbox"));
2732 } else if (folder_type == TNY_FOLDER_TYPE_ARCHIVE ||
2733 folder_type == TNY_FOLDER_TYPE_DRAFTS ||
2734 folder_type == TNY_FOLDER_TYPE_SENT ||
2735 folder_type == TNY_FOLDER_TYPE_OUTBOX) {
2736 output = g_string_append (output, modest_local_folder_info_get_type_display_name (folder_type));
2738 output = g_string_append (output, *current);
2746 *path = g_string_free (output, FALSE);
2750 move_to_dialog_set_selected_folder_store (GtkWidget *dialog,
2751 TnyFolderStore *folder_store)
2753 GtkWidget *action_button;
2754 GtkWidget *image = NULL;
2755 TnyAccount *account;
2756 gchar *account_name = NULL, *short_name = NULL;
2758 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2760 /* Get account name */
2761 if (TNY_IS_FOLDER (folder_store))
2762 account = tny_folder_get_account (TNY_FOLDER (folder_store));
2764 account = g_object_ref (folder_store);
2766 if (modest_tny_account_is_virtual_local_folders (account))
2767 account_name = modest_conf_get_string (modest_runtime_get_conf(),
2768 MODEST_CONF_DEVICE_NAME, NULL);
2771 account_name = g_strdup (tny_account_get_name (account));
2773 g_object_unref (account);
2775 /* Set title of button: account or folder name */
2776 if (TNY_IS_FOLDER (folder_store))
2777 short_name = folder_store_get_display_name (folder_store);
2779 short_name = g_strdup (account_name);
2781 hildon_button_set_title (HILDON_BUTTON (action_button), short_name);
2783 /* Set value of button, folder full name */
2784 if (TNY_IS_CAMEL_FOLDER (folder_store)) {
2785 const gchar *camel_full_name;
2786 gchar *last_slash, *full_name;
2788 camel_full_name = tny_camel_folder_get_full_name (TNY_CAMEL_FOLDER (folder_store));
2789 last_slash = g_strrstr (camel_full_name, "/");
2791 gchar *prefix = g_strndup (camel_full_name, last_slash - camel_full_name + 1);
2792 full_name = g_strconcat (account_name, MOVE_TO_FOLDER_SEPARATOR, prefix, short_name, NULL);
2795 full_name = g_strconcat (account_name, MOVE_TO_FOLDER_SEPARATOR,
2799 translate_path (&full_name);
2800 hildon_button_set_value (HILDON_BUTTON (action_button), full_name);
2803 g_free (account_name);
2804 g_free (short_name);
2806 /* Set image for the button */
2807 image = get_image_for_folder_store (folder_store, MODEST_ICON_SIZE_BIG);
2809 hildon_button_set_image (HILDON_BUTTON (action_button), image);
2813 move_to_dialog_show_accounts (GtkWidget *dialog)
2815 GtkWidget *back_button;
2816 GtkWidget *folder_view;
2817 GtkWidget *pannable;
2818 GtkWidget *action_button;
2820 back_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2821 action_button = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2822 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2823 pannable = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2825 gtk_widget_set_sensitive (back_button, FALSE);
2826 gtk_widget_set_sensitive (action_button, FALSE);
2828 /* Need to set this here, otherwise callbacks called because
2829 of filtering won't perform correctly */
2830 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS, GINT_TO_POINTER (FALSE));
2832 /* Reset action button */
2833 hildon_button_set_title (HILDON_BUTTON (action_button), NULL);
2834 hildon_button_set_value (HILDON_BUTTON (action_button), NULL);
2835 hildon_button_set_image (HILDON_BUTTON (action_button), NULL);
2837 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view), NULL);
2838 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), TRUE);
2839 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
2840 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
2841 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2842 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
2843 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2844 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view),
2845 MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
2846 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2847 MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2848 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2852 move_to_dialog_show_folders (GtkWidget *dialog, TnyFolderStore *folder_store)
2854 GtkWidget *back_button;
2855 GtkWidget *folder_view;
2856 TnyAccount *account;
2857 const gchar *account_id;
2858 GtkWidget *pannable;
2859 GtkWidget *action_button;
2862 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON));
2864 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON));
2866 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2868 GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE));
2870 gtk_widget_set_sensitive (back_button, TRUE);
2871 gtk_widget_set_sensitive (action_button, TRUE);
2873 /* Need to set this here, otherwise callbacks called because
2874 of filtering won't perform correctly */
2875 g_object_set_data (G_OBJECT (dialog),
2876 MOVE_TO_DIALOG_SHOWING_FOLDERS,
2877 GINT_TO_POINTER (TRUE));
2879 account = TNY_ACCOUNT (folder_store);
2880 if (modest_tny_account_is_virtual_local_folders (account)) {
2881 account_id = tny_account_get_id (account);
2882 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2883 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2884 } else if (modest_tny_account_is_memory_card_account (account)) {
2885 account_id = tny_account_get_id (account);
2886 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2887 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2889 account_id = tny_account_get_id (account);
2890 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2891 MODEST_FOLDER_VIEW_FILTER_HIDE_LOCAL_FOLDERS);
2892 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view),
2893 MODEST_FOLDER_VIEW_FILTER_HIDE_MCC_FOLDERS);
2896 move_to_dialog_set_selected_folder_store (dialog, folder_store);
2897 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (folder_view),
2900 modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (folder_view), FALSE);
2901 modest_folder_view_set_style (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
2902 modest_folder_view_set_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_ACCOUNTS);
2903 modest_folder_view_unset_filter (MODEST_FOLDER_VIEW (folder_view), MODEST_FOLDER_VIEW_FILTER_HIDE_FOLDERS);
2904 hildon_pannable_area_jump_to (HILDON_PANNABLE_AREA (pannable), 0, 0);
2908 on_move_to_dialog_back_clicked (GtkButton *button,
2911 GtkWidget *dialog = (GtkWidget *) userdata;
2913 /* Back to show accounts */
2914 move_to_dialog_show_accounts (dialog);
2918 on_move_to_dialog_row_activated (GtkTreeView *tree_view,
2920 GtkTreeViewColumn *column,
2923 TnyFolderStore *selected = NULL;
2925 GtkWidget *folder_view;
2926 gboolean showing_folders;
2928 dialog = (GtkWidget *) user_data;
2929 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog),
2930 MOVE_TO_DIALOG_SHOWING_FOLDERS));
2932 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog),
2933 MOVE_TO_DIALOG_FOLDER_VIEW));
2935 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2939 if (!showing_folders) {
2940 gboolean valid = TRUE;
2942 if (TNY_IS_ACCOUNT (selected) &&
2943 modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (selected))) {
2944 ModestProtocolType protocol_type;
2946 protocol_type = modest_tny_account_get_protocol_type (TNY_ACCOUNT (selected));
2947 valid = !modest_protocol_registry_protocol_type_has_tag
2948 (modest_runtime_get_protocol_registry (),
2950 MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
2953 move_to_dialog_show_folders (dialog, selected);
2955 move_to_dialog_set_selected_folder_store (dialog, selected);
2957 g_object_unref (selected);
2961 on_move_to_dialog_selection_changed (GtkTreeSelection *selection,
2964 gboolean showing_folders;
2967 dialog = (GtkWidget *) user_data;
2968 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2969 if (showing_folders) {
2970 TnyFolderStore *selected;
2971 GtkWidget *folder_view;
2973 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2974 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2977 move_to_dialog_set_selected_folder_store (dialog, selected);
2978 g_object_unref (selected);
2984 on_move_to_dialog_action_clicked (GtkButton *selection,
2988 gboolean showing_folders;
2990 dialog = (GtkWidget *) user_data;
2991 showing_folders = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_SHOWING_FOLDERS));
2992 if (showing_folders) {
2993 TnyFolderStore *selected;
2994 GtkWidget *folder_view;
2996 folder_view = GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW));
2997 selected = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3000 /* It's not possible to select root folders as
3001 targets unless they're the local account or
3002 the memory card account */
3003 if ((TNY_IS_FOLDER (selected) && !TNY_IS_MERGE_FOLDER (selected)) ||
3004 (TNY_IS_ACCOUNT (selected) &&
3005 (modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (selected)) ||
3006 modest_tny_account_is_memory_card_account (TNY_ACCOUNT (selected)))))
3007 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
3008 g_object_unref (selected);
3014 move_to_dialog_activity_changed (ModestFolderView *folder_view, gboolean activity, GtkDialog *dialog)
3016 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (dialog), activity?1:0);
3020 modest_platform_create_move_to_dialog (GtkWindow *parent_window,
3021 GtkWidget **folder_view)
3023 GtkWidget *dialog, *folder_view_container;
3025 GtkWidget *buttons_hbox;
3026 GtkWidget *back_button;
3027 GdkPixbuf *back_pixbuf;
3028 GtkWidget *top_vbox;
3029 GtkWidget *action_button;
3030 GtkTreeSelection *selection;
3032 /* Create dialog. We cannot use a touch selector because we
3033 need to use here the folder view widget directly */
3034 dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3035 GTK_WINDOW (parent_window),
3036 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR |
3037 GTK_DIALOG_DESTROY_WITH_PARENT,
3038 _HL("wdgt_bd_new"), MODEST_GTK_RESPONSE_NEW_FOLDER,
3041 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
3042 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_NONE);
3043 top_vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_HALF);
3045 /* Create folder view */
3046 *folder_view = modest_platform_create_folder_view_full (NULL, FALSE);
3047 g_signal_connect (G_OBJECT (*folder_view), "activity-changed", G_CALLBACK (move_to_dialog_activity_changed),
3050 modest_folder_view_set_cell_style (MODEST_FOLDER_VIEW (*folder_view),
3051 MODEST_FOLDER_VIEW_CELL_STYLE_COMPACT);
3052 modest_folder_view_show_message_count (MODEST_FOLDER_VIEW (*folder_view),
3054 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (*folder_view),
3055 (TnyAccountStore *) modest_runtime_get_account_store ());
3057 buttons_hbox = gtk_hbox_new (FALSE, MODEST_MARGIN_HALF);
3058 back_button = gtk_button_new ();
3059 back_pixbuf = modest_platform_get_icon (_FM("filemanager_folder_up"), MODEST_ICON_SIZE_BIG);
3061 gtk_button_set_image (GTK_BUTTON (back_button), gtk_image_new_from_pixbuf (back_pixbuf));
3062 g_object_unref (back_pixbuf);
3065 action_button = hildon_button_new (HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT,
3066 HILDON_BUTTON_ARRANGEMENT_VERTICAL);
3067 gtk_button_set_alignment (GTK_BUTTON (action_button), 0.0, 0.5);
3069 gtk_box_pack_start (GTK_BOX (buttons_hbox), back_button, FALSE, FALSE, 0);
3070 gtk_box_pack_start (GTK_BOX (buttons_hbox), action_button, TRUE, TRUE, 0);
3071 gtk_widget_set_sensitive (GTK_WIDGET (back_button), FALSE);
3072 gtk_widget_set_sensitive (GTK_WIDGET (action_button), FALSE);
3073 gtk_box_pack_start (GTK_BOX (top_vbox), buttons_hbox, FALSE, FALSE, 0);
3075 /* Create pannable and add it to the dialog */
3076 folder_view_container = hildon_pannable_area_new ();
3077 gtk_container_add (GTK_CONTAINER (folder_view_container), *folder_view);
3078 gtk_box_pack_start (GTK_BOX (top_vbox), folder_view_container, TRUE, TRUE, 0);
3080 gtk_container_add (GTK_CONTAINER (align), top_vbox);
3081 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), align, TRUE, TRUE, 0);
3083 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3085 gtk_widget_show (GTK_DIALOG (dialog)->vbox);
3086 gtk_widget_show (folder_view_container);
3087 gtk_widget_show (align);
3088 gtk_widget_show (top_vbox);
3089 gtk_widget_show (*folder_view);
3090 gtk_widget_show_all (back_button);
3091 gtk_widget_show (action_button);
3092 gtk_widget_show (buttons_hbox);
3093 gtk_widget_show (dialog);
3095 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_FOLDER_VIEW, *folder_view);
3096 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_BACK_BUTTON, back_button);
3097 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_ACTION_BUTTON, action_button);
3098 g_object_set_data (G_OBJECT (dialog), MOVE_TO_DIALOG_PANNABLE, folder_view_container);
3100 /* Simulate the behaviour of a HildonPickerDialog by emitting
3101 a response when a folder is selected */
3102 g_signal_connect (*folder_view, "row-activated",
3103 G_CALLBACK (on_move_to_dialog_row_activated),
3106 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (*folder_view));
3107 g_signal_connect (selection, "changed",
3108 G_CALLBACK (on_move_to_dialog_selection_changed),
3111 g_signal_connect (action_button, "clicked",
3112 G_CALLBACK (on_move_to_dialog_action_clicked),
3115 g_signal_connect (back_button, "clicked",
3116 G_CALLBACK (on_move_to_dialog_back_clicked),
3119 move_to_dialog_show_accounts (dialog);
3125 modest_platform_get_list_to_move (ModestWindow *window)
3127 TnyList *list = NULL;
3129 if (MODEST_IS_HEADER_WINDOW (window)) {
3130 ModestHeaderView *header_view;
3132 header_view = modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window));
3133 list = modest_header_view_get_selected_headers (header_view);
3134 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3135 ModestFolderView *folder_view;
3136 TnyFolderStore *selected_folder;
3138 list = TNY_LIST (tny_simple_list_new ());
3139 folder_view = modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window));
3140 selected_folder = modest_folder_view_get_selected (folder_view);
3141 if (selected_folder) {
3142 tny_list_prepend (list, G_OBJECT (selected_folder));
3143 g_object_unref (selected_folder);
3146 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3149 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
3151 list = TNY_LIST (tny_simple_list_new ());
3152 tny_list_prepend (list, G_OBJECT (header));
3153 g_object_unref (header);
3156 g_return_val_if_reached (NULL);