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"
59 #define HILDON_OSSO_URI_ACTION "uri-action"
60 #define URI_ACTION_COPY "copy:"
62 static osso_context_t *osso_context = NULL;
65 on_modest_conf_update_interval_changed (ModestConf* self,
67 ModestConfEvent event,
68 ModestConfNotificationId id,
71 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
72 const guint update_interval_minutes =
73 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
74 modest_platform_set_update_interval (update_interval_minutes);
79 modest_platform_init (int argc, char *argv[])
81 osso_hw_state_t hw_state = { 0 };
85 osso_initialize(PACKAGE,PACKAGE_VERSION,
88 g_printerr ("modest: failed to acquire osso context\n");
92 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
93 g_printerr ("modest: could not get dbus connection\n");
98 /* Add a D-Bus handler to be used when the main osso-rpc
99 * D-Bus handler has not handled something.
100 * We use this for D-Bus methods that need to use more complex types
101 * than osso-rpc supports.
103 if (!dbus_connection_add_filter (con,
104 modest_dbus_req_filter,
108 g_printerr ("modest: Could not add D-Bus filter\n");
112 /* Register our simple D-Bus callbacks, via the osso API: */
113 osso_return_t result = osso_rpc_set_cb_f(osso_context,
117 modest_dbus_req_handler, NULL /* user_data */);
118 if (result != OSSO_OK) {
119 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
123 /* Add handler for Exit D-BUS messages.
124 * Not used because osso_application_set_exit_cb() is deprecated and obsolete:
125 result = osso_application_set_exit_cb(osso_context,
126 modest_dbus_exit_event_handler,
128 if (result != OSSO_OK) {
129 g_print("Error setting exit callback (%d)\n", result);
134 /* Register hardware event dbus callback: */
135 hw_state.shutdown_ind = TRUE;
136 osso_hw_set_event_cb(osso_context, NULL,/*&hw_state*/ modest_osso_cb_hw_state_handler, NULL);
138 /* Register osso auto-save callbacks: */
139 result = osso_application_set_autosave_cb (osso_context,
140 modest_on_osso_application_autosave, NULL /* user_data */);
141 if (result != OSSO_OK) {
142 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
147 /* Make sure that the update interval is changed whenever its gconf key
149 /* CAUTION: we're not using here the
150 modest_conf_listen_to_namespace because we know that there
151 are other parts of Modest listening for this namespace, so
152 we'll receive the notifications anyway. We basically do not
153 use it because there is no easy way to do the
154 modest_conf_forget_namespace */
155 ModestConf *conf = modest_runtime_get_conf ();
156 g_signal_connect (G_OBJECT(conf),
158 G_CALLBACK (on_modest_conf_update_interval_changed),
161 /* Get the initial update interval from gconf: */
162 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
163 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
165 /* initialize the addressbook */
166 if (!osso_abook_init (&argc, &argv, osso_context)) {
167 g_printerr ("modest: failed to initialized addressbook\n");
175 modest_platform_get_new_device (void)
177 return TNY_DEVICE (tny_maemo_conic_device_new ());
182 guess_mime_type_from_name (const gchar* name)
185 const static gchar* mime_type;
186 const static gchar* mime_map[][2] = {
187 { ".note.html", "text/note"}, /* for the osso_notes program */
188 { ".deb", "application/x-deb"},
189 { ".install", "application/x-install-instructions"},
190 { ".html", "text/html"},
191 { ".htm", "text/html"},
192 { ".pdf", "application/pdf"},
193 { ".doc", "application/msword"},
194 { ".xls", "application/excel"},
195 { ".png", "image/png" },
196 { ".gif", "image/gif" },
197 { ".jpg", "image/jpeg"},
198 { ".jpeg", "image/jpeg"},
199 { ".mp3", "audio/mp3" }
202 mime_type = "application/octet-stream";
205 gchar* lc_name = g_utf8_strdown (name, -1);
206 for (i = 0; i != G_N_ELEMENTS(mime_map); ++i) {
207 if (g_str_has_suffix (lc_name, mime_map[i][0])) {
208 mime_type = mime_map[i][1];
220 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
221 gchar **effective_mime_type)
223 GString *mime_str = NULL;
224 gchar *icon_name = NULL;
225 gchar **icons, **cursor;
227 if (!mime_type || !g_ascii_strcasecmp (mime_type, "application/octet-stream"))
228 mime_str = g_string_new (guess_mime_type_from_name(name));
230 mime_str = g_string_new (mime_type);
231 g_string_ascii_down (mime_str);
234 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
235 for (cursor = icons; cursor; ++cursor) {
236 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
237 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
238 icon_name = g_strdup ("qgn_list_messagin");
240 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
241 icon_name = g_strdup (*cursor);
247 if (effective_mime_type)
248 *effective_mime_type = g_string_free (mime_str, FALSE);
250 g_string_free (mime_str, TRUE);
257 modest_platform_activate_uri (const gchar *uri)
259 HildonURIAction *action;
260 gboolean result = FALSE;
261 GSList *actions, *iter = NULL;
264 g_return_val_if_fail (uri, FALSE);
268 scheme = hildon_uri_get_scheme_from_uri (uri, NULL);
269 actions = hildon_uri_get_actions (scheme, NULL);
271 for (iter = actions; iter; iter = g_slist_next (iter)) {
272 action = (HildonURIAction*) iter->data;
273 if (action && strcmp (hildon_uri_action_get_service (action),
274 "com.nokia.modest") == 0) {
276 result = hildon_uri_open (uri, action, &err);
277 if (!result && err) {
278 g_printerr ("modest: modest_platform_activate_uri : %s",
279 err->message ? err->message : "unknown error");
286 /* if we could open it with email, try something else */
288 result = hildon_uri_open (uri, NULL, NULL);
291 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
297 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
301 gchar *uri_path = NULL;
303 uri_path = g_strconcat ("file://", path, NULL);
304 con = osso_get_dbus_connection (osso_context);
307 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
309 result = hildon_mime_open_file (con, uri_path);
311 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"));
319 } ModestPlatformPopupInfo;
322 delete_uri_popup (GtkWidget *menu,
326 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
328 g_free (popup_info->uri);
329 hildon_uri_free_actions (popup_info->actions);
335 activate_uri_popup_item (GtkMenuItem *menu_item,
339 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
340 const gchar* action_name;
342 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
344 g_printerr ("modest: no action name defined\n");
348 /* special handling for the copy menu item -- copy the uri to the clipboard */
349 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
350 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
351 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
352 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
354 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
355 action_name += strlen ("mailto:");
357 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
358 return; /* we're done */
361 /* now, the real uri-actions... */
362 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
363 HildonURIAction *action = (HildonURIAction *) node->data;
364 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
365 hildon_uri_open (popup_info->uri, action, NULL);
372 modest_platform_show_uri_popup (const gchar *uri)
375 GSList *actions_list;
380 scheme = hildon_uri_get_scheme_from_uri (uri, NULL);
381 actions_list = hildon_uri_get_actions (scheme, NULL);
382 if (actions_list != NULL) {
384 GtkWidget *menu = gtk_menu_new ();
385 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
387 popup_info->actions = actions_list;
388 popup_info->uri = g_strdup (uri);
390 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
391 GtkWidget *menu_item;
392 const gchar *action_name;
393 const gchar *translation_domain;
394 HildonURIAction *action = (HildonURIAction *) node->data;
395 action_name = hildon_uri_action_get_name (action);
396 translation_domain = hildon_uri_action_get_translation_domain (action);
397 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
398 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
399 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
402 if (hildon_uri_is_default_action (action, NULL)) {
403 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
405 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
407 gtk_widget_show (menu_item);
410 /* always add the copy item */
411 GtkWidget* menu_item = gtk_menu_item_new_with_label (dgettext("osso-uri", "uri_link_copy_link_location"));
412 g_object_set_data_full (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION,
413 g_strconcat (URI_ACTION_COPY, uri, NULL),
415 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),NULL);
416 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
417 gtk_widget_show (menu_item);
420 /* and what to do when the link is deleted */
421 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
422 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
425 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
434 modest_platform_get_icon (const gchar *name)
437 GdkPixbuf* pixbuf = NULL;
438 GtkIconTheme *current_theme = NULL;
440 g_return_val_if_fail (name, NULL);
442 /* strlen == 0 is not really an error; it just
443 * means the icon is not available
445 if (!name || strlen(name) == 0)
448 #if 0 /* do we still need this? */
449 if (g_str_has_suffix (name, ".png")) { /*FIXME: hack*/
450 pixbuf = gdk_pixbuf_new_from_file (name, &err);
452 g_printerr ("modest: error loading icon '%s': %s\n",
460 current_theme = gtk_icon_theme_get_default ();
461 pixbuf = gtk_icon_theme_load_icon (current_theme, name, 26,
462 GTK_ICON_LOOKUP_NO_SVG,
465 g_printerr ("modest: error loading theme icon '%s': %s\n",
473 modest_platform_get_app_name (void)
475 return _("mcen_ap_name");
479 entry_insert_text (GtkEditable *editable,
488 chars = gtk_editable_get_chars (editable, 0, -1);
489 chars_length = g_utf8_strlen (chars, -1);
491 /* Show WID-INF036 */
492 if (chars_length >= 20) {
493 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
494 _CS("ckdg_ib_maximum_characters_reached"));
496 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
500 tmp = g_strndup (folder_name_forbidden_chars,
501 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
502 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
503 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
508 /* Write the text in the entry if it's valid */
509 g_signal_handlers_block_by_func (editable,
510 (gpointer) entry_insert_text, data);
511 gtk_editable_insert_text (editable, text, length, position);
512 g_signal_handlers_unblock_by_func (editable,
513 (gpointer) entry_insert_text, data);
516 /* Do not allow further processing */
517 g_signal_stop_emission_by_name (editable, "insert_text");
521 entry_changed (GtkEditable *editable,
525 GtkWidget *ok_button;
528 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
529 ok_button = GTK_WIDGET (buttons->next->data);
531 chars = gtk_editable_get_chars (editable, 0, -1);
532 g_return_if_fail (chars != NULL);
535 if (g_utf8_strlen (chars,-1) >= 21)
536 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
537 _CS("ckdg_ib_maximum_characters_reached"));
539 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
542 g_list_free (buttons);
547 launch_sort_headers_dialog (GtkWindow *parent_window,
548 HildonSortDialog *dialog)
550 ModestHeaderView *header_view = NULL;
552 GtkSortType sort_type;
554 gint default_key = 0;
556 gboolean outgoing = FALSE;
557 gint current_sort_colid = -1;
558 GtkSortType current_sort_type;
559 gint attachments_sort_id;
560 gint priority_sort_id;
561 GtkTreeSortable *sortable;
563 /* Get header window */
564 if (MODEST_IS_MAIN_WINDOW (parent_window)) {
565 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_window),
566 MODEST_WIDGET_TYPE_HEADER_VIEW));
568 if (!header_view) return;
570 /* Add sorting keys */
571 cols = modest_header_view_get_columns (header_view);
572 if (cols == NULL) return;
573 int sort_model_ids[6];
577 outgoing = (GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cols->data), MODEST_HEADER_VIEW_COLUMN))==
578 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT);
580 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_sender_recipient"));
582 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
583 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
585 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
586 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
589 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_date"));
591 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
592 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE;
594 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
595 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE;
597 default_key = sort_key;
599 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_subject"));
600 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
602 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
604 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
606 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_attachment"));
607 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
608 sort_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
609 attachments_sort_id = sort_key;
611 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_size"));
612 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN;
613 sort_ids[sort_key] = 0;
615 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_priority"));
616 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
617 sort_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY;
618 priority_sort_id = sort_key;
620 sortable = GTK_TREE_SORTABLE (gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)))));
622 if (!gtk_tree_sortable_get_sort_column_id (sortable,
623 ¤t_sort_colid, ¤t_sort_type)) {
624 hildon_sort_dialog_set_sort_key (dialog, default_key);
625 hildon_sort_dialog_set_sort_order (dialog, GTK_SORT_DESCENDING);
627 hildon_sort_dialog_set_sort_order (dialog, current_sort_type);
628 if (current_sort_colid == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
629 gpointer flags_sort_type_pointer;
630 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), MODEST_HEADER_VIEW_FLAG_SORT);
631 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY)
632 hildon_sort_dialog_set_sort_key (dialog, priority_sort_id);
634 hildon_sort_dialog_set_sort_key (dialog, attachments_sort_id);
636 gint current_sort_keyid = 0;
637 while (current_sort_keyid < 6) {
638 if (sort_model_ids[current_sort_keyid] == current_sort_colid)
641 current_sort_keyid++;
643 hildon_sort_dialog_set_sort_key (dialog, current_sort_keyid);
647 result = gtk_dialog_run (GTK_DIALOG (dialog));
648 if (result == GTK_RESPONSE_OK) {
649 sort_key = hildon_sort_dialog_get_sort_key (dialog);
650 sort_type = hildon_sort_dialog_get_sort_order (dialog);
651 if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
652 g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
653 GINT_TO_POINTER (sort_ids[sort_key]));
654 /* This is a hack to make it resort rows always when flag fields are
655 * selected. If we do not do this, changing sort field from priority to
656 * attachments does not work */
657 modest_header_view_sort_by_column_id (header_view, 0, sort_type);
659 gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data),
660 sort_model_ids[sort_key]);
663 modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
664 gtk_tree_sortable_sort_column_changed (sortable);
667 modest_widget_memory_save (modest_runtime_get_conf (),
668 G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
670 /* while (gtk_events_pending ()) */
671 /* gtk_main_iteration (); */
680 on_response (GtkDialog *dialog,
684 GList *child_vbox, *child_hbox;
685 GtkWidget *hbox, *entry;
686 TnyFolderStore *parent;
688 if (response != GTK_RESPONSE_ACCEPT)
692 child_vbox = gtk_container_get_children (GTK_CONTAINER (dialog->vbox));
693 hbox = child_vbox->data;
694 child_hbox = gtk_container_get_children (GTK_CONTAINER (hbox));
695 entry = child_hbox->next->data;
697 parent = TNY_FOLDER_STORE (user_data);
699 /* Look for another folder with the same name */
700 if (modest_tny_folder_has_subfolder_with_name (parent,
701 gtk_entry_get_text (GTK_ENTRY (entry)))) {
703 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
704 NULL, _CS("ckdg_ib_folder_already_exists"));
705 /* Select the text */
706 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
707 gtk_widget_grab_focus (entry);
708 /* Do not close the dialog */
709 g_signal_stop_emission_by_name (dialog, "response");
715 modest_platform_run_folder_name_dialog (GtkWindow *parent_window,
716 TnyFolderStore *parent,
717 const gchar *dialog_title,
718 const gchar *label_text,
719 const gchar *suggested_name,
722 GtkWidget *accept_btn = NULL;
723 GtkWidget *dialog, *entry, *label, *hbox;
724 GList *buttons = NULL;
727 /* Ask the user for the folder name */
728 dialog = gtk_dialog_new_with_buttons (dialog_title,
730 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
731 _("mcen_bd_dialog_ok"),
733 _("mcen_bd_dialog_cancel"),
737 /* Add accept button (with unsensitive handler) */
738 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
739 accept_btn = GTK_WIDGET (buttons->next->data);
740 /* Create label and entry */
741 label = gtk_label_new (label_text);
742 /* TODO: check that the suggested name does not exist */
743 /* We set 21 as maximum because we want to show WID-INF036
744 when the user inputs more that 20 */
745 entry = gtk_entry_new_with_max_length (21);
747 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
749 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
750 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
752 /* Connect to the response method to avoid closing the dialog
753 when an invalid name is selected*/
754 g_signal_connect (dialog,
756 G_CALLBACK (on_response),
759 /* Track entry changes */
760 g_signal_connect (entry,
762 G_CALLBACK (entry_insert_text),
764 g_signal_connect (entry,
766 G_CALLBACK (entry_changed),
769 /* Create the hbox */
770 hbox = gtk_hbox_new (FALSE, 12);
771 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, FALSE, 0);
772 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, FALSE, 0);
774 /* Add hbox to dialog */
775 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
776 hbox, FALSE, FALSE, 0);
778 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
780 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
784 result = gtk_dialog_run (GTK_DIALOG(dialog));
785 if (result == GTK_RESPONSE_ACCEPT)
786 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
788 gtk_widget_destroy (dialog);
790 while (gtk_events_pending ())
791 gtk_main_iteration ();
797 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
798 TnyFolderStore *parent_folder,
799 gchar *suggested_name,
802 gchar *real_suggested_name = NULL;
805 if(suggested_name == NULL)
807 const gchar *default_name = _("mcen_ia_default_folder_name");
811 for(i = 0; i < 100; ++ i) {
812 gboolean exists = FALSE;
814 sprintf(num_str, "%.2u", i);
817 real_suggested_name = g_strdup (default_name);
819 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
822 exists = modest_tny_folder_has_subfolder_with_name (parent_folder,
823 real_suggested_name);
828 g_free (real_suggested_name);
831 /* Didn't find a free number */
833 real_suggested_name = g_strdup (default_name);
835 real_suggested_name = suggested_name;
838 result = modest_platform_run_folder_name_dialog (parent_window,
840 _("mcen_ti_new_folder"),
841 _("mcen_fi_new_folder_name"),
844 if (suggested_name == NULL)
845 g_free(real_suggested_name);
851 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
852 TnyFolderStore *parent_folder,
853 const gchar *suggested_name,
856 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
858 return modest_platform_run_folder_name_dialog (parent_window,
860 _HL("ckdg_ti_rename_folder"),
861 _HL("ckdg_fi_rename_name"),
867 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
868 const gchar *message)
873 dialog = hildon_note_new_confirmation (parent_window, message);
874 gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
876 response = gtk_dialog_run (GTK_DIALOG (dialog));
878 gtk_widget_destroy (GTK_WIDGET (dialog));
880 while (gtk_events_pending ())
881 gtk_main_iteration ();
887 modest_platform_run_yes_no_dialog (GtkWindow *parent_window,
888 const gchar *message)
893 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
894 _("mcen_bd_yes"), GTK_RESPONSE_YES,
895 _("mcen_bd_no"), GTK_RESPONSE_NO,
897 gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
899 response = gtk_dialog_run (GTK_DIALOG (dialog));
901 gtk_widget_destroy (GTK_WIDGET (dialog));
903 while (gtk_events_pending ())
904 gtk_main_iteration ();
910 modest_platform_run_information_dialog (GtkWindow *parent_window,
911 const gchar *message)
915 dialog = hildon_note_new_information (parent_window, message);
917 g_signal_connect_swapped (dialog,
919 G_CALLBACK (gtk_widget_destroy),
922 gtk_widget_show_all (dialog);
933 on_idle_connect_and_wait(gpointer user_data)
935 printf ("DEBUG: %s:\n", __FUNCTION__);
936 TnyDevice *device = modest_runtime_get_device();
937 if (!tny_device_is_online (device)) {
939 /* This is a GDK lock because we are an idle callback and
940 * tny_maemo_conic_device_connect can contain Gtk+ code */
942 gdk_threads_enter(); /* CHECKED */
943 tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), NULL);
944 gdk_threads_leave(); /* CHECKED */
947 /* Allow the function that requested this idle callback to continue: */
948 UtilIdleData *data = (UtilIdleData*)user_data;
950 g_main_loop_quit (data->loop);
952 return FALSE; /* Don't call this again. */
955 static gboolean connect_request_in_progress = FALSE;
957 /* This callback is used when connect_and_wait() is already queued as an idle callback.
958 * This can happen because the gtk_dialog_run() for the connection dialog
959 * (at least in the fake scratchbox version) allows idle handlers to keep running.
962 on_idle_wait_for_previous_connect_to_finish(gpointer user_data)
964 gboolean result = FALSE;
965 TnyDevice *device = modest_runtime_get_device();
966 if (tny_device_is_online (device))
967 result = FALSE; /* Stop trying. */
969 /* Keep trying until connect_request_in_progress is FALSE. */
970 if (connect_request_in_progress)
971 result = TRUE; /* Keep trying */
973 printf ("DEBUG: %s: other idle has finished.\n", __FUNCTION__);
975 result = FALSE; /* Stop trying, now that a result should be available. */
979 if (result == FALSE) {
980 /* Allow the function that requested this idle callback to continue: */
981 UtilIdleData *data = (UtilIdleData*)user_data;
983 g_main_loop_quit (data->loop);
990 set_account_to_online (TnyAccount *account)
992 /* TODO: This is necessary to prevent a cancel of the password dialog
993 * from making a restart necessary to be asked the password again,
994 * but it causes a hang:
997 if (account && TNY_IS_CAMEL_STORE_ACCOUNT (account)) {
998 /* Make sure that store accounts are online too,
999 * because tinymail sets accounts to offline if
1000 * a password dialog is ever cancelled.
1001 * We don't do this for transport accounts because
1002 * a) They fundamentally need network access, so they can't really be offline.
1003 * b) That might cause a transport connection to happen too early.
1005 GError *error = NULL;
1006 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE, &error);
1008 g_warning ("%s: tny_camel_account_set_online() returned a GError:\n %s\n",
1009 __FUNCTION__, error->message);
1010 g_error_free (error);
1016 gboolean modest_platform_connect_and_wait (GtkWindow *parent_window, TnyAccount *account)
1018 if (connect_request_in_progress)
1021 printf ("DEBUG: %s:\n", __FUNCTION__);
1022 TnyDevice *device = modest_runtime_get_device();
1024 if (tny_device_is_online (device)) {
1025 printf ("DEBUG: %s: Already online.\n", __FUNCTION__);
1026 set_account_to_online (account);
1030 printf ("DEBUG: %s: tny_device_is_online() returned FALSE\n", __FUNCTION__);
1033 /* This blocks on the result: */
1034 UtilIdleData *data = g_slice_new0 (UtilIdleData);
1036 GMainContext *context = NULL; /* g_main_context_new (); */
1037 data->loop = g_main_loop_new (context, FALSE /* not running */);
1039 /* Cause the function to be run in an idle-handler, which is always
1040 * in the main thread:
1042 if (!connect_request_in_progress) {
1043 printf ("DEBUG: %s: First request\n", __FUNCTION__);
1044 connect_request_in_progress = TRUE;
1045 g_idle_add (&on_idle_connect_and_wait, data);
1048 printf ("DEBUG: %s: nth request\n", __FUNCTION__);
1049 g_idle_add_full (G_PRIORITY_LOW, &on_idle_wait_for_previous_connect_to_finish, data, NULL);
1052 /* This main loop will run until the idle handler has stopped it: */
1053 printf ("DEBUG: %s: before g_main_loop_run()\n", __FUNCTION__);
1054 GDK_THREADS_LEAVE();
1055 g_main_loop_run (data->loop);
1056 GDK_THREADS_ENTER();
1057 printf ("DEBUG: %s: after g_main_loop_run()\n", __FUNCTION__);
1058 connect_request_in_progress = FALSE;
1059 printf ("DEBUG: %s: Finished\n", __FUNCTION__);
1060 g_main_loop_unref (data->loop);
1061 /* g_main_context_unref (context); */
1063 g_slice_free (UtilIdleData, data);
1065 const gboolean result = tny_device_is_online (device);
1068 set_account_to_online (account);
1074 gboolean modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1076 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1077 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1078 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1079 /* This must be a maildir account, which does not require a connection: */
1084 return modest_platform_connect_and_wait (parent_window, account);
1087 gboolean modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1090 return TRUE; /* Maybe it is something local. */
1092 gboolean result = TRUE;
1093 if (TNY_IS_FOLDER (folder_store)) {
1094 /* Get the folder's parent account: */
1095 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1096 if (account != NULL) {
1097 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1098 g_object_unref (account);
1100 } else if (TNY_IS_ACCOUNT (folder_store)) {
1101 /* Use the folder store as an account: */
1102 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1108 gboolean modest_platform_is_network_folderstore (TnyFolderStore *folder_store)
1110 TnyAccount *account = NULL;
1111 gboolean result = TRUE;
1113 g_return_val_if_fail(TNY_IS_FOLDER_STORE(folder_store), FALSE);
1115 if (TNY_IS_FOLDER (folder_store)) {
1116 /* Get the folder's parent account: */
1117 account = tny_folder_get_account(TNY_FOLDER(folder_store));
1118 } else if (TNY_IS_ACCOUNT (folder_store)) {
1119 account = TNY_ACCOUNT(folder_store);
1120 g_object_ref(account);
1123 if (account != NULL) {
1124 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1125 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1126 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1127 /* This must be a maildir account, which does
1128 * not require a connection: */
1132 g_object_unref (account);
1141 modest_platform_run_sort_dialog (GtkWindow *parent_window,
1142 ModestSortDialogType type)
1144 GtkWidget *dialog = NULL;
1147 dialog = hildon_sort_dialog_new (parent_window);
1148 gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
1150 /* Fill sort keys */
1152 case MODEST_SORT_HEADERS:
1153 launch_sort_headers_dialog (parent_window,
1154 HILDON_SORT_DIALOG(dialog));
1159 gtk_widget_destroy (GTK_WIDGET (dialog));
1163 gboolean modest_platform_set_update_interval (guint minutes)
1165 ModestConf *conf = modest_runtime_get_conf ();
1169 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1171 /* Delete any existing alarm,
1172 * because we will replace it: */
1174 /* TODO: What does the alarm_event_del() return value mean? */
1175 alarm_event_del(alarm_cookie);
1177 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1180 /* 0 means no updates: */
1185 /* Register alarm: */
1187 /* Set the interval in alarm_event_t structure: */
1188 alarm_event_t *event = g_new0(alarm_event_t, 1);
1189 event->alarm_time = minutes * 60; /* seconds */
1191 /* Set recurrence every few minutes: */
1192 event->recurrence = minutes;
1193 event->recurrence_count = -1; /* Means infinite */
1195 /* Specify what should happen when the alarm happens:
1196 * It should call this D-Bus method: */
1198 event->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1199 event->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1200 event->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1201 event->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1203 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1204 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1205 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1206 * This is why we want to use the Alarm API instead of just g_timeout_add().
1207 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1209 event->flags = ALARM_EVENT_NO_DIALOG | ALARM_EVENT_ACTIVATION;
1211 alarm_cookie = alarm_event_add (event);
1214 alarm_event_free (event);
1216 /* Store the alarm ID in GConf, so we can remove it later:
1217 * This is apparently valid between application instances. */
1218 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1220 if (!alarm_cookie) {
1222 const alarm_error_t alarm_error = alarmd_get_error ();
1223 g_debug ("Error setting alarm event. Error code: '%d'\n", alarm_error);
1225 /* Give people some clue: */
1226 /* The alarm API should have a function for this: */
1227 if (alarm_error == ALARMD_ERROR_DBUS) {
1228 g_debug (" ALARMD_ERROR_DBUS: An error with D-Bus occurred, probably coudn't get a D-Bus connection.\n");
1229 } else if (alarm_error == ALARMD_ERROR_CONNECTION) {
1230 g_debug (" ALARMD_ERROR_CONNECTION: Could not contact alarmd via D-Bus.\n");
1231 } else if (alarm_error == ALARMD_ERROR_INTERNAL) {
1232 g_debug (" ALARMD_ERROR_INTERNAL: Some alarmd or libalarm internal error, possibly a version mismatch.\n");
1233 } else if (alarm_error == ALARMD_ERROR_MEMORY) {
1234 g_debug (" ALARMD_ERROR_MEMORY: A memory allocation failed.\n");
1235 } else if (alarm_error == ALARMD_ERROR_ARGUMENT) {
1236 g_debug (" ALARMD_ERROR_ARGUMENT: An argument given by caller was invalid.\n");
1237 } else if (alarm_error == ALARMD_ERROR_NOT_RUNNING) {
1238 g_debug (" ALARMD_ERROR_NOT_RUNNING: alarmd is not running.\n");
1248 modest_platform_get_global_settings_dialog ()
1250 return modest_maemo_global_settings_dialog_new ();
1254 modest_platform_on_new_msg (void)
1256 #ifdef MODEST_HAVE_HILDON_NOTIFY
1257 HildonNotification *not;
1259 /* Create a new notification. TODO: per-mail data needed */
1260 not = hildon_notification_new ("TODO: (new email) Summary",
1261 "TODO: (new email) Description",
1262 "qgn_list_messagin_mail_unread",
1265 hildon_notification_add_dbus_action(not,
1268 MODEST_DBUS_SERVICE,
1271 MODEST_DBUS_METHOD_OPEN_DEFAULT_INBOX,
1274 /* Play sound SR-SND-18 */
1275 hildon_notification_set_sound
1276 (not, "/usr/share/sounds/ui-new_email.wav");
1277 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (not), "dialog-type", 4);
1279 /* Set the led pattern */
1280 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (not),
1282 "PatternCommunicationEmail");
1284 /* Notify. We need to do this in an idle because this function
1285 could be called from a thread */
1286 if (!notify_notification_show (NOTIFY_NOTIFICATION (not), NULL))
1287 g_error ("Failed to send notification");
1289 g_object_unref (not);
1290 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1295 modest_platform_show_help (GtkWindow *parent_window,
1296 const gchar *help_id)
1298 osso_return_t result;
1300 g_return_if_fail (help_id);
1301 g_return_if_fail (osso_context);
1304 #ifdef MODEST_HAVE_OSSO_HELP
1305 result = ossohelp_show (osso_context, help_id, OSSO_HELP_SHOW_DIALOG);
1307 result = hildon_help_show (osso_context, help_id, OSSO_HELP_SHOW_DIALOG);
1310 if (result != OSSO_OK) {
1312 error_msg = g_strdup_printf ("FIXME The help topic %s could not be found", help_id);
1313 hildon_banner_show_information (GTK_WIDGET (parent_window),
1321 modest_platform_show_search_messages (GtkWindow *parent_window)
1323 osso_return_t result = OSSO_ERROR;
1325 result = osso_rpc_run_with_defaults (osso_context, "osso_global_search", "search_email", NULL, DBUS_TYPE_INVALID);
1327 if (result != OSSO_OK) {
1328 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1333 modest_platform_show_addressbook (GtkWindow *parent_window)
1335 osso_return_t result = OSSO_ERROR;
1337 result = osso_rpc_run_with_defaults (osso_context, "osso_addressbook", "top_application", NULL, DBUS_TYPE_INVALID);
1339 if (result != OSSO_OK) {
1340 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1345 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1347 GtkWidget *widget = modest_folder_view_new (query);
1349 /* Show one account by default */
1350 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1351 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1354 /* Restore settings */
1355 modest_widget_memory_restore (modest_runtime_get_conf(),
1357 MODEST_CONF_FOLDER_VIEW_KEY);
1363 modest_platform_information_banner (GtkWidget *parent,
1364 const gchar *icon_name,
1367 hildon_banner_show_information (parent, icon_name, text);
1371 modest_platform_animation_banner (GtkWidget *parent,
1372 const gchar *animation_name,
1375 GtkWidget *inf_note = NULL;
1377 g_return_val_if_fail (text != NULL, NULL);
1379 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1387 TnyAccount *account;
1390 } CheckAccountIdleData;
1392 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1395 on_timeout_check_account_is_online(gpointer user_data)
1397 printf ("DEBUG: %s:\n", __FUNCTION__);
1398 CheckAccountIdleData *data = (CheckAccountIdleData*)user_data;
1401 g_warning ("%s: data is NULL.\n", __FUNCTION__);
1404 if (!(data->account)) {
1405 g_warning ("%s: data->account is NULL.\n", __FUNCTION__);
1408 if (data && data->account) {
1409 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__, tny_account_get_connection_status (data->account));
1412 gboolean stop_trying = FALSE;
1413 if (data && data->account &&
1414 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1415 * after which the account is likely to be usable, or never likely to be usable soon: */
1416 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1418 data->is_online = TRUE;
1423 /* Give up if we have tried too many times: */
1424 if (data->count_tries >= NUMBER_OF_TRIES)
1429 /* Wait for another timeout: */
1430 ++(data->count_tries);
1435 /* Allow the function that requested this idle callback to continue: */
1437 g_main_loop_quit (data->loop);
1440 g_object_unref (data->account);
1442 return FALSE; /* Don't call this again. */
1444 return TRUE; /* Call this timeout callback again. */
1448 /* Return TRUE immediately if the account is already online,
1449 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1450 * soon as the account is online, or FALSE if the account does
1451 * not become online in the NUMBER_OF_TRIES seconds.
1452 * This is useful when the D-Bus method was run immediately after
1453 * the application was started (when using D-Bus activation),
1454 * because the account usually takes a short time to go online.
1455 * The return value is maybe not very useful.
1458 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1460 g_return_val_if_fail (account, FALSE);
1462 printf ("DEBUG: %s: account id=%s\n", __FUNCTION__, tny_account_get_id (account));
1464 if (!tny_device_is_online (modest_runtime_get_device())) {
1465 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1469 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1470 * so we avoid wait unnecessarily: */
1471 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1472 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account) ) {
1476 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n",
1477 __FUNCTION__, tny_account_get_connection_status (account));
1479 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1480 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1481 * we want to avoid. */
1482 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1485 /* This blocks on the result: */
1486 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1487 data->is_online = FALSE;
1488 data->account = account;
1489 g_object_ref (data->account);
1490 data->count_tries = 0;
1492 GMainContext *context = NULL; /* g_main_context_new (); */
1493 data->loop = g_main_loop_new (context, FALSE /* not running */);
1495 g_timeout_add (1000, &on_timeout_check_account_is_online, data);
1497 /* This main loop will run until the idle handler has stopped it: */
1498 g_main_loop_run (data->loop);
1500 g_main_loop_unref (data->loop);
1501 /* g_main_context_unref (context); */
1503 g_slice_free (CheckAccountIdleData, data);
1505 return data->is_online;
1511 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1513 // handle ok/cancel in the normal way
1514 if (response_id != GTK_RESPONSE_HELP)
1515 gtk_dialog_response (dialog, response_id);
1517 // GTK_RESPONSE_HELP means we need to show the certificate
1521 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1522 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1523 gtk_dialog_run (GTK_DIALOG(note));
1524 gtk_widget_destroy (note);
1530 modest_platform_run_certificate_conformation_dialog (const gchar* server_name,
1531 const gchar *certificate)
1535 GtkWindow *main_win =
1536 (GtkWindow*)modest_window_mgr_get_main_window (modest_runtime_get_window_mgr());
1538 gchar *question = g_strdup_printf (_("mcen_mc_unknown_certificate"),
1541 note = hildon_note_new_confirmation_add_buttons (
1544 _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK,
1545 _("mcen_bd_view"), GTK_RESPONSE_HELP, /* abusing this... */
1546 _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL,
1549 g_signal_connect (G_OBJECT(note), "response", G_CALLBACK(on_cert_dialog_response),
1550 (gpointer)certificate);
1551 response = gtk_dialog_run(GTK_DIALOG(note));
1553 gtk_widget_destroy(GTK_WIDGET(note));
1562 modest_platform_run_alert_dialog (const gchar* prompt, gboolean is_question)
1564 ModestWindow *main_window =
1565 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ());
1567 gboolean retval = TRUE;
1569 /* The Tinymail documentation says that we should show Yes and No buttons,
1570 * when it is a question.
1571 * Obviously, we need tinymail to use more specific error codes instead,
1572 * so we know what buttons to show. */
1573 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (main_window),
1575 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1576 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1578 gtk_widget_destroy (dialog);
1581 /* Just show the error text and use the default response: */
1582 modest_maemo_show_information_note_and_forget(GTK_WINDOW (main_window),