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 "maemo/modest-maemo-global-settings-dialog.h"
37 #include "modest-widget-memory.h"
38 #include <modest-hildon-includes.h>
39 #include <osso-helplib.h>
40 #include <modest-maemo-utils.h>
41 #include <dbus_api/modest-dbus-callbacks.h>
42 #include <libosso-abook/osso-abook.h>
43 #include <maemo/modest-osso-autosave-callbacks.h>
45 #include <alarmd/alarm_event.h> /* For alarm_event_add(), etc. */
46 #include <tny-maemo-conic-device.h>
47 #include <tny-simple-list.h>
48 #include <tny-folder.h>
49 #include <tny-camel-imap-store-account.h>
50 #include <tny-camel-pop-store-account.h>
51 #include <gtk/gtkicontheme.h>
52 #include <gtk/gtkmenuitem.h>
53 #include <gtk/gtkmain.h>
54 #include <modest-text-utils.h>
55 #include "modest-tny-folder.h"
57 #include <libgnomevfs/gnome-vfs-mime-utils.h>
60 #define HILDON_OSSO_URI_ACTION "uri-action"
61 #define URI_ACTION_COPY "copy:"
63 static osso_context_t *osso_context = NULL;
66 on_modest_conf_update_interval_changed (ModestConf* self,
68 ModestConfEvent event,
69 ModestConfNotificationId id,
72 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
73 const guint update_interval_minutes =
74 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
75 modest_platform_set_update_interval (update_interval_minutes);
82 check_required_files (void)
84 FILE *mcc_file = modest_maemo_open_mcc_mapping_file ();
86 g_printerr ("modest: check for mcc file failed\n");
91 if (access (MODEST_PROVIDERS_DATA_PATH, R_OK) != 0) {
92 g_printerr ("modest: cannot find providers data\n");
102 modest_platform_init (int argc, char *argv[])
104 osso_hw_state_t hw_state = { 0 };
107 if (!check_required_files ()) {
108 g_printerr ("modest: missing required files\n");
114 osso_initialize(PACKAGE,PACKAGE_VERSION,
117 g_printerr ("modest: failed to acquire osso context\n");
121 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
122 g_printerr ("modest: could not get dbus connection\n");
127 /* Add a D-Bus handler to be used when the main osso-rpc
128 * D-Bus handler has not handled something.
129 * We use this for D-Bus methods that need to use more complex types
130 * than osso-rpc supports.
132 if (!dbus_connection_add_filter (con,
133 modest_dbus_req_filter,
137 g_printerr ("modest: Could not add D-Bus filter\n");
141 /* Register our simple D-Bus callbacks, via the osso API: */
142 osso_return_t result = osso_rpc_set_cb_f(osso_context,
146 modest_dbus_req_handler, NULL /* user_data */);
147 if (result != OSSO_OK) {
148 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
152 /* Add handler for Exit D-BUS messages.
153 * Not used because osso_application_set_exit_cb() is deprecated and obsolete:
154 result = osso_application_set_exit_cb(osso_context,
155 modest_dbus_exit_event_handler,
157 if (result != OSSO_OK) {
158 g_print("Error setting exit callback (%d)\n", result);
163 /* Register hardware event dbus callback: */
164 hw_state.shutdown_ind = TRUE;
165 osso_hw_set_event_cb(osso_context, NULL,/*&hw_state*/ modest_osso_cb_hw_state_handler, NULL);
167 /* Register osso auto-save callbacks: */
168 result = osso_application_set_autosave_cb (osso_context,
169 modest_on_osso_application_autosave, NULL /* user_data */);
170 if (result != OSSO_OK) {
171 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
176 /* Make sure that the update interval is changed whenever its gconf key
178 /* CAUTION: we're not using here the
179 modest_conf_listen_to_namespace because we know that there
180 are other parts of Modest listening for this namespace, so
181 we'll receive the notifications anyway. We basically do not
182 use it because there is no easy way to do the
183 modest_conf_forget_namespace */
184 ModestConf *conf = modest_runtime_get_conf ();
185 g_signal_connect (G_OBJECT(conf),
187 G_CALLBACK (on_modest_conf_update_interval_changed),
190 /* Get the initial update interval from gconf: */
191 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
192 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
194 /* initialize the addressbook */
195 if (!osso_abook_init (&argc, &argv, osso_context)) {
196 g_printerr ("modest: failed to initialized addressbook\n");
204 modest_platform_get_new_device (void)
206 return TNY_DEVICE (tny_maemo_conic_device_new ());
210 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
211 gchar **effective_mime_type)
213 GString *mime_str = NULL;
214 gchar *icon_name = NULL;
215 gchar **icons, **cursor;
217 if (!mime_type || !g_ascii_strcasecmp (mime_type, "application/octet-stream"))
218 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
220 mime_str = g_string_new (mime_type);
221 g_string_ascii_down (mime_str);
224 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
225 for (cursor = icons; cursor; ++cursor) {
226 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
227 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
228 icon_name = g_strdup ("qgn_list_messagin");
230 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
231 icon_name = g_strdup (*cursor);
237 if (effective_mime_type)
238 *effective_mime_type = g_string_free (mime_str, FALSE);
240 g_string_free (mime_str, TRUE);
247 modest_platform_activate_uri (const gchar *uri)
249 HildonURIAction *action;
250 gboolean result = FALSE;
251 GSList *actions, *iter = NULL;
253 g_return_val_if_fail (uri, FALSE);
257 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
259 for (iter = actions; iter; iter = g_slist_next (iter)) {
260 action = (HildonURIAction*) iter->data;
261 if (action && strcmp (hildon_uri_action_get_service (action),
262 "com.nokia.modest") == 0) {
264 result = hildon_uri_open (uri, action, &err);
265 if (!result && err) {
266 g_printerr ("modest: modest_platform_activate_uri : %s",
267 err->message ? err->message : "unknown error");
274 /* if we could not open it with email, try something else */
276 result = hildon_uri_open (uri, NULL, NULL);
279 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
285 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
289 gchar *uri_path = NULL;
291 uri_path = g_strconcat ("file://", path, NULL);
292 con = osso_get_dbus_connection (osso_context);
295 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
297 result = hildon_mime_open_file (con, uri_path);
299 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"));
307 } ModestPlatformPopupInfo;
310 delete_uri_popup (GtkWidget *menu,
314 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
316 g_free (popup_info->uri);
317 hildon_uri_free_actions (popup_info->actions);
323 activate_uri_popup_item (GtkMenuItem *menu_item,
327 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
328 const gchar* action_name;
330 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
332 g_printerr ("modest: no action name defined\n");
336 /* special handling for the copy menu item -- copy the uri to the clipboard */
337 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
338 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
339 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
340 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
342 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
343 action_name += strlen ("mailto:");
345 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
346 return; /* we're done */
349 /* now, the real uri-actions... */
350 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
351 HildonURIAction *action = (HildonURIAction *) node->data;
352 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
353 hildon_uri_open (popup_info->uri, action, NULL);
360 modest_platform_show_uri_popup (const gchar *uri)
362 GSList *actions_list;
367 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
368 if (actions_list != NULL) {
370 GtkWidget *menu = gtk_menu_new ();
371 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
373 popup_info->actions = actions_list;
374 popup_info->uri = g_strdup (uri);
376 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
377 GtkWidget *menu_item;
378 const gchar *action_name;
379 const gchar *translation_domain;
380 HildonURIAction *action = (HildonURIAction *) node->data;
381 action_name = hildon_uri_action_get_name (action);
382 translation_domain = hildon_uri_action_get_translation_domain (action);
383 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
384 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
385 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
388 if (hildon_uri_is_default_action (action, NULL)) {
389 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
391 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
393 gtk_widget_show (menu_item);
396 /* always add the copy item */
397 GtkWidget* menu_item = gtk_menu_item_new_with_label (dgettext("osso-uri", "uri_link_copy_link_location"));
398 g_object_set_data_full (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION,
399 g_strconcat (URI_ACTION_COPY, uri, NULL),
401 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),NULL);
402 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
403 gtk_widget_show (menu_item);
406 /* and what to do when the link is deleted */
407 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
408 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
411 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
419 modest_platform_get_icon (const gchar *name)
422 GdkPixbuf* pixbuf = NULL;
423 GtkIconTheme *current_theme = NULL;
425 g_return_val_if_fail (name, NULL);
427 /* strlen == 0 is not really an error; it just
428 * means the icon is not available
430 if (!name || strlen(name) == 0)
433 #if 0 /* do we still need this? */
434 if (g_str_has_suffix (name, ".png")) { /*FIXME: hack*/
435 pixbuf = gdk_pixbuf_new_from_file (name, &err);
437 g_printerr ("modest: error loading icon '%s': %s\n",
445 current_theme = gtk_icon_theme_get_default ();
446 pixbuf = gtk_icon_theme_load_icon (current_theme, name, 26,
447 GTK_ICON_LOOKUP_NO_SVG,
450 g_printerr ("modest: error loading theme icon '%s': %s\n",
458 modest_platform_get_app_name (void)
460 return _("mcen_ap_name");
464 entry_insert_text (GtkEditable *editable,
473 chars = gtk_editable_get_chars (editable, 0, -1);
474 chars_length = g_utf8_strlen (chars, -1);
476 /* Show WID-INF036 */
477 if (chars_length >= 20) {
478 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
479 _CS("ckdg_ib_maximum_characters_reached"));
481 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
485 tmp = g_strndup (folder_name_forbidden_chars,
486 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
487 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
488 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
493 /* Write the text in the entry if it's valid */
494 g_signal_handlers_block_by_func (editable,
495 (gpointer) entry_insert_text, data);
496 gtk_editable_insert_text (editable, text, length, position);
497 g_signal_handlers_unblock_by_func (editable,
498 (gpointer) entry_insert_text, data);
501 /* Do not allow further processing */
502 g_signal_stop_emission_by_name (editable, "insert_text");
506 entry_changed (GtkEditable *editable,
510 GtkWidget *ok_button;
513 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
514 ok_button = GTK_WIDGET (buttons->next->data);
516 chars = gtk_editable_get_chars (editable, 0, -1);
517 g_return_if_fail (chars != NULL);
520 if (g_utf8_strlen (chars,-1) >= 21)
521 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
522 _CS("ckdg_ib_maximum_characters_reached"));
524 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
527 g_list_free (buttons);
532 launch_sort_headers_dialog (GtkWindow *parent_window,
533 HildonSortDialog *dialog)
535 ModestHeaderView *header_view = NULL;
537 GtkSortType sort_type;
539 gint default_key = 0;
541 gboolean outgoing = FALSE;
542 gint current_sort_colid = -1;
543 GtkSortType current_sort_type;
544 gint attachments_sort_id;
545 gint priority_sort_id;
546 GtkTreeSortable *sortable;
548 /* Get header window */
549 if (MODEST_IS_MAIN_WINDOW (parent_window)) {
550 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_window),
551 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
553 if (!header_view) return;
555 /* Add sorting keys */
556 cols = modest_header_view_get_columns (header_view);
557 if (cols == NULL) return;
558 int sort_model_ids[6];
562 outgoing = (GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cols->data), MODEST_HEADER_VIEW_COLUMN))==
563 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT);
565 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_sender_recipient"));
567 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
568 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
570 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
571 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
574 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_date"));
576 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
577 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE;
579 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
580 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE;
582 default_key = sort_key;
584 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_subject"));
585 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
587 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
589 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
591 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_attachment"));
592 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
593 sort_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
594 attachments_sort_id = sort_key;
596 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_size"));
597 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN;
598 sort_ids[sort_key] = 0;
600 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_priority"));
601 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
602 sort_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY;
603 priority_sort_id = sort_key;
605 sortable = GTK_TREE_SORTABLE (gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)))));
607 if (!gtk_tree_sortable_get_sort_column_id (sortable,
608 ¤t_sort_colid, ¤t_sort_type)) {
609 hildon_sort_dialog_set_sort_key (dialog, default_key);
610 hildon_sort_dialog_set_sort_order (dialog, GTK_SORT_DESCENDING);
612 hildon_sort_dialog_set_sort_order (dialog, current_sort_type);
613 if (current_sort_colid == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
614 gpointer flags_sort_type_pointer;
615 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), MODEST_HEADER_VIEW_FLAG_SORT);
616 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY)
617 hildon_sort_dialog_set_sort_key (dialog, priority_sort_id);
619 hildon_sort_dialog_set_sort_key (dialog, attachments_sort_id);
621 gint current_sort_keyid = 0;
622 while (current_sort_keyid < 6) {
623 if (sort_model_ids[current_sort_keyid] == current_sort_colid)
626 current_sort_keyid++;
628 hildon_sort_dialog_set_sort_key (dialog, current_sort_keyid);
632 result = gtk_dialog_run (GTK_DIALOG (dialog));
633 if (result == GTK_RESPONSE_OK) {
634 sort_key = hildon_sort_dialog_get_sort_key (dialog);
635 sort_type = hildon_sort_dialog_get_sort_order (dialog);
636 if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
637 g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
638 GINT_TO_POINTER (sort_ids[sort_key]));
639 /* This is a hack to make it resort rows always when flag fields are
640 * selected. If we do not do this, changing sort field from priority to
641 * attachments does not work */
642 modest_header_view_sort_by_column_id (header_view, 0, sort_type);
644 gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data),
645 sort_model_ids[sort_key]);
648 modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
649 gtk_tree_sortable_sort_column_changed (sortable);
652 modest_widget_memory_save (modest_runtime_get_conf (),
653 G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
655 /* while (gtk_events_pending ()) */
656 /* gtk_main_iteration (); */
665 on_response (GtkDialog *dialog,
669 GList *child_vbox, *child_hbox;
670 GtkWidget *hbox, *entry;
671 TnyFolderStore *parent;
673 if (response != GTK_RESPONSE_ACCEPT)
677 child_vbox = gtk_container_get_children (GTK_CONTAINER (dialog->vbox));
678 hbox = child_vbox->data;
679 child_hbox = gtk_container_get_children (GTK_CONTAINER (hbox));
680 entry = child_hbox->next->data;
682 parent = TNY_FOLDER_STORE (user_data);
684 /* Look for another folder with the same name */
685 if (modest_tny_folder_has_subfolder_with_name (parent,
686 gtk_entry_get_text (GTK_ENTRY (entry)))) {
688 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
689 NULL, _CS("ckdg_ib_folder_already_exists"));
690 /* Select the text */
691 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
692 gtk_widget_grab_focus (entry);
693 /* Do not close the dialog */
694 g_signal_stop_emission_by_name (dialog, "response");
701 modest_platform_run_folder_name_dialog (GtkWindow *parent_window,
702 TnyFolderStore *parent,
703 const gchar *dialog_title,
704 const gchar *label_text,
705 const gchar *suggested_name,
708 GtkWidget *accept_btn = NULL;
709 GtkWidget *dialog, *entry, *label, *hbox;
710 GList *buttons = NULL;
713 /* Ask the user for the folder name */
714 dialog = gtk_dialog_new_with_buttons (dialog_title,
716 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
717 _("mcen_bd_dialog_ok"),
719 _("mcen_bd_dialog_cancel"),
723 /* Add accept button (with unsensitive handler) */
724 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
725 accept_btn = GTK_WIDGET (buttons->next->data);
726 /* Create label and entry */
727 label = gtk_label_new (label_text);
728 /* TODO: check that the suggested name does not exist */
729 /* We set 21 as maximum because we want to show WID-INF036
730 when the user inputs more that 20 */
731 entry = gtk_entry_new_with_max_length (21);
733 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
735 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
736 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
738 /* Connect to the response method to avoid closing the dialog
739 when an invalid name is selected*/
740 g_signal_connect (dialog,
742 G_CALLBACK (on_response),
745 /* Track entry changes */
746 g_signal_connect (entry,
748 G_CALLBACK (entry_insert_text),
750 g_signal_connect (entry,
752 G_CALLBACK (entry_changed),
755 /* Create the hbox */
756 hbox = gtk_hbox_new (FALSE, 12);
757 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, FALSE, 0);
758 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, FALSE, 0);
760 /* Add hbox to dialog */
761 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
762 hbox, FALSE, FALSE, 0);
764 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
765 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
767 result = gtk_dialog_run (GTK_DIALOG(dialog));
768 if (result == GTK_RESPONSE_ACCEPT)
769 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
771 gtk_widget_destroy (dialog);
773 while (gtk_events_pending ())
774 gtk_main_iteration ();
780 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
781 TnyFolderStore *parent_folder,
782 gchar *suggested_name,
785 gchar *real_suggested_name = NULL;
788 if(suggested_name == NULL)
790 const gchar *default_name = _("mcen_ia_default_folder_name");
794 for(i = 0; i < 100; ++ i) {
795 gboolean exists = FALSE;
797 sprintf(num_str, "%.2u", i);
800 real_suggested_name = g_strdup (default_name);
802 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
805 exists = modest_tny_folder_has_subfolder_with_name (parent_folder,
806 real_suggested_name);
811 g_free (real_suggested_name);
814 /* Didn't find a free number */
816 real_suggested_name = g_strdup (default_name);
818 real_suggested_name = suggested_name;
821 result = modest_platform_run_folder_name_dialog (parent_window,
823 _("mcen_ti_new_folder"),
824 _("mcen_fi_new_folder_name"),
827 if (suggested_name == NULL)
828 g_free(real_suggested_name);
834 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
835 TnyFolderStore *parent_folder,
836 const gchar *suggested_name,
839 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
841 return modest_platform_run_folder_name_dialog (parent_window,
843 _HL("ckdg_ti_rename_folder"),
844 _HL("ckdg_fi_rename_name"),
852 on_destroy_dialog (GtkDialog *dialog)
854 if (dialog == modest_window_mgr_get_modal_dialog (modest_runtime_get_window_mgr()))
855 modest_window_mgr_set_modal_dialog (modest_runtime_get_window_mgr(),
857 gtk_widget_destroy (GTK_WIDGET(dialog));
861 /* is there already a modal dialog? if so, return TRUE, if not set this
862 * dialog to be the registered one */
864 check_modal_and_set_maybe (GtkDialog *dialog)
866 GtkDialog *old_modal;
869 modest_window_mgr_get_modal_dialog (modest_runtime_get_window_mgr());
872 gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
874 /* un-modalize the old one; the one on top should be the
876 gtk_window_set_modal (GTK_WINDOW(old_modal), FALSE);
877 gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
880 /* this will be the new modal dialog */
881 modest_window_mgr_set_modal_dialog (modest_runtime_get_window_mgr(),
886 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
887 const gchar *message)
892 dialog = hildon_note_new_confirmation (parent_window, message);
893 check_modal_and_set_maybe (GTK_DIALOG(dialog));
895 response = gtk_dialog_run (GTK_DIALOG (dialog));
897 on_destroy_dialog (GTK_DIALOG(dialog));
899 while (gtk_events_pending ())
900 gtk_main_iteration ();
906 modest_platform_run_yes_no_dialog (GtkWindow *parent_window,
907 const gchar *message)
912 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
913 _("mcen_bd_yes"), GTK_RESPONSE_YES,
914 _("mcen_bd_no"), GTK_RESPONSE_NO,
916 check_modal_and_set_maybe (GTK_DIALOG(dialog));
917 response = gtk_dialog_run (GTK_DIALOG (dialog));
919 on_destroy_dialog (GTK_DIALOG(dialog));
921 while (gtk_events_pending ())
922 gtk_main_iteration ();
930 modest_platform_run_information_dialog (GtkWindow *parent_window,
931 const gchar *message)
935 note = hildon_note_new_information (parent_window, message);
936 check_modal_and_set_maybe (GTK_DIALOG(note));
938 g_signal_connect_swapped (note,
940 G_CALLBACK (on_destroy_dialog),
943 gtk_widget_show_all (note);
954 on_idle_connect_and_wait(gpointer user_data)
956 printf ("DEBUG: %s:\n", __FUNCTION__);
957 TnyDevice *device = modest_runtime_get_device();
958 if (!tny_device_is_online (device)) {
960 /* This is a GDK lock because we are an idle callback and
961 * tny_maemo_conic_device_connect can contain Gtk+ code */
963 gdk_threads_enter(); /* CHECKED */
964 tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), NULL);
965 gdk_threads_leave(); /* CHECKED */
968 /* Allow the function that requested this idle callback to continue: */
969 UtilIdleData *data = (UtilIdleData*)user_data;
971 g_main_loop_quit (data->loop);
973 return FALSE; /* Don't call this again. */
976 static gboolean connect_request_in_progress = FALSE;
978 /* This callback is used when connect_and_wait() is already queued as an idle callback.
979 * This can happen because the gtk_dialog_run() for the connection dialog
980 * (at least in the fake scratchbox version) allows idle handlers to keep running.
983 on_idle_wait_for_previous_connect_to_finish(gpointer user_data)
985 gboolean result = FALSE;
986 TnyDevice *device = modest_runtime_get_device();
987 if (tny_device_is_online (device))
988 result = FALSE; /* Stop trying. */
990 /* Keep trying until connect_request_in_progress is FALSE. */
991 if (connect_request_in_progress)
992 result = TRUE; /* Keep trying */
994 printf ("DEBUG: %s: other idle has finished.\n", __FUNCTION__);
996 result = FALSE; /* Stop trying, now that a result should be available. */
1000 if (result == FALSE) {
1001 /* Allow the function that requested this idle callback to continue: */
1002 UtilIdleData *data = (UtilIdleData*)user_data;
1004 g_main_loop_quit (data->loop);
1011 set_account_to_online (TnyAccount *account)
1013 /* TODO: This is necessary to prevent a cancel of the password dialog
1014 * from making a restart necessary to be asked the password again,
1015 * but it causes a hang:
1018 if (account && TNY_IS_CAMEL_STORE_ACCOUNT (account)) {
1019 /* Make sure that store accounts are online too,
1020 * because tinymail sets accounts to offline if
1021 * a password dialog is ever cancelled.
1022 * We don't do this for transport accounts because
1023 * a) They fundamentally need network access, so they can't really be offline.
1024 * b) That might cause a transport connection to happen too early.
1027 /* The last argument is user_data, the NULL before that is the callback */
1028 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE, NULL, NULL);
1034 modest_platform_connect_and_wait (GtkWindow *parent_window, TnyAccount *account)
1036 if (connect_request_in_progress)
1039 printf ("DEBUG: %s:\n", __FUNCTION__);
1040 TnyDevice *device = modest_runtime_get_device();
1042 if (tny_device_is_online (device)) {
1043 printf ("DEBUG: %s: Already online.\n", __FUNCTION__);
1044 set_account_to_online (account);
1048 printf ("DEBUG: %s: tny_device_is_online() returned FALSE\n", __FUNCTION__);
1051 /* This blocks on the result: */
1052 UtilIdleData *data = g_slice_new0 (UtilIdleData);
1054 GMainContext *context = NULL; /* g_main_context_new (); */
1055 data->loop = g_main_loop_new (context, FALSE /* not running */);
1057 /* Cause the function to be run in an idle-handler, which is always
1058 * in the main thread:
1060 if (!connect_request_in_progress) {
1061 printf ("DEBUG: %s: First request\n", __FUNCTION__);
1062 connect_request_in_progress = TRUE;
1063 g_idle_add (&on_idle_connect_and_wait, data);
1066 printf ("DEBUG: %s: nth request\n", __FUNCTION__);
1067 g_idle_add_full (G_PRIORITY_LOW, &on_idle_wait_for_previous_connect_to_finish, data, NULL);
1070 /* This main loop will run until the idle handler has stopped it: */
1071 printf ("DEBUG: %s: before g_main_loop_run()\n", __FUNCTION__);
1072 GDK_THREADS_LEAVE();
1073 g_main_loop_run (data->loop);
1074 GDK_THREADS_ENTER();
1075 printf ("DEBUG: %s: after g_main_loop_run()\n", __FUNCTION__);
1076 connect_request_in_progress = FALSE;
1077 printf ("DEBUG: %s: Finished\n", __FUNCTION__);
1078 g_main_loop_unref (data->loop);
1079 /* g_main_context_unref (context); */
1081 g_slice_free (UtilIdleData, data);
1083 const gboolean result = tny_device_is_online (device);
1086 set_account_to_online (account);
1093 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1095 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1096 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1097 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1098 /* This must be a maildir account, which does not require a connection: */
1103 return modest_platform_connect_and_wait (parent_window, account);
1107 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1110 return TRUE; /* Maybe it is something local. */
1112 gboolean result = TRUE;
1113 if (TNY_IS_FOLDER (folder_store)) {
1114 /* Get the folder's parent account: */
1115 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1116 if (account != NULL) {
1117 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1118 g_object_unref (account);
1120 } else if (TNY_IS_ACCOUNT (folder_store)) {
1121 /* Use the folder store as an account: */
1122 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1129 modest_platform_is_network_folderstore (TnyFolderStore *folder_store)
1131 TnyAccount *account = NULL;
1132 gboolean result = TRUE;
1134 g_return_val_if_fail(TNY_IS_FOLDER_STORE(folder_store), FALSE);
1136 if (TNY_IS_FOLDER (folder_store)) {
1137 /* Get the folder's parent account: */
1138 account = tny_folder_get_account(TNY_FOLDER(folder_store));
1139 } else if (TNY_IS_ACCOUNT (folder_store)) {
1140 account = TNY_ACCOUNT(folder_store);
1141 g_object_ref(account);
1144 if (account != NULL) {
1145 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1146 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1147 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1148 /* This must be a maildir account, which does
1149 * not require a connection: */
1153 g_object_unref (account);
1162 modest_platform_run_sort_dialog (GtkWindow *parent_window,
1163 ModestSortDialogType type)
1165 GtkWidget *dialog = NULL;
1168 dialog = hildon_sort_dialog_new (parent_window);
1169 check_modal_and_set_maybe (GTK_DIALOG(dialog));
1171 /* Fill sort keys */
1173 case MODEST_SORT_HEADERS:
1174 launch_sort_headers_dialog (parent_window,
1175 HILDON_SORT_DIALOG(dialog));
1180 on_destroy_dialog (GTK_DIALOG(dialog));
1185 modest_platform_set_update_interval (guint minutes)
1187 ModestConf *conf = modest_runtime_get_conf ();
1191 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1193 /* Delete any existing alarm,
1194 * because we will replace it: */
1196 /* TODO: What does the alarm_event_del() return value mean? */
1197 alarm_event_del(alarm_cookie);
1199 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1202 /* 0 means no updates: */
1207 /* Register alarm: */
1209 /* Set the interval in alarm_event_t structure: */
1210 alarm_event_t *event = g_new0(alarm_event_t, 1);
1211 event->alarm_time = minutes * 60; /* seconds */
1213 /* Set recurrence every few minutes: */
1214 event->recurrence = minutes;
1215 event->recurrence_count = -1; /* Means infinite */
1217 /* Specify what should happen when the alarm happens:
1218 * It should call this D-Bus method: */
1220 event->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1221 event->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1222 event->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1223 event->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1225 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1226 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1227 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1228 * This is why we want to use the Alarm API instead of just g_timeout_add().
1229 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1231 event->flags = ALARM_EVENT_NO_DIALOG | ALARM_EVENT_ACTIVATION;
1233 alarm_cookie = alarm_event_add (event);
1236 alarm_event_free (event);
1238 /* Store the alarm ID in GConf, so we can remove it later:
1239 * This is apparently valid between application instances. */
1240 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1242 if (!alarm_cookie) {
1244 const alarm_error_t alarm_error = alarmd_get_error ();
1245 g_debug ("Error setting alarm event. Error code: '%d'\n", alarm_error);
1247 /* Give people some clue: */
1248 /* The alarm API should have a function for this: */
1249 if (alarm_error == ALARMD_ERROR_DBUS) {
1250 g_debug (" ALARMD_ERROR_DBUS: An error with D-Bus occurred, probably coudn't get a D-Bus connection.\n");
1251 } else if (alarm_error == ALARMD_ERROR_CONNECTION) {
1252 g_debug (" ALARMD_ERROR_CONNECTION: Could not contact alarmd via D-Bus.\n");
1253 } else if (alarm_error == ALARMD_ERROR_INTERNAL) {
1254 g_debug (" ALARMD_ERROR_INTERNAL: Some alarmd or libalarm internal error, possibly a version mismatch.\n");
1255 } else if (alarm_error == ALARMD_ERROR_MEMORY) {
1256 g_debug (" ALARMD_ERROR_MEMORY: A memory allocation failed.\n");
1257 } else if (alarm_error == ALARMD_ERROR_ARGUMENT) {
1258 g_debug (" ALARMD_ERROR_ARGUMENT: An argument given by caller was invalid.\n");
1259 } else if (alarm_error == ALARMD_ERROR_NOT_RUNNING) {
1260 g_debug (" ALARMD_ERROR_NOT_RUNNING: alarmd is not running.\n");
1270 modest_platform_get_global_settings_dialog ()
1272 return modest_maemo_global_settings_dialog_new ();
1276 modest_platform_on_new_header_received (TnyHeader *header)
1278 #ifdef MODEST_HAVE_HILDON_NOTIFY
1279 HildonNotification *notification;
1281 TnyFolder *folder = NULL;
1282 const gchar *subject;
1284 subject = tny_header_get_subject (header);
1285 if (!subject || strlen(subject) == 0)
1286 subject = _("mail_va_no_subject");
1288 notification = hildon_notification_new (tny_header_get_from (header),
1290 "qgn_list_messagin",
1293 folder = tny_header_get_folder (header);
1294 url = g_strdup_printf ("%s/%s",
1295 tny_folder_get_url_string (folder),
1296 tny_header_get_uid (header));
1297 g_object_unref (folder);
1299 hildon_notification_add_dbus_action(notification,
1302 MODEST_DBUS_SERVICE,
1305 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1310 /* Play sound if the user wants */
1311 if (modest_conf_get_bool (modest_runtime_get_conf (),
1312 MODEST_CONF_PLAY_SOUND_MSG_ARRIVE,
1314 hildon_notification_set_sound (HILDON_NOTIFICATION(notification),
1315 "/usr/share/sounds/ui-new_email.wav");
1318 /* Set the led pattern */
1319 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION(notification),
1321 notify_notification_set_hint_string(NOTIFY_NOTIFICATION(notification),
1323 "PatternCommunicationEmail");
1325 /* Notify. We need to do this in an idle because this function
1326 could be called from a thread */
1327 if (!notify_notification_show (NOTIFY_NOTIFICATION(notification), NULL))
1328 g_error ("Failed to send notification");
1330 g_object_unref (notification);
1331 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1336 modest_platform_show_help (GtkWindow *parent_window,
1337 const gchar *help_id)
1339 osso_return_t result;
1341 g_return_if_fail (help_id);
1342 g_return_if_fail (osso_context);
1345 #ifdef MODEST_HAVE_OSSO_HELP
1346 result = ossohelp_show (osso_context, help_id, OSSO_HELP_SHOW_DIALOG);
1348 result = hildon_help_show (osso_context, help_id, OSSO_HELP_SHOW_DIALOG);
1351 if (result != OSSO_OK) {
1353 error_msg = g_strdup_printf ("FIXME The help topic %s could not be found", help_id);
1354 hildon_banner_show_information (GTK_WIDGET (parent_window),
1362 modest_platform_show_search_messages (GtkWindow *parent_window)
1364 osso_return_t result = OSSO_ERROR;
1366 result = osso_rpc_run_with_defaults (osso_context, "osso_global_search", "search_email", NULL, DBUS_TYPE_INVALID);
1368 if (result != OSSO_OK) {
1369 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1374 modest_platform_show_addressbook (GtkWindow *parent_window)
1376 osso_return_t result = OSSO_ERROR;
1378 result = osso_rpc_run_with_defaults (osso_context, "osso_addressbook", "top_application", NULL, DBUS_TYPE_INVALID);
1380 if (result != OSSO_OK) {
1381 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1386 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1388 GtkWidget *widget = modest_folder_view_new (query);
1390 /* Show one account by default */
1391 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1392 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1395 /* Restore settings */
1396 modest_widget_memory_restore (modest_runtime_get_conf(),
1398 MODEST_CONF_FOLDER_VIEW_KEY);
1404 modest_platform_information_banner (GtkWidget *parent,
1405 const gchar *icon_name,
1408 hildon_banner_show_information (parent, icon_name, text);
1412 modest_platform_animation_banner (GtkWidget *parent,
1413 const gchar *animation_name,
1416 GtkWidget *inf_note = NULL;
1418 g_return_val_if_fail (text != NULL, NULL);
1420 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1428 TnyAccount *account;
1431 } CheckAccountIdleData;
1433 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1436 on_timeout_check_account_is_online(gpointer user_data)
1438 printf ("DEBUG: %s:\n", __FUNCTION__);
1439 CheckAccountIdleData *data = (CheckAccountIdleData*)user_data;
1442 g_warning ("%s: data is NULL.\n", __FUNCTION__);
1445 if (!(data->account)) {
1446 g_warning ("%s: data->account is NULL.\n", __FUNCTION__);
1449 if (data && data->account) {
1450 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__, tny_account_get_connection_status (data->account));
1453 gboolean stop_trying = FALSE;
1454 if (data && data->account &&
1455 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1456 * after which the account is likely to be usable, or never likely to be usable soon: */
1457 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1459 data->is_online = TRUE;
1464 /* Give up if we have tried too many times: */
1465 if (data->count_tries >= NUMBER_OF_TRIES)
1470 /* Wait for another timeout: */
1471 ++(data->count_tries);
1476 /* Allow the function that requested this idle callback to continue: */
1478 g_main_loop_quit (data->loop);
1481 g_object_unref (data->account);
1483 return FALSE; /* Don't call this again. */
1485 return TRUE; /* Call this timeout callback again. */
1489 /* Return TRUE immediately if the account is already online,
1490 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1491 * soon as the account is online, or FALSE if the account does
1492 * not become online in the NUMBER_OF_TRIES seconds.
1493 * This is useful when the D-Bus method was run immediately after
1494 * the application was started (when using D-Bus activation),
1495 * because the account usually takes a short time to go online.
1496 * The return value is maybe not very useful.
1499 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1501 g_return_val_if_fail (account, FALSE);
1503 printf ("DEBUG: %s: account id=%s\n", __FUNCTION__, tny_account_get_id (account));
1505 if (!tny_device_is_online (modest_runtime_get_device())) {
1506 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1510 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1511 * so we avoid wait unnecessarily: */
1512 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1513 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account) ) {
1517 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n",
1518 __FUNCTION__, tny_account_get_connection_status (account));
1520 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1521 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1522 * we want to avoid. */
1523 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1526 /* This blocks on the result: */
1527 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1528 data->is_online = FALSE;
1529 data->account = account;
1530 g_object_ref (data->account);
1531 data->count_tries = 0;
1533 GMainContext *context = NULL; /* g_main_context_new (); */
1534 data->loop = g_main_loop_new (context, FALSE /* not running */);
1536 g_timeout_add (1000, &on_timeout_check_account_is_online, data);
1538 /* This main loop will run until the idle handler has stopped it: */
1539 g_main_loop_run (data->loop);
1541 g_main_loop_unref (data->loop);
1542 /* g_main_context_unref (context); */
1544 g_slice_free (CheckAccountIdleData, data);
1546 return data->is_online;
1552 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1554 /* GTK_RESPONSE_HELP means we need to show the certificate */
1555 if (response_id == GTK_RESPONSE_HELP) {
1559 /* Do not close the dialog */
1560 g_signal_stop_emission_by_name (dialog, "response");
1562 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1563 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1564 gtk_dialog_run (GTK_DIALOG(note));
1565 gtk_widget_destroy (note);
1571 modest_platform_run_certificate_conformation_dialog (const gchar* server_name,
1572 const gchar *certificate)
1576 GtkWindow *main_win =
1577 (GtkWindow*)modest_window_mgr_get_main_window (modest_runtime_get_window_mgr());
1579 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1582 note = hildon_note_new_confirmation_add_buttons (
1585 _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK,
1586 _("mcen_bd_view"), GTK_RESPONSE_HELP, /* abusing this... */
1587 _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL,
1590 g_signal_connect (G_OBJECT(note), "response",
1591 G_CALLBACK(on_cert_dialog_response),
1592 (gpointer) certificate);
1594 check_modal_and_set_maybe (GTK_DIALOG(note));
1595 response = gtk_dialog_run(GTK_DIALOG(note));
1597 on_destroy_dialog (GTK_DIALOG(note));
1606 modest_platform_run_alert_dialog (const gchar* prompt,
1607 gboolean is_question)
1609 ModestWindow *main_window =
1610 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ());
1612 gboolean retval = TRUE;
1614 /* The Tinymail documentation says that we should show Yes and No buttons,
1615 * when it is a question.
1616 * Obviously, we need tinymail to use more specific error codes instead,
1617 * so we know what buttons to show. */
1618 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (main_window),
1620 check_modal_and_set_maybe (GTK_DIALOG(dialog));
1622 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1623 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1625 on_destroy_dialog (GTK_DIALOG(dialog));
1627 /* Just show the error text and use the default response: */
1628 modest_platform_run_information_dialog (GTK_WINDOW (main_window),