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>
32 #include <modest-platform.h>
33 #include <modest-runtime.h>
34 #include <modest-main-window.h>
35 #include <modest-header-view.h>
36 #include "modest-hildon2-global-settings-dialog.h"
37 #include "modest-widget-memory.h"
38 #include <modest-hildon-includes.h>
39 #include <modest-maemo-utils.h>
40 #include <dbus_api/modest-dbus-callbacks.h>
41 #include <modest-osso-autosave-callbacks.h>
43 #include <tny-maemo-conic-device.h>
44 #include <tny-simple-list.h>
45 #include <tny-folder.h>
46 #include <gtk/gtkicontheme.h>
47 #include <gtk/gtkmenuitem.h>
48 #include <gtk/gtkmain.h>
49 #include <modest-text-utils.h>
50 #include "modest-tny-folder.h"
51 #include "modest-tny-account.h"
53 #include <libgnomevfs/gnome-vfs-mime-utils.h>
54 #include <modest-account-settings-dialog.h>
55 #include <modest-easysetup-wizard-dialog.h>
56 #include "modest-hildon2-sort-dialog.h"
57 #include <hildon/hildon-sound.h>
59 #include "hildon2/modest-hildon2-details-dialog.h"
60 #include <modest-datetime-formatter.h>
62 #ifdef MODEST_HAVE_MCE
63 #include <mce/dbus-names.h>
64 #endif /*MODEST_HAVE_MCE*/
66 #ifdef MODEST_HAVE_ABOOK
67 #include <libosso-abook/osso-abook.h>
68 #endif /*MODEST_HAVE_ABOOK*/
70 #ifdef MODEST_HAVE_LIBALARM
71 #include <alarmd/libalarm.h> /* For alarm_event_add(), etc. */
72 #endif /*MODEST_HAVE_LIBALARM*/
75 #define HILDON_OSSO_URI_ACTION "uri-action"
76 #define URI_ACTION_COPY "copy:"
77 #define MODEST_NEW_MAIL_SOUND_FILE "/usr/share/sounds/ui-new_email.wav"
78 #define MODEST_NEW_MAIL_LIGHTING_PATTERN "PatternCommunicationEmail"
81 on_modest_conf_update_interval_changed (ModestConf* self,
83 ModestConfEvent event,
84 ModestConfNotificationId id,
87 g_return_if_fail (key);
89 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
90 const guint update_interval_minutes =
91 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
92 modest_platform_set_update_interval (update_interval_minutes);
99 check_required_files (void)
101 FILE *mcc_file = modest_maemo_open_mcc_mapping_file ();
103 g_printerr ("modest: check for mcc file failed\n");
108 if (access(MODEST_PROVIDER_DATA_FILE, R_OK) != 0 &&
109 access(MODEST_MAEMO_PROVIDER_DATA_FILE, R_OK) != 0) {
110 g_printerr ("modest: cannot find providers data\n");
118 /* the gpointer here is the osso_context. */
120 modest_platform_init (int argc, char *argv[])
122 osso_context_t *osso_context;
124 osso_hw_state_t hw_state = { 0 };
128 if (!check_required_files ()) {
129 g_printerr ("modest: missing required files\n");
133 osso_context = osso_initialize(PACKAGE,PACKAGE_VERSION,
136 g_printerr ("modest: failed to acquire osso context\n");
139 modest_maemo_utils_set_osso_context (osso_context);
141 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
142 g_printerr ("modest: could not get dbus connection\n");
146 /* Add a D-Bus handler to be used when the main osso-rpc
147 * D-Bus handler has not handled something.
148 * We use this for D-Bus methods that need to use more complex types
149 * than osso-rpc supports.
151 if (!dbus_connection_add_filter (con,
152 modest_dbus_req_filter,
156 g_printerr ("modest: Could not add D-Bus filter\n");
160 /* Register our simple D-Bus callbacks, via the osso API: */
161 osso_return_t result = osso_rpc_set_cb_f(osso_context,
165 modest_dbus_req_handler, NULL /* user_data */);
166 if (result != OSSO_OK) {
167 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
171 /* Register hardware event dbus callback: */
172 hw_state.shutdown_ind = TRUE;
173 osso_hw_set_event_cb(osso_context, NULL, NULL, NULL);
175 /* Register osso auto-save callbacks: */
176 result = osso_application_set_autosave_cb (osso_context,
177 modest_on_osso_application_autosave, NULL /* user_data */);
178 if (result != OSSO_OK) {
179 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
184 /* Make sure that the update interval is changed whenever its gconf key
186 /* CAUTION: we're not using here the
187 modest_conf_listen_to_namespace because we know that there
188 are other parts of Modest listening for this namespace, so
189 we'll receive the notifications anyway. We basically do not
190 use it because there is no easy way to do the
191 modest_conf_forget_namespace */
192 ModestConf *conf = modest_runtime_get_conf ();
193 g_signal_connect (G_OBJECT(conf),
195 G_CALLBACK (on_modest_conf_update_interval_changed),
198 /* only force the setting of the default interval, if there are actually
200 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
202 /* Get the initial update interval from gconf: */
203 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
204 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
205 modest_account_mgr_free_account_names (acc_names);
209 #ifdef MODEST_HAVE_ABOOK
210 /* initialize the addressbook */
211 if (!osso_abook_init (&argc, &argv, osso_context)) {
212 g_printerr ("modest: failed to initialized addressbook\n");
215 #endif /*MODEST_HAVE_ABOOK*/
221 modest_platform_uninit (void)
223 osso_context_t *osso_context =
224 modest_maemo_utils_get_osso_context ();
226 osso_deinitialize (osso_context);
235 modest_platform_get_new_device (void)
237 return TNY_DEVICE (tny_maemo_conic_device_new ());
241 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
242 gchar **effective_mime_type)
244 GString *mime_str = NULL;
245 gchar *icon_name = NULL;
246 gchar **icons, **cursor;
248 if (!mime_type || g_ascii_strcasecmp (mime_type, "application/octet-stream") == 0)
249 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
251 mime_str = g_string_new (mime_type);
252 g_string_ascii_down (mime_str);
255 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
257 for (cursor = icons; cursor; ++cursor) {
258 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
259 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
260 icon_name = g_strdup ("qgn_list_messagin");
262 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
263 icon_name = g_strdup (*cursor);
269 if (effective_mime_type)
270 *effective_mime_type = g_string_free (mime_str, FALSE);
272 g_string_free (mime_str, TRUE);
279 checked_hildon_uri_open (const gchar *uri, HildonURIAction *action)
284 g_return_val_if_fail (uri, FALSE);
286 result = hildon_uri_open (uri, action, &err);
288 g_printerr ("modest: hildon_uri_open ('%s', %p) failed: %s",
289 uri, action, err && err->message ? err->message : "unknown error");
299 modest_platform_activate_uri (const gchar *uri)
301 HildonURIAction *action;
302 gboolean result = FALSE;
303 GSList *actions, *iter = NULL;
305 g_return_val_if_fail (uri, FALSE);
309 /* don't try to activate file: uri's -- they might confuse the user,
310 * and/or might have security implications */
311 if (!g_str_has_prefix (uri, "file:")) {
313 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
315 for (iter = actions; iter; iter = g_slist_next (iter)) {
316 action = (HildonURIAction*) iter->data;
317 if (action && strcmp (hildon_uri_action_get_service (action),
318 "com.nokia.modest") == 0) {
319 result = checked_hildon_uri_open (uri, action);
324 /* if we could not open it with email, try something else */
326 result = checked_hildon_uri_open (uri, NULL);
330 ModestWindow *parent =
331 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
332 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
333 _("mcen_ib_unsupported_link"));
334 g_warning ("%s: cannot open uri '%s'", __FUNCTION__,uri);
341 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
345 gchar *uri_path = NULL;
347 uri_path = gnome_vfs_get_uri_from_local_path (path);
348 con = osso_get_dbus_connection (modest_maemo_utils_get_osso_context());
351 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
353 result = hildon_mime_open_file (con, uri_path);
355 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"), FALSE);
363 } ModestPlatformPopupInfo;
366 delete_uri_popup (GtkWidget *menu,
370 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
372 g_free (popup_info->uri);
373 hildon_uri_free_actions (popup_info->actions);
379 activate_uri_popup_item (GtkMenuItem *menu_item,
383 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
384 const gchar* action_name;
386 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
388 g_printerr ("modest: no action name defined\n");
392 /* special handling for the copy menu item -- copy the uri to the clipboard */
393 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
394 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
395 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
396 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
398 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
399 action_name += strlen ("mailto:");
401 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
402 modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
403 return; /* we're done */
406 /* now, the real uri-actions... */
407 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
408 HildonURIAction *action = (HildonURIAction *) node->data;
409 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
410 if (!checked_hildon_uri_open (popup_info->uri, action)) {
411 ModestWindow *parent =
412 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
413 hildon_banner_show_information (parent ? GTK_WIDGET(parent): NULL, NULL,
414 _("mcen_ib_unsupported_link"));
422 modest_platform_show_uri_popup (const gchar *uri)
424 GSList *actions_list;
429 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
432 GtkWidget *menu = gtk_menu_new ();
433 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
435 /* don't add actions for file: uri's -- they might confuse the user,
436 * and/or might have security implications
437 * we still allow to copy the url though
439 if (!g_str_has_prefix (uri, "file:")) {
442 popup_info->actions = actions_list;
443 popup_info->uri = g_strdup (uri);
445 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
446 GtkWidget *menu_item;
447 const gchar *action_name;
448 const gchar *translation_domain;
449 HildonURIAction *action = (HildonURIAction *) node->data;
450 action_name = hildon_uri_action_get_name (action);
451 translation_domain = hildon_uri_action_get_translation_domain (action);
452 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
453 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
454 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
457 if (hildon_uri_is_default_action (action, NULL)) {
458 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
460 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
462 gtk_widget_show (menu_item);
466 /* always add the copy item */
467 GtkWidget* menu_item = gtk_menu_item_new_with_label (dgettext("osso-uri",
468 "uri_link_copy_link_location"));
469 g_object_set_data_full (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION,
470 g_strconcat (URI_ACTION_COPY, uri, NULL),
472 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),NULL);
473 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
474 gtk_widget_show (menu_item);
477 /* and what to do when the link is deleted */
478 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
479 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
482 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
490 modest_platform_get_icon (const gchar *name, guint icon_size)
493 GdkPixbuf* pixbuf = NULL;
494 GtkIconTheme *current_theme = NULL;
496 g_return_val_if_fail (name, NULL);
498 /* strlen == 0 is not really an error; it just
499 * means the icon is not available
501 if (!name || strlen(name) == 0)
504 current_theme = gtk_icon_theme_get_default ();
505 pixbuf = gtk_icon_theme_load_icon (current_theme, name, icon_size,
506 GTK_ICON_LOOKUP_NO_SVG,
509 g_printerr ("modest: error loading theme icon '%s': %s\n",
517 modest_platform_get_app_name (void)
519 return _("mcen_ap_name");
523 entry_insert_text (GtkEditable *editable,
532 chars = gtk_editable_get_chars (editable, 0, -1);
533 chars_length = g_utf8_strlen (chars, -1);
536 /* Show WID-INF036 */
537 if (chars_length >= 20) {
538 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
539 _CS("ckdg_ib_maximum_characters_reached"));
541 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
545 tmp = g_strndup (folder_name_forbidden_chars,
546 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
547 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
548 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
553 /* Write the text in the entry if it's valid */
554 g_signal_handlers_block_by_func (editable,
555 (gpointer) entry_insert_text, data);
556 gtk_editable_insert_text (editable, text, length, position);
557 g_signal_handlers_unblock_by_func (editable,
558 (gpointer) entry_insert_text, data);
561 /* Do not allow further processing */
562 g_signal_stop_emission_by_name (editable, "insert_text");
566 entry_changed (GtkEditable *editable,
570 GtkWidget *ok_button;
573 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
574 ok_button = GTK_WIDGET (buttons->data);
576 chars = gtk_editable_get_chars (editable, 0, -1);
577 g_return_if_fail (chars != NULL);
580 if (g_utf8_strlen (chars,-1) >= 20)
581 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
582 _CS("ckdg_ib_maximum_characters_reached"));
584 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
587 g_list_free (buttons);
594 on_response (GtkDialog *dialog,
598 GList *child_vbox, *child_hbox;
599 GtkWidget *hbox, *entry;
600 TnyFolderStore *parent;
601 const gchar *new_name;
604 if (response != GTK_RESPONSE_ACCEPT)
608 child_vbox = gtk_container_get_children (GTK_CONTAINER (dialog->vbox));
609 hbox = child_vbox->data;
610 child_hbox = gtk_container_get_children (GTK_CONTAINER (hbox));
611 entry = child_hbox->next->data;
613 parent = TNY_FOLDER_STORE (user_data);
614 new_name = gtk_entry_get_text (GTK_ENTRY (entry));
617 /* Look for another folder with the same name */
618 if (modest_tny_folder_has_subfolder_with_name (parent,
625 if (TNY_IS_ACCOUNT (parent) &&
626 modest_tny_account_is_virtual_local_folders (TNY_ACCOUNT (parent)) &&
627 modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (parent),
636 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
637 NULL, _CS("ckdg_ib_folder_already_exists"));
638 /* Select the text */
639 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
640 gtk_widget_grab_focus (entry);
641 /* Do not close the dialog */
642 g_signal_stop_emission_by_name (dialog, "response");
649 modest_platform_run_folder_name_dialog (GtkWindow *parent_window,
650 TnyFolderStore *parent,
651 const gchar *dialog_title,
652 const gchar *label_text,
653 const gchar *suggested_name,
656 GtkWidget *accept_btn = NULL;
657 GtkWidget *dialog, *entry, *label, *hbox;
658 GList *buttons = NULL;
661 /* Ask the user for the folder name */
662 dialog = gtk_dialog_new_with_buttons (dialog_title,
664 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
669 /* Add accept button (with unsensitive handler) */
670 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
671 accept_btn = GTK_WIDGET (buttons->data);
672 /* Create label and entry */
673 label = gtk_label_new (label_text);
675 entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
676 gtk_entry_set_max_length (GTK_ENTRY (entry), 20);
679 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
681 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
682 gtk_entry_set_width_chars (GTK_ENTRY (entry),
683 MAX (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry)), -1),
684 g_utf8_strlen (_("mcen_ia_default_folder_name"), -1)));
685 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
687 /* Connect to the response method to avoid closing the dialog
688 when an invalid name is selected*/
689 g_signal_connect (dialog,
691 G_CALLBACK (on_response),
694 /* Track entry changes */
695 g_signal_connect (entry,
697 G_CALLBACK (entry_insert_text),
699 g_signal_connect (entry,
701 G_CALLBACK (entry_changed),
705 /* Some locales like pt_BR need this to get the full window
707 gtk_widget_set_size_request (GTK_WIDGET (dialog), 300, -1);
709 /* Create the hbox */
710 hbox = gtk_hbox_new (FALSE, 12);
711 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
712 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
714 /* Add hbox to dialog */
715 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
716 hbox, FALSE, FALSE, 0);
717 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
718 GTK_WINDOW (dialog), parent_window);
719 gtk_widget_show_all (GTK_WIDGET(dialog));
721 result = gtk_dialog_run (GTK_DIALOG(dialog));
722 if (result == GTK_RESPONSE_ACCEPT)
723 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
725 gtk_widget_destroy (dialog);
727 while (gtk_events_pending ())
728 gtk_main_iteration ();
734 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
735 TnyFolderStore *parent_folder,
736 gchar *suggested_name,
739 gchar *real_suggested_name = NULL, *tmp = NULL;
742 if(suggested_name == NULL)
744 const gchar *default_name = _("mcen_ia_default_folder_name");
748 for(i = 0; i < 100; ++ i) {
749 gboolean exists = FALSE;
751 sprintf(num_str, "%.2u", i);
754 real_suggested_name = g_strdup (default_name);
756 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
758 exists = modest_tny_folder_has_subfolder_with_name (parent_folder,
765 g_free (real_suggested_name);
768 /* Didn't find a free number */
770 real_suggested_name = g_strdup (default_name);
772 real_suggested_name = suggested_name;
775 tmp = g_strconcat (_("mcen_fi_new_folder_name"), ":", NULL);
776 result = modest_platform_run_folder_name_dialog (parent_window,
778 _("mcen_ti_new_folder"),
784 if (suggested_name == NULL)
785 g_free(real_suggested_name);
791 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
792 TnyFolderStore *parent_folder,
793 const gchar *suggested_name,
796 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
798 return modest_platform_run_folder_name_dialog (parent_window,
800 _HL("ckdg_ti_rename_folder"),
801 _HL("ckdg_fi_rename_name"),
809 on_destroy_dialog (GtkWidget *dialog)
811 /* This could happen when the dialogs get programatically
812 hidden or destroyed (for example when closing the
813 application while a dialog is being shown) */
814 if (!GTK_IS_WIDGET (dialog))
817 gtk_widget_destroy (dialog);
819 if (gtk_events_pending ())
820 gtk_main_iteration ();
824 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
825 const gchar *message)
830 dialog = hildon_note_new_confirmation (parent_window, message);
831 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
832 GTK_WINDOW (dialog), parent_window);
834 response = gtk_dialog_run (GTK_DIALOG (dialog));
836 on_destroy_dialog (dialog);
842 modest_platform_run_confirmation_dialog_with_buttons (GtkWindow *parent_window,
843 const gchar *message,
844 const gchar *button_accept,
845 const gchar *button_cancel)
850 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
851 button_accept, GTK_RESPONSE_ACCEPT,
852 button_cancel, GTK_RESPONSE_CANCEL,
855 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
856 GTK_WINDOW (dialog), parent_window);
858 response = gtk_dialog_run (GTK_DIALOG (dialog));
860 on_destroy_dialog (dialog);
866 modest_platform_run_information_dialog (GtkWindow *parent_window,
867 const gchar *message,
872 note = hildon_note_new_information (parent_window, message);
874 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
875 GTK_WINDOW (note), parent_window);
878 gtk_dialog_run (GTK_DIALOG (note));
880 on_destroy_dialog (note);
882 g_signal_connect_swapped (note,
884 G_CALLBACK (on_destroy_dialog),
887 gtk_widget_show_all (note);
891 typedef struct _ConnectAndWaitData {
893 GMainLoop *wait_loop;
894 gboolean has_callback;
896 } ConnectAndWaitData;
900 quit_wait_loop (TnyAccount *account,
901 ConnectAndWaitData *data)
903 /* Set the has_callback to TRUE (means that the callback was
904 executed and wake up every code waiting for cond to be
906 g_mutex_lock (data->mutex);
907 data->has_callback = TRUE;
909 g_main_loop_quit (data->wait_loop);
910 g_mutex_unlock (data->mutex);
914 on_connection_status_changed (TnyAccount *account,
915 TnyConnectionStatus status,
918 TnyConnectionStatus conn_status;
919 ConnectAndWaitData *data;
921 /* Ignore if reconnecting or disconnected */
922 conn_status = tny_account_get_connection_status (account);
923 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
924 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
927 /* Remove the handler */
928 data = (ConnectAndWaitData *) user_data;
929 g_signal_handler_disconnect (account, data->handler);
931 /* Quit from wait loop */
932 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
936 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
941 /* Quit from wait loop */
942 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
946 modest_platform_connect_and_wait (GtkWindow *parent_window,
949 ConnectAndWaitData *data = NULL;
950 gboolean device_online;
952 TnyConnectionStatus conn_status;
953 gboolean user_requested;
955 device = modest_runtime_get_device();
956 device_online = tny_device_is_online (device);
958 /* Whether the connection is user requested or automatically
959 requested, for example via D-Bus */
960 user_requested = (parent_window) ? TRUE : FALSE;
962 /* If there is no account check only the device status */
967 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
968 NULL, user_requested);
971 /* Return if the account is already connected */
972 conn_status = tny_account_get_connection_status (account);
973 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
976 /* Create the helper */
977 data = g_slice_new0 (ConnectAndWaitData);
978 data->mutex = g_mutex_new ();
979 data->has_callback = FALSE;
981 /* Connect the device */
982 if (!device_online) {
983 /* Track account connection status changes */
984 data->handler = g_signal_connect (account, "connection-status-changed",
985 G_CALLBACK (on_connection_status_changed),
987 /* Try to connect the device */
988 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device),
989 NULL, user_requested);
991 /* If the device connection failed then exit */
992 if (!device_online && data->handler)
995 /* Force a reconnection of the account */
996 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
997 on_tny_camel_account_set_online_cb, data);
1000 /* Wait until the callback is executed */
1001 g_mutex_lock (data->mutex);
1002 if (!data->has_callback) {
1003 data->wait_loop = g_main_loop_new (g_main_context_new (), FALSE);
1004 gdk_threads_leave ();
1005 g_mutex_unlock (data->mutex);
1006 g_main_loop_run (data->wait_loop);
1007 g_mutex_lock (data->mutex);
1008 gdk_threads_enter ();
1010 g_mutex_unlock (data->mutex);
1014 if (g_signal_handler_is_connected (account, data->handler))
1015 g_signal_handler_disconnect (account, data->handler);
1016 g_mutex_free (data->mutex);
1017 g_main_loop_unref (data->wait_loop);
1018 g_slice_free (ConnectAndWaitData, data);
1021 conn_status = tny_account_get_connection_status (account);
1022 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1026 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1028 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1029 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1030 /* This must be a maildir account, which does not require a connection: */
1035 return modest_platform_connect_and_wait (parent_window, account);
1039 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1042 return TRUE; /* Maybe it is something local. */
1044 gboolean result = TRUE;
1045 if (TNY_IS_FOLDER (folder_store)) {
1046 /* Get the folder's parent account: */
1047 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1048 if (account != NULL) {
1049 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1050 g_object_unref (account);
1052 } else if (TNY_IS_ACCOUNT (folder_store)) {
1053 /* Use the folder store as an account: */
1054 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1061 modest_platform_create_sort_dialog (GtkWindow *parent_window)
1065 dialog = modest_hildon2_sort_dialog_new (parent_window);
1072 modest_platform_set_update_interval (guint minutes)
1074 #ifdef MODEST_HAVE_LIBALARM
1076 ModestConf *conf = modest_runtime_get_conf ();
1080 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1082 /* Delete any existing alarm,
1083 * because we will replace it: */
1085 if (alarmd_event_del(alarm_cookie) != 1)
1086 g_warning ("%s: alarm %d was not on the queue", __FUNCTION__, (int)alarm_cookie);
1088 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1091 /* 0 means no updates: */
1096 /* Register alarm: */
1098 /* Set the interval in alarm_event_t structure: */
1099 alarm_event_t *event = alarm_event_create ();
1100 alarm_event_add_actions (event, 1);
1101 alarm_action_t *action = alarm_event_get_action (event, 0);
1102 event->alarm_time = minutes * 60; /* seconds */
1104 /* Set recurrence every few minutes: */
1105 event->recur_secs = minutes*60;
1106 event->recur_count = -1; /* Means infinite */
1108 /* Specify what should happen when the alarm happens:
1109 * It should call this D-Bus method: */
1111 action->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1112 action->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1113 action->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1114 action->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1115 action->flags = ALARM_ACTION_TYPE_DBUS | ALARM_ACTION_DBUS_USE_ACTIVATION;
1117 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1118 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1119 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1120 * This is why we want to use the Alarm API instead of just g_timeout_add().
1121 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1122 * ALARM_EVENT_CONNECTED will prevent the alarm from being called in case that the device is offline
1124 event->flags = ALARM_EVENT_CONNECTED;
1126 alarm_cookie = alarmd_event_add (event);
1129 alarm_event_delete (event);
1131 /* Store the alarm ID in GConf, so we can remove it later:
1132 * This is apparently valid between application instances. */
1133 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1135 if (!alarm_cookie) {
1137 g_debug ("Error setting alarm event. \n");
1141 #endif /* MODEST_HAVE_LIBALARM */
1146 modest_platform_push_email_notification(void)
1148 gboolean play_sound;
1149 ModestWindow *main_window;
1150 gboolean screen_on = TRUE, app_in_foreground;
1152 /* Check whether or not we should play a sound */
1153 play_sound = modest_conf_get_bool (modest_runtime_get_conf (),
1154 MODEST_CONF_PLAY_SOUND_MSG_ARRIVE,
1157 /* Get the screen status */
1158 main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (), FALSE);
1160 screen_on = modest_main_window_screen_is_on (MODEST_MAIN_WINDOW (main_window));
1162 /* Get the window status */
1163 app_in_foreground = hildon_program_get_is_topmost (hildon_program_get_instance ());
1165 /* If the screen is on and the app is in the
1166 foreground we don't show anything */
1167 if (!(screen_on && app_in_foreground)) {
1170 hildon_play_system_sound (MODEST_NEW_MAIL_SOUND_FILE);
1172 /* Activate LED. This must be deactivated by
1173 modest_platform_remove_new_mail_notifications */
1174 #ifdef MODEST_HAVE_MCE
1175 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1179 MCE_ACTIVATE_LED_PATTERN,
1181 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1188 modest_platform_on_new_headers_received (TnyList *header_list,
1189 gboolean show_visual)
1191 g_return_if_fail (TNY_IS_LIST(header_list));
1193 if (tny_list_get_length(header_list) == 0) {
1194 g_warning ("%s: header list is empty", __FUNCTION__);
1199 modest_platform_push_email_notification ();
1200 /* We do a return here to avoid indentation with an else */
1204 #ifdef MODEST_HAVE_HILDON_NOTIFY
1205 gboolean play_sound;
1207 /* Check whether or not we should play a sound */
1208 play_sound = modest_conf_get_bool (modest_runtime_get_conf (),
1209 MODEST_CONF_PLAY_SOUND_MSG_ARRIVE,
1212 HildonNotification *notification;
1214 GSList *notifications_list = NULL;
1216 /* Get previous notifications ids */
1217 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1218 MODEST_CONF_NOTIFICATION_IDS,
1219 MODEST_CONF_VALUE_INT, NULL);
1221 iter = tny_list_create_iterator (header_list);
1222 while (!tny_iterator_is_done (iter)) {
1223 gchar *url = NULL, *display_address = NULL, *summary = NULL;
1224 const gchar *display_date;
1225 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1226 TnyFolder *folder = tny_header_get_folder (header);
1227 gboolean first_notification = TRUE;
1230 ModestDatetimeFormatter *datetime_formatter;
1232 /* constant string, don't free */
1233 datetime_formatter = modest_datetime_formatter_new ();
1234 display_date = modest_datetime_formatter_display_datetime (datetime_formatter,
1235 tny_header_get_date_received (header));
1236 g_object_unref (datetime_formatter);
1238 display_address = tny_header_dup_from (header);
1239 modest_text_utils_get_display_address (display_address); /* string is changed in-place */
1241 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1242 str = tny_header_dup_subject (header);
1243 notification = hildon_notification_new (summary,
1245 "qgn_list_messagin",
1248 /* Create the message URL */
1249 str = tny_header_dup_uid (header);
1250 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1254 hildon_notification_add_dbus_action(notification,
1257 MODEST_DBUS_SERVICE,
1260 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1264 /* Play sound if the user wants. Show the LED
1265 pattern. Show and play just one */
1266 if (G_UNLIKELY (first_notification)) {
1267 first_notification = FALSE;
1269 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1270 "sound-file", MODEST_NEW_MAIL_SOUND_FILE);
1273 /* Set the led pattern */
1274 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1276 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1278 MODEST_NEW_MAIL_LIGHTING_PATTERN);
1281 /* Notify. We need to do this in an idle because this function
1282 could be called from a thread */
1283 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1285 /* Save id in the list */
1286 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1287 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1288 /* We don't listen for the "closed" signal, because we
1289 don't care about if the notification was removed or
1290 not to store the list in gconf */
1292 /* Free & carry on */
1293 g_free (display_address);
1296 g_object_unref (folder);
1297 g_object_unref (header);
1298 tny_iterator_next (iter);
1300 g_object_unref (iter);
1303 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1304 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1306 g_slist_free (notifications_list);
1308 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1312 modest_platform_remove_new_mail_notifications (gboolean only_visuals)
1315 #ifdef MODEST_HAVE_MCE
1316 osso_rpc_run_system (modest_maemo_utils_get_osso_context (),
1320 MCE_DEACTIVATE_LED_PATTERN,
1322 DBUS_TYPE_STRING, MODEST_NEW_MAIL_LIGHTING_PATTERN,
1328 #ifdef MODEST_HAVE_HILDON_NOTIFY
1329 GSList *notif_list = NULL;
1331 /* Get previous notifications ids */
1332 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1333 MODEST_CONF_NOTIFICATION_IDS,
1334 MODEST_CONF_VALUE_INT, NULL);
1336 while (notif_list) {
1338 NotifyNotification *notif;
1340 /* Nasty HACK to remove the notifications, set the id
1341 of the existing ones and then close them */
1342 notif_id = GPOINTER_TO_INT(notif_list->data);
1343 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1344 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1346 /* Close the notification, note that some ids could be
1347 already invalid, but we don't care because it does
1349 notify_notification_close(notif, NULL);
1350 g_object_unref(notif);
1352 /* Delete the link, it's like going to the next */
1353 notif_list = g_slist_delete_link (notif_list, notif_list);
1357 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1358 notif_list, MODEST_CONF_VALUE_INT, NULL);
1360 g_slist_free (notif_list);
1362 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1368 modest_platform_get_global_settings_dialog ()
1370 return modest_hildon2_global_settings_dialog_new ();
1374 modest_platform_show_help (GtkWindow *parent_window,
1375 const gchar *help_id)
1381 modest_platform_show_search_messages (GtkWindow *parent_window)
1383 osso_return_t result = OSSO_ERROR;
1385 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1386 "osso_global_search",
1387 "search_email", NULL, DBUS_TYPE_INVALID);
1389 if (result != OSSO_OK) {
1390 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1395 modest_platform_show_addressbook (GtkWindow *parent_window)
1397 osso_return_t result = OSSO_ERROR;
1399 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1401 "top_application", NULL, DBUS_TYPE_INVALID);
1403 if (result != OSSO_OK) {
1404 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1409 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1411 GtkWidget *widget = modest_folder_view_new (query);
1413 /* Show one account by default */
1414 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1415 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1417 /* Restore settings */
1418 modest_widget_memory_restore (modest_runtime_get_conf(),
1420 MODEST_CONF_FOLDER_VIEW_KEY);
1426 banner_finish (gpointer data, GObject *object)
1428 ModestWindowMgr *mgr = (ModestWindowMgr *) data;
1429 modest_window_mgr_unregister_banner (mgr);
1430 g_object_unref (mgr);
1434 modest_platform_information_banner (GtkWidget *parent,
1435 const gchar *icon_name,
1438 GtkWidget *banner, *banner_parent = NULL;
1439 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1441 if (modest_window_mgr_num_windows (mgr) == 0)
1444 if (parent && GTK_IS_WINDOW (parent)) {
1445 /* If the window is the active one then show the
1446 banner on top of this window */
1447 if (gtk_window_is_active (GTK_WINDOW (parent)))
1448 banner_parent = parent;
1449 /* If the window is not the topmost but it's visible
1450 (it's minimized for example) then show the banner
1452 else if (GTK_WIDGET_VISIBLE (parent))
1453 banner_parent = NULL;
1454 /* If the window is hidden (like the main window when
1455 running in the background) then do not show
1462 banner = hildon_banner_show_information (banner_parent, icon_name, text);
1464 modest_window_mgr_register_banner (mgr);
1466 g_object_weak_ref ((GObject *) banner, banner_finish, mgr);
1470 modest_platform_information_banner_with_timeout (GtkWidget *parent,
1471 const gchar *icon_name,
1477 if (modest_window_mgr_num_windows (modest_runtime_get_window_mgr ()) == 0)
1480 banner = hildon_banner_show_information (parent, icon_name, text);
1481 hildon_banner_set_timeout(HILDON_BANNER(banner), timeout);
1485 modest_platform_animation_banner (GtkWidget *parent,
1486 const gchar *animation_name,
1489 GtkWidget *inf_note = NULL;
1491 g_return_val_if_fail (text != NULL, NULL);
1493 if (modest_window_mgr_num_windows (modest_runtime_get_window_mgr ()) == 0)
1496 /* If the parent is not visible then do not show */
1497 if (parent && !GTK_WIDGET_VISIBLE (parent))
1500 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1508 TnyAccount *account;
1511 } CheckAccountIdleData;
1513 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1516 on_timeout_check_account_is_online(CheckAccountIdleData* data)
1518 gboolean stop_trying = FALSE;
1519 g_return_val_if_fail (data && data->account, FALSE);
1521 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1522 tny_account_get_connection_status (data->account));
1524 if (data && data->account &&
1525 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1526 * after which the account is likely to be usable, or never likely to be usable soon: */
1527 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1529 data->is_online = TRUE;
1533 /* Give up if we have tried too many times: */
1534 if (data->count_tries >= NUMBER_OF_TRIES) {
1537 /* Wait for another timeout: */
1538 ++(data->count_tries);
1543 /* Allow the function that requested this idle callback to continue: */
1545 g_main_loop_quit (data->loop);
1548 g_object_unref (data->account);
1550 return FALSE; /* Don't call this again. */
1552 return TRUE; /* Call this timeout callback again. */
1556 /* Return TRUE immediately if the account is already online,
1557 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1558 * soon as the account is online, or FALSE if the account does
1559 * not become online in the NUMBER_OF_TRIES seconds.
1560 * This is useful when the D-Bus method was run immediately after
1561 * the application was started (when using D-Bus activation),
1562 * because the account usually takes a short time to go online.
1563 * The return value is maybe not very useful.
1566 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1570 g_return_val_if_fail (account, FALSE);
1572 if (!tny_device_is_online (modest_runtime_get_device())) {
1573 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1577 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1578 * so we avoid wait unnecessarily: */
1579 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1582 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1583 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1584 * we want to avoid. */
1585 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1588 /* This blocks on the result: */
1589 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1590 data->is_online = FALSE;
1591 data->account = account;
1592 g_object_ref (data->account);
1593 data->count_tries = 0;
1595 GMainContext *context = NULL; /* g_main_context_new (); */
1596 data->loop = g_main_loop_new (context, FALSE /* not running */);
1598 g_timeout_add (1000, (GSourceFunc)(on_timeout_check_account_is_online), data);
1600 /* This main loop will run until the idle handler has stopped it: */
1601 g_main_loop_run (data->loop);
1603 g_main_loop_unref (data->loop);
1604 /* g_main_context_unref (context); */
1606 is_online = data->is_online;
1607 g_slice_free (CheckAccountIdleData, data);
1615 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1617 /* GTK_RESPONSE_HELP means we need to show the certificate */
1618 if (response_id == GTK_RESPONSE_APPLY) {
1622 /* Do not close the dialog */
1623 g_signal_stop_emission_by_name (dialog, "response");
1625 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1626 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1627 gtk_dialog_run (GTK_DIALOG(note));
1628 gtk_widget_destroy (note);
1634 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1635 const gchar *certificate)
1639 ModestWindow *main_win;
1641 if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
1642 g_warning ("%s: don't show dialogs if there's no main window; assuming 'Cancel'",
1647 /* don't create it */
1648 main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
1649 g_return_val_if_fail (main_win, FALSE); /* should not happen */
1652 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1655 /* We use GTK_RESPONSE_APPLY because we want the button in the
1656 middle of OK and CANCEL the same as the browser does for
1657 example. With GTK_RESPONSE_HELP the view button is aligned
1658 to the left while the other two to the right */
1659 note = hildon_note_new_confirmation_add_buttons (
1660 GTK_WINDOW(main_win),
1662 _HL("wdgt_bd_yes"), GTK_RESPONSE_OK,
1663 _HL("wdgt_bd_view"), GTK_RESPONSE_APPLY, /* abusing this... */
1664 _HL("wdgt_bd_no"), GTK_RESPONSE_CANCEL,
1667 g_signal_connect (G_OBJECT(note), "response",
1668 G_CALLBACK(on_cert_dialog_response),
1669 (gpointer) certificate);
1671 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1672 GTK_WINDOW (note), GTK_WINDOW (main_win));
1673 response = gtk_dialog_run(GTK_DIALOG(note));
1675 on_destroy_dialog (note);
1678 return response == GTK_RESPONSE_OK;
1682 modest_platform_run_alert_dialog (const gchar* prompt,
1683 gboolean is_question)
1685 ModestWindow *main_win;
1687 if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
1688 g_warning ("%s:\n'%s'\ndon't show dialogs if there's no main window;"
1689 " assuming 'Cancel' for questions, 'Ok' otherwise", prompt, __FUNCTION__);
1690 return is_question ? FALSE : TRUE;
1693 main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (), FALSE);
1694 g_return_val_if_fail (main_win, FALSE); /* should not happen */
1696 gboolean retval = TRUE;
1698 /* The Tinymail documentation says that we should show Yes and No buttons,
1699 * when it is a question.
1700 * Obviously, we need tinymail to use more specific error codes instead,
1701 * so we know what buttons to show. */
1702 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (main_win),
1704 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1705 GTK_WINDOW (dialog), GTK_WINDOW (main_win));
1707 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1708 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1710 on_destroy_dialog (dialog);
1712 /* Just show the error text and use the default response: */
1713 modest_platform_run_information_dialog (GTK_WINDOW (main_win),
1721 GtkWindow *parent_window;
1722 ModestConnectedPerformer callback;
1723 TnyAccount *account;
1730 on_went_online_info_free (OnWentOnlineInfo *info)
1732 /* And if we cleanup, we DO cleanup :-) */
1735 g_object_unref (info->device);
1738 if (info->parent_window)
1739 g_object_unref (info->parent_window);
1741 g_object_unref (info->account);
1743 g_slice_free (OnWentOnlineInfo, info);
1745 /* We're done ... */
1751 on_account_went_online (TnyCamelAccount *account, gboolean canceled, GError *err, gpointer user_data)
1753 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1755 /* Now it's really time to callback to the caller. If going online didn't succeed,
1756 * err will be set. We don't free it, Tinymail does that! If a cancel happened,
1757 * canceled will be set. Etcetera etcetera. */
1759 if (info->callback) {
1760 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
1763 /* This is our last call, we must cleanup here if we didn't yet do that */
1764 on_went_online_info_free (info);
1771 on_conic_device_went_online (TnyMaemoConicDevice *device, const gchar* iap_id, gboolean canceled, GError *err, gpointer user_data)
1773 OnWentOnlineInfo *info = (OnWentOnlineInfo *) user_data;
1774 info->iap = g_strdup (iap_id);
1776 if (canceled || err || !info->account) {
1778 /* If there's a problem or if there's no account (then that's it for us, we callback
1779 * the caller's callback now. He'll have to handle err or canceled, of course.
1780 * We are not really online, as the account is not really online here ... */
1782 /* We'll use the err and the canceled of this cb. TnyMaemoConicDevice delivered us
1783 * this info. We don't cleanup err, Tinymail does that! */
1785 if (info->callback) {
1787 /* info->account can be NULL here, this means that the user did not
1788 * provide a nice account instance. We'll assume that the user knows
1789 * what he's doing and is happy with just the device going online.
1791 * We can't do magic, we don't know what account the user wants to
1792 * see going online. So just the device goes online, end of story */
1794 info->callback (canceled, err, info->parent_window, info->account, info->user_data);
1797 } else if (info->account) {
1799 /* If there's no problem and if we have an account, we'll put the account
1800 * online too. When done, the callback of bringing the account online
1801 * will callback the caller's callback. This is the most normal case. */
1803 info->device = TNY_DEVICE (g_object_ref (device));
1805 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (info->account), TRUE,
1806 on_account_went_online, info);
1808 /* The on_account_went_online cb frees up the info, go look if you
1809 * don't believe me! (so we return here) */
1814 /* We cleanup if we are not bringing the account online too */
1815 on_went_online_info_free (info);
1821 modest_platform_connect_and_perform (GtkWindow *parent_window,
1823 TnyAccount *account,
1824 ModestConnectedPerformer callback,
1827 gboolean device_online;
1829 TnyConnectionStatus conn_status;
1830 OnWentOnlineInfo *info;
1832 device = modest_runtime_get_device();
1833 device_online = tny_device_is_online (device);
1835 /* If there is no account check only the device status */
1838 if (device_online) {
1840 /* We promise to instantly perform the callback, so ... */
1842 callback (FALSE, NULL, parent_window, account, user_data);
1847 info = g_slice_new0 (OnWentOnlineInfo);
1850 info->device = NULL;
1851 info->account = NULL;
1854 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
1856 info->parent_window = NULL;
1857 info->user_data = user_data;
1858 info->callback = callback;
1860 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
1861 force, on_conic_device_went_online,
1864 /* We'll cleanup in on_conic_device_went_online */
1867 /* The other code has no more reason to run. This is all that we can do for the
1868 * caller (he should have given us a nice and clean account instance!). We
1869 * can't do magic, we don't know what account he intends to bring online. So
1870 * we'll just bring the device online (and await his false bug report). */
1876 /* Return if the account is already connected */
1878 conn_status = tny_account_get_connection_status (account);
1879 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED) {
1881 /* We promise to instantly perform the callback, so ... */
1883 callback (FALSE, NULL, parent_window, account, user_data);
1889 /* Else, we are in a state that requires that we go online before we
1890 * call the caller's callback. */
1892 info = g_slice_new0 (OnWentOnlineInfo);
1894 info->device = NULL;
1896 info->account = TNY_ACCOUNT (g_object_ref (account));
1899 info->parent_window = (GtkWindow *) g_object_ref (parent_window);
1901 info->parent_window = NULL;
1903 /* So we'll put the callback away for later ... */
1905 info->user_data = user_data;
1906 info->callback = callback;
1908 if (!device_online) {
1910 /* If also the device is offline, then we connect both the device
1911 * and the account */
1913 tny_maemo_conic_device_connect_async (TNY_MAEMO_CONIC_DEVICE (device), NULL,
1914 force, on_conic_device_went_online,
1919 /* If the device is online, we'll just connect the account */
1921 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1922 on_account_went_online, info);
1925 /* The info gets freed by on_account_went_online or on_conic_device_went_online
1926 * in both situations, go look if you don't believe me! */
1932 modest_platform_connect_if_remote_and_perform (GtkWindow *parent_window,
1934 TnyFolderStore *folder_store,
1935 ModestConnectedPerformer callback,
1938 TnyAccount *account = NULL;
1940 if (!folder_store) {
1941 /* We promise to instantly perform the callback, so ... */
1943 callback (FALSE, NULL, parent_window, NULL, user_data);
1947 } else if (TNY_IS_FOLDER (folder_store)) {
1948 /* Get the folder's parent account: */
1949 account = tny_folder_get_account (TNY_FOLDER (folder_store));
1950 } else if (TNY_IS_ACCOUNT (folder_store)) {
1951 /* Use the folder store as an account: */
1952 account = TNY_ACCOUNT (g_object_ref (folder_store));
1955 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1956 if (!modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1957 /* No need to connect a local account */
1959 callback (FALSE, NULL, parent_window, account, user_data);
1964 modest_platform_connect_and_perform (parent_window, force, account, callback, user_data);
1968 g_object_unref (account);
1972 src_account_connect_performer (gboolean canceled,
1974 GtkWindow *parent_window,
1975 TnyAccount *src_account,
1978 DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
1980 if (canceled || err) {
1981 /* If there was any error call the user callback */
1982 info->callback (canceled, err, parent_window, src_account, info->data);
1984 /* Connect the destination account */
1985 modest_platform_connect_if_remote_and_perform (parent_window, TRUE,
1986 TNY_FOLDER_STORE (info->dst_account),
1987 info->callback, info->data);
1990 /* Free the info object */
1991 g_object_unref (info->dst_account);
1992 g_slice_free (DoubleConnectionInfo, info);
1997 modest_platform_double_connect_and_perform (GtkWindow *parent_window,
1999 TnyFolderStore *folder_store,
2000 DoubleConnectionInfo *connect_info)
2002 modest_platform_connect_if_remote_and_perform(parent_window,
2005 src_account_connect_performer,
2010 modest_platform_get_account_settings_wizard (void)
2012 ModestEasysetupWizardDialog *dialog = modest_easysetup_wizard_dialog_new ();
2014 return GTK_WIDGET (dialog);
2018 modest_platform_get_current_connection (void)
2020 TnyDevice *device = NULL;
2021 ModestConnectedVia retval = MODEST_CONNECTED_VIA_ANY;
2023 device = modest_runtime_get_device ();
2025 if (!tny_device_is_online (device))
2026 return MODEST_CONNECTED_VIA_ANY;
2028 #ifdef MODEST_HAVE_CONIC
2030 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
2032 ConIcIap *iap = tny_maemo_conic_device_get_iap (
2033 TNY_MAEMO_CONIC_DEVICE (device), iap_id);
2034 const gchar *bearer_type = con_ic_iap_get_bearer_type (iap);
2036 if (!strcmp (bearer_type, CON_IC_BEARER_WLAN_INFRA) ||
2037 !strcmp (bearer_type, CON_IC_BEARER_WLAN_ADHOC) ||
2038 !strcmp (bearer_type, "WIMAX")) {
2039 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX;
2041 retval = MODEST_CONNECTED_VIA_ANY;
2044 g_object_unref (iap);
2047 retval = MODEST_CONNECTED_VIA_WLAN_OR_WIMAX; /* assume WLAN (fast) internet */
2048 #endif /* MODEST_HAVE_CONIC */
2055 modest_platform_check_memory_low (ModestWindow *win,
2060 /* are we in low memory state? */
2061 lowmem = osso_mem_in_lowmem_state () ? TRUE : FALSE;
2063 if (win && lowmem && visuals)
2064 modest_platform_run_information_dialog (
2066 dgettext("ke-recv","memr_ib_operation_disabled"),
2070 g_debug ("%s: low memory reached. disallowing some operations",
2077 modest_platform_run_folder_details_dialog (GtkWindow *parent_window,
2083 dialog = modest_hildon2_details_dialog_new_with_folder (parent_window, folder);
2086 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2087 GTK_WINDOW (dialog),
2089 gtk_widget_show_all (dialog);
2091 g_signal_connect_swapped (dialog, "response",
2092 G_CALLBACK (gtk_widget_destroy),
2097 modest_platform_run_header_details_dialog (GtkWindow *parent_window,
2103 dialog = modest_hildon2_details_dialog_new_with_header (parent_window, header);
2106 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2107 GTK_WINDOW (dialog),
2109 gtk_widget_show_all (dialog);
2111 g_signal_connect_swapped (dialog, "response",
2112 G_CALLBACK (gtk_widget_destroy),
2117 modest_platform_get_osso_context (void)
2119 return modest_maemo_utils_get_osso_context ();