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);
1017 modest_platform_connect_and_wait (GtkWindow *parent_window, TnyAccount *account)
1019 if (connect_request_in_progress)
1022 printf ("DEBUG: %s:\n", __FUNCTION__);
1023 TnyDevice *device = modest_runtime_get_device();
1025 if (tny_device_is_online (device)) {
1026 printf ("DEBUG: %s: Already online.\n", __FUNCTION__);
1027 set_account_to_online (account);
1031 printf ("DEBUG: %s: tny_device_is_online() returned FALSE\n", __FUNCTION__);
1034 /* This blocks on the result: */
1035 UtilIdleData *data = g_slice_new0 (UtilIdleData);
1037 GMainContext *context = NULL; /* g_main_context_new (); */
1038 data->loop = g_main_loop_new (context, FALSE /* not running */);
1040 /* Cause the function to be run in an idle-handler, which is always
1041 * in the main thread:
1043 if (!connect_request_in_progress) {
1044 printf ("DEBUG: %s: First request\n", __FUNCTION__);
1045 connect_request_in_progress = TRUE;
1046 g_idle_add (&on_idle_connect_and_wait, data);
1049 printf ("DEBUG: %s: nth request\n", __FUNCTION__);
1050 g_idle_add_full (G_PRIORITY_LOW, &on_idle_wait_for_previous_connect_to_finish, data, NULL);
1053 /* This main loop will run until the idle handler has stopped it: */
1054 printf ("DEBUG: %s: before g_main_loop_run()\n", __FUNCTION__);
1055 GDK_THREADS_LEAVE();
1056 g_main_loop_run (data->loop);
1057 GDK_THREADS_ENTER();
1058 printf ("DEBUG: %s: after g_main_loop_run()\n", __FUNCTION__);
1059 connect_request_in_progress = FALSE;
1060 printf ("DEBUG: %s: Finished\n", __FUNCTION__);
1061 g_main_loop_unref (data->loop);
1062 /* g_main_context_unref (context); */
1064 g_slice_free (UtilIdleData, data);
1066 const gboolean result = tny_device_is_online (device);
1069 set_account_to_online (account);
1076 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1078 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1079 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1080 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1081 /* This must be a maildir account, which does not require a connection: */
1086 return modest_platform_connect_and_wait (parent_window, account);
1090 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1093 return TRUE; /* Maybe it is something local. */
1095 gboolean result = TRUE;
1096 if (TNY_IS_FOLDER (folder_store)) {
1097 /* Get the folder's parent account: */
1098 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1099 if (account != NULL) {
1100 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1101 g_object_unref (account);
1103 } else if (TNY_IS_ACCOUNT (folder_store)) {
1104 /* Use the folder store as an account: */
1105 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1112 modest_platform_is_network_folderstore (TnyFolderStore *folder_store)
1114 TnyAccount *account = NULL;
1115 gboolean result = TRUE;
1117 g_return_val_if_fail(TNY_IS_FOLDER_STORE(folder_store), FALSE);
1119 if (TNY_IS_FOLDER (folder_store)) {
1120 /* Get the folder's parent account: */
1121 account = tny_folder_get_account(TNY_FOLDER(folder_store));
1122 } else if (TNY_IS_ACCOUNT (folder_store)) {
1123 account = TNY_ACCOUNT(folder_store);
1124 g_object_ref(account);
1127 if (account != NULL) {
1128 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1129 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1130 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1131 /* This must be a maildir account, which does
1132 * not require a connection: */
1136 g_object_unref (account);
1145 modest_platform_run_sort_dialog (GtkWindow *parent_window,
1146 ModestSortDialogType type)
1148 GtkWidget *dialog = NULL;
1151 dialog = hildon_sort_dialog_new (parent_window);
1152 gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
1154 /* Fill sort keys */
1156 case MODEST_SORT_HEADERS:
1157 launch_sort_headers_dialog (parent_window,
1158 HILDON_SORT_DIALOG(dialog));
1163 gtk_widget_destroy (GTK_WIDGET (dialog));
1168 modest_platform_set_update_interval (guint minutes)
1170 ModestConf *conf = modest_runtime_get_conf ();
1174 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1176 /* Delete any existing alarm,
1177 * because we will replace it: */
1179 /* TODO: What does the alarm_event_del() return value mean? */
1180 alarm_event_del(alarm_cookie);
1182 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1185 /* 0 means no updates: */
1190 /* Register alarm: */
1192 /* Set the interval in alarm_event_t structure: */
1193 alarm_event_t *event = g_new0(alarm_event_t, 1);
1194 event->alarm_time = minutes * 60; /* seconds */
1196 /* Set recurrence every few minutes: */
1197 event->recurrence = minutes;
1198 event->recurrence_count = -1; /* Means infinite */
1200 /* Specify what should happen when the alarm happens:
1201 * It should call this D-Bus method: */
1203 event->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1204 event->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1205 event->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1206 event->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1208 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1209 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1210 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1211 * This is why we want to use the Alarm API instead of just g_timeout_add().
1212 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1214 event->flags = ALARM_EVENT_NO_DIALOG | ALARM_EVENT_ACTIVATION;
1216 alarm_cookie = alarm_event_add (event);
1219 alarm_event_free (event);
1221 /* Store the alarm ID in GConf, so we can remove it later:
1222 * This is apparently valid between application instances. */
1223 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1225 if (!alarm_cookie) {
1227 const alarm_error_t alarm_error = alarmd_get_error ();
1228 g_debug ("Error setting alarm event. Error code: '%d'\n", alarm_error);
1230 /* Give people some clue: */
1231 /* The alarm API should have a function for this: */
1232 if (alarm_error == ALARMD_ERROR_DBUS) {
1233 g_debug (" ALARMD_ERROR_DBUS: An error with D-Bus occurred, probably coudn't get a D-Bus connection.\n");
1234 } else if (alarm_error == ALARMD_ERROR_CONNECTION) {
1235 g_debug (" ALARMD_ERROR_CONNECTION: Could not contact alarmd via D-Bus.\n");
1236 } else if (alarm_error == ALARMD_ERROR_INTERNAL) {
1237 g_debug (" ALARMD_ERROR_INTERNAL: Some alarmd or libalarm internal error, possibly a version mismatch.\n");
1238 } else if (alarm_error == ALARMD_ERROR_MEMORY) {
1239 g_debug (" ALARMD_ERROR_MEMORY: A memory allocation failed.\n");
1240 } else if (alarm_error == ALARMD_ERROR_ARGUMENT) {
1241 g_debug (" ALARMD_ERROR_ARGUMENT: An argument given by caller was invalid.\n");
1242 } else if (alarm_error == ALARMD_ERROR_NOT_RUNNING) {
1243 g_debug (" ALARMD_ERROR_NOT_RUNNING: alarmd is not running.\n");
1253 modest_platform_get_global_settings_dialog ()
1255 return modest_maemo_global_settings_dialog_new ();
1259 modest_platform_on_new_header_received (TnyHeader *header)
1261 #ifdef MODEST_HAVE_HILDON_NOTIFY
1262 HildonNotification *not;
1264 TnyFolder *folder = NULL;
1266 /* Create a new notification. TODO: per-mail data needed */
1267 not = hildon_notification_new (tny_header_get_from (header),
1268 tny_header_get_subject (header),
1269 "qgn_list_messagin_mail_unread",
1272 folder = tny_header_get_folder (header);
1273 url = g_strdup_printf ("%s/%s",
1274 tny_folder_get_url_string (folder),
1275 tny_header_get_uid (header));
1276 g_object_unref (folder);
1278 hildon_notification_add_dbus_action(not,
1281 MODEST_DBUS_SERVICE,
1284 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1289 /* Play sound SR-SND-18 */
1290 hildon_notification_set_sound
1291 (not, "/usr/share/sounds/ui-new_email.wav");
1292 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (not), "dialog-type", 4);
1294 /* Set the led pattern */
1295 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (not),
1297 "PatternCommunicationEmail");
1299 /* Notify. We need to do this in an idle because this function
1300 could be called from a thread */
1301 if (!notify_notification_show (NOTIFY_NOTIFICATION (not), NULL))
1302 g_error ("Failed to send notification");
1304 g_object_unref (not);
1305 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1310 modest_platform_show_help (GtkWindow *parent_window,
1311 const gchar *help_id)
1313 osso_return_t result;
1315 g_return_if_fail (help_id);
1316 g_return_if_fail (osso_context);
1319 #ifdef MODEST_HAVE_OSSO_HELP
1320 result = ossohelp_show (osso_context, help_id, OSSO_HELP_SHOW_DIALOG);
1322 result = hildon_help_show (osso_context, help_id, OSSO_HELP_SHOW_DIALOG);
1325 if (result != OSSO_OK) {
1327 error_msg = g_strdup_printf ("FIXME The help topic %s could not be found", help_id);
1328 hildon_banner_show_information (GTK_WIDGET (parent_window),
1336 modest_platform_show_search_messages (GtkWindow *parent_window)
1338 osso_return_t result = OSSO_ERROR;
1340 result = osso_rpc_run_with_defaults (osso_context, "osso_global_search", "search_email", NULL, DBUS_TYPE_INVALID);
1342 if (result != OSSO_OK) {
1343 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1348 modest_platform_show_addressbook (GtkWindow *parent_window)
1350 osso_return_t result = OSSO_ERROR;
1352 result = osso_rpc_run_with_defaults (osso_context, "osso_addressbook", "top_application", NULL, DBUS_TYPE_INVALID);
1354 if (result != OSSO_OK) {
1355 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1360 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1362 GtkWidget *widget = modest_folder_view_new (query);
1364 /* Show one account by default */
1365 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1366 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1369 /* Restore settings */
1370 modest_widget_memory_restore (modest_runtime_get_conf(),
1372 MODEST_CONF_FOLDER_VIEW_KEY);
1378 modest_platform_information_banner (GtkWidget *parent,
1379 const gchar *icon_name,
1382 hildon_banner_show_information (parent, icon_name, text);
1386 modest_platform_animation_banner (GtkWidget *parent,
1387 const gchar *animation_name,
1390 GtkWidget *inf_note = NULL;
1392 g_return_val_if_fail (text != NULL, NULL);
1394 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1402 TnyAccount *account;
1405 } CheckAccountIdleData;
1407 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1410 on_timeout_check_account_is_online(gpointer user_data)
1412 printf ("DEBUG: %s:\n", __FUNCTION__);
1413 CheckAccountIdleData *data = (CheckAccountIdleData*)user_data;
1416 g_warning ("%s: data is NULL.\n", __FUNCTION__);
1419 if (!(data->account)) {
1420 g_warning ("%s: data->account is NULL.\n", __FUNCTION__);
1423 if (data && data->account) {
1424 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__, tny_account_get_connection_status (data->account));
1427 gboolean stop_trying = FALSE;
1428 if (data && data->account &&
1429 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1430 * after which the account is likely to be usable, or never likely to be usable soon: */
1431 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1433 data->is_online = TRUE;
1438 /* Give up if we have tried too many times: */
1439 if (data->count_tries >= NUMBER_OF_TRIES)
1444 /* Wait for another timeout: */
1445 ++(data->count_tries);
1450 /* Allow the function that requested this idle callback to continue: */
1452 g_main_loop_quit (data->loop);
1455 g_object_unref (data->account);
1457 return FALSE; /* Don't call this again. */
1459 return TRUE; /* Call this timeout callback again. */
1463 /* Return TRUE immediately if the account is already online,
1464 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1465 * soon as the account is online, or FALSE if the account does
1466 * not become online in the NUMBER_OF_TRIES seconds.
1467 * This is useful when the D-Bus method was run immediately after
1468 * the application was started (when using D-Bus activation),
1469 * because the account usually takes a short time to go online.
1470 * The return value is maybe not very useful.
1473 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1475 g_return_val_if_fail (account, FALSE);
1477 printf ("DEBUG: %s: account id=%s\n", __FUNCTION__, tny_account_get_id (account));
1479 if (!tny_device_is_online (modest_runtime_get_device())) {
1480 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1484 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1485 * so we avoid wait unnecessarily: */
1486 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1487 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account) ) {
1491 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n",
1492 __FUNCTION__, tny_account_get_connection_status (account));
1494 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1495 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1496 * we want to avoid. */
1497 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1500 /* This blocks on the result: */
1501 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1502 data->is_online = FALSE;
1503 data->account = account;
1504 g_object_ref (data->account);
1505 data->count_tries = 0;
1507 GMainContext *context = NULL; /* g_main_context_new (); */
1508 data->loop = g_main_loop_new (context, FALSE /* not running */);
1510 g_timeout_add (1000, &on_timeout_check_account_is_online, data);
1512 /* This main loop will run until the idle handler has stopped it: */
1513 g_main_loop_run (data->loop);
1515 g_main_loop_unref (data->loop);
1516 /* g_main_context_unref (context); */
1518 g_slice_free (CheckAccountIdleData, data);
1520 return data->is_online;
1526 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1528 // handle ok/cancel in the normal way
1529 if (response_id != GTK_RESPONSE_HELP)
1530 gtk_dialog_response (dialog, response_id);
1532 // GTK_RESPONSE_HELP means we need to show the certificate
1536 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1537 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1538 gtk_dialog_run (GTK_DIALOG(note));
1539 gtk_widget_destroy (note);
1545 modest_platform_run_certificate_conformation_dialog (const gchar* server_name,
1546 const gchar *certificate)
1550 GtkWindow *main_win =
1551 (GtkWindow*)modest_window_mgr_get_main_window (modest_runtime_get_window_mgr());
1553 gchar *question = g_strdup_printf (_("mcen_mc_unknown_certificate"),
1556 note = hildon_note_new_confirmation_add_buttons (
1559 _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK,
1560 _("mcen_bd_view"), GTK_RESPONSE_HELP, /* abusing this... */
1561 _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL,
1564 g_signal_connect (G_OBJECT(note), "response", G_CALLBACK(on_cert_dialog_response),
1565 (gpointer)certificate);
1566 response = gtk_dialog_run(GTK_DIALOG(note));
1568 gtk_widget_destroy(GTK_WIDGET(note));
1577 modest_platform_run_alert_dialog (const gchar* prompt, gboolean is_question)
1579 ModestWindow *main_window =
1580 modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ());
1582 gboolean retval = TRUE;
1584 /* The Tinymail documentation says that we should show Yes and No buttons,
1585 * when it is a question.
1586 * Obviously, we need tinymail to use more specific error codes instead,
1587 * so we know what buttons to show. */
1588 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (main_window),
1590 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1591 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1593 gtk_widget_destroy (dialog);
1596 /* Just show the error text and use the default response: */
1597 modest_maemo_show_information_note_and_forget(GTK_WINDOW (main_window),