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 <modest-maemo-utils.h>
40 #include <dbus_api/modest-dbus-callbacks.h>
41 #include <maemo/modest-osso-autosave-callbacks.h>
43 #include <alarmd/alarm_event.h> /* For alarm_event_add(), etc. */
44 #include <tny-maemo-conic-device.h>
45 #include <tny-simple-list.h>
46 #include <tny-folder.h>
47 #include <tny-camel-imap-store-account.h>
48 #include <tny-camel-pop-store-account.h>
49 #include <gtk/gtkicontheme.h>
50 #include <gtk/gtkmenuitem.h>
51 #include <gtk/gtkmain.h>
52 #include <modest-text-utils.h>
53 #include "modest-tny-folder.h"
55 #include <libgnomevfs/gnome-vfs-mime-utils.h>
57 #ifdef MODEST_HAVE_ABOOK
58 #include <libosso-abook/osso-abook.h>
59 #endif /*MODEST_HAVE_ABOOK*/
62 #define HILDON_OSSO_URI_ACTION "uri-action"
63 #define URI_ACTION_COPY "copy:"
65 static osso_context_t *osso_context = NULL; /* urgh global */
68 on_modest_conf_update_interval_changed (ModestConf* self,
70 ModestConfEvent event,
71 ModestConfNotificationId id,
74 g_return_if_fail (key);
76 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
77 const guint update_interval_minutes =
78 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
79 modest_platform_set_update_interval (update_interval_minutes);
86 check_required_files (void)
88 FILE *mcc_file = modest_maemo_open_mcc_mapping_file ();
90 g_printerr ("modest: check for mcc file failed\n");
95 if (access (MODEST_PROVIDERS_DATA_PATH, R_OK) != 0) {
96 g_printerr ("modest: cannot find providers data\n");
106 modest_platform_init (int argc, char *argv[])
108 osso_hw_state_t hw_state = { 0 };
112 if (!check_required_files ()) {
113 g_printerr ("modest: missing required files\n");
119 osso_initialize(PACKAGE,PACKAGE_VERSION,
122 g_printerr ("modest: failed to acquire osso context\n");
126 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
127 g_printerr ("modest: could not get dbus connection\n");
132 /* Add a D-Bus handler to be used when the main osso-rpc
133 * D-Bus handler has not handled something.
134 * We use this for D-Bus methods that need to use more complex types
135 * than osso-rpc supports.
137 if (!dbus_connection_add_filter (con,
138 modest_dbus_req_filter,
142 g_printerr ("modest: Could not add D-Bus filter\n");
146 /* Register our simple D-Bus callbacks, via the osso API: */
147 osso_return_t result = osso_rpc_set_cb_f(osso_context,
151 modest_dbus_req_handler, NULL /* user_data */);
152 if (result != OSSO_OK) {
153 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
157 /* Add handler for Exit D-BUS messages.
158 * Not used because osso_application_set_exit_cb() is deprecated and obsolete:
159 result = osso_application_set_exit_cb(osso_context,
160 modest_dbus_exit_event_handler,
162 if (result != OSSO_OK) {
163 g_print("Error setting exit callback (%d)\n", result);
168 /* Register hardware event dbus callback: */
169 hw_state.shutdown_ind = TRUE;
170 osso_hw_set_event_cb(osso_context, NULL,/*&hw_state*/ modest_osso_cb_hw_state_handler, NULL);
172 /* Register osso auto-save callbacks: */
173 result = osso_application_set_autosave_cb (osso_context,
174 modest_on_osso_application_autosave, NULL /* user_data */);
175 if (result != OSSO_OK) {
176 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
181 /* Make sure that the update interval is changed whenever its gconf key
183 /* CAUTION: we're not using here the
184 modest_conf_listen_to_namespace because we know that there
185 are other parts of Modest listening for this namespace, so
186 we'll receive the notifications anyway. We basically do not
187 use it because there is no easy way to do the
188 modest_conf_forget_namespace */
189 ModestConf *conf = modest_runtime_get_conf ();
190 g_signal_connect (G_OBJECT(conf),
192 G_CALLBACK (on_modest_conf_update_interval_changed),
195 /* only force the setting of the default interval, if there are actually
197 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
199 /* Get the initial update interval from gconf: */
200 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
201 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
202 modest_account_mgr_free_account_names (acc_names);
206 #ifdef MODEST_HAVE_ABOOK
207 /* initialize the addressbook */
208 if (!osso_abook_init (&argc, &argv, osso_context)) {
209 g_printerr ("modest: failed to initialized addressbook\n");
212 #endif /*MODEST_HAVE_ABOOK*/
219 modest_platform_get_new_device (void)
221 return TNY_DEVICE (tny_maemo_conic_device_new ());
225 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
226 gchar **effective_mime_type)
228 GString *mime_str = NULL;
229 gchar *icon_name = NULL;
230 gchar **icons, **cursor;
232 if (!mime_type || !g_ascii_strcasecmp (mime_type, "application/octet-stream"))
233 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
235 mime_str = g_string_new (mime_type);
236 g_string_ascii_down (mime_str);
239 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
240 for (cursor = icons; cursor; ++cursor) {
241 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
242 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
243 icon_name = g_strdup ("qgn_list_messagin");
245 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
246 icon_name = g_strdup (*cursor);
252 if (effective_mime_type)
253 *effective_mime_type = g_string_free (mime_str, FALSE);
255 g_string_free (mime_str, TRUE);
262 modest_platform_activate_uri (const gchar *uri)
264 HildonURIAction *action;
265 gboolean result = FALSE;
266 GSList *actions, *iter = NULL;
268 g_return_val_if_fail (uri, FALSE);
272 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
274 for (iter = actions; iter; iter = g_slist_next (iter)) {
275 action = (HildonURIAction*) iter->data;
276 if (action && strcmp (hildon_uri_action_get_service (action),
277 "com.nokia.modest") == 0) {
279 result = hildon_uri_open (uri, action, &err);
280 if (!result && err) {
281 g_printerr ("modest: modest_platform_activate_uri : %s",
282 err->message ? err->message : "unknown error");
289 /* if we could not open it with email, try something else */
291 result = hildon_uri_open (uri, NULL, NULL);
294 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
300 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
304 gchar *uri_path = NULL;
306 uri_path = g_strconcat ("file://", path, NULL);
307 con = osso_get_dbus_connection (osso_context);
310 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
312 result = hildon_mime_open_file (con, uri_path);
314 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"));
322 } ModestPlatformPopupInfo;
325 delete_uri_popup (GtkWidget *menu,
329 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
331 g_free (popup_info->uri);
332 hildon_uri_free_actions (popup_info->actions);
338 activate_uri_popup_item (GtkMenuItem *menu_item,
342 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
343 const gchar* action_name;
345 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
347 g_printerr ("modest: no action name defined\n");
351 /* special handling for the copy menu item -- copy the uri to the clipboard */
352 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
353 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
354 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
355 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
357 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
358 action_name += strlen ("mailto:");
360 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
361 return; /* we're done */
364 /* now, the real uri-actions... */
365 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
366 HildonURIAction *action = (HildonURIAction *) node->data;
367 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
368 hildon_uri_open (popup_info->uri, action, NULL);
375 modest_platform_show_uri_popup (const gchar *uri)
377 GSList *actions_list;
382 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
383 if (actions_list != NULL) {
385 GtkWidget *menu = gtk_menu_new ();
386 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
388 popup_info->actions = actions_list;
389 popup_info->uri = g_strdup (uri);
391 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
392 GtkWidget *menu_item;
393 const gchar *action_name;
394 const gchar *translation_domain;
395 HildonURIAction *action = (HildonURIAction *) node->data;
396 action_name = hildon_uri_action_get_name (action);
397 translation_domain = hildon_uri_action_get_translation_domain (action);
398 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
399 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
400 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
403 if (hildon_uri_is_default_action (action, NULL)) {
404 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
406 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
408 gtk_widget_show (menu_item);
411 /* always add the copy item */
412 GtkWidget* menu_item = gtk_menu_item_new_with_label (dgettext("osso-uri", "uri_link_copy_link_location"));
413 g_object_set_data_full (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION,
414 g_strconcat (URI_ACTION_COPY, uri, NULL),
416 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),NULL);
417 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
418 gtk_widget_show (menu_item);
421 /* and what to do when the link is deleted */
422 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
423 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
426 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_MAIN_WINDOW_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_MASK;
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_MASK)
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");
716 modest_platform_run_folder_name_dialog (GtkWindow *parent_window,
717 TnyFolderStore *parent,
718 const gchar *dialog_title,
719 const gchar *label_text,
720 const gchar *suggested_name,
723 GtkWidget *accept_btn = NULL;
724 GtkWidget *dialog, *entry, *label, *hbox;
725 GList *buttons = NULL;
728 /* Ask the user for the folder name */
729 dialog = gtk_dialog_new_with_buttons (dialog_title,
731 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
732 _("mcen_bd_dialog_ok"),
734 _("mcen_bd_dialog_cancel"),
738 /* Add accept button (with unsensitive handler) */
739 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
740 accept_btn = GTK_WIDGET (buttons->next->data);
741 /* Create label and entry */
742 label = gtk_label_new (label_text);
743 /* TODO: check that the suggested name does not exist */
744 /* We set 21 as maximum because we want to show WID-INF036
745 when the user inputs more that 20 */
746 entry = gtk_entry_new_with_max_length (21);
748 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
750 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
751 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
753 /* Connect to the response method to avoid closing the dialog
754 when an invalid name is selected*/
755 g_signal_connect (dialog,
757 G_CALLBACK (on_response),
760 /* Track entry changes */
761 g_signal_connect (entry,
763 G_CALLBACK (entry_insert_text),
765 g_signal_connect (entry,
767 G_CALLBACK (entry_changed),
770 /* Create the hbox */
771 hbox = gtk_hbox_new (FALSE, 12);
772 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, FALSE, 0);
773 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, FALSE, 0);
775 /* Add hbox to dialog */
776 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
777 hbox, FALSE, FALSE, 0);
779 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
780 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
782 result = gtk_dialog_run (GTK_DIALOG(dialog));
783 if (result == GTK_RESPONSE_ACCEPT)
784 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
786 gtk_widget_destroy (dialog);
788 while (gtk_events_pending ())
789 gtk_main_iteration ();
795 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
796 TnyFolderStore *parent_folder,
797 gchar *suggested_name,
800 gchar *real_suggested_name = NULL;
803 if(suggested_name == NULL)
805 const gchar *default_name = _("mcen_ia_default_folder_name");
809 for(i = 0; i < 100; ++ i) {
810 gboolean exists = FALSE;
812 sprintf(num_str, "%.2u", i);
815 real_suggested_name = g_strdup (default_name);
817 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
820 exists = modest_tny_folder_has_subfolder_with_name (parent_folder,
821 real_suggested_name);
826 g_free (real_suggested_name);
829 /* Didn't find a free number */
831 real_suggested_name = g_strdup (default_name);
833 real_suggested_name = suggested_name;
836 result = modest_platform_run_folder_name_dialog (parent_window,
838 _("mcen_ti_new_folder"),
839 _("mcen_fi_new_folder_name"),
842 if (suggested_name == NULL)
843 g_free(real_suggested_name);
849 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
850 TnyFolderStore *parent_folder,
851 const gchar *suggested_name,
854 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
856 return modest_platform_run_folder_name_dialog (parent_window,
858 _HL("ckdg_ti_rename_folder"),
859 _HL("ckdg_fi_rename_name"),
867 on_destroy_dialog (GtkDialog *dialog)
869 gtk_widget_destroy (GTK_WIDGET(dialog));
870 if (gtk_events_pending ())
871 gtk_main_iteration ();
875 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
876 const gchar *message)
881 dialog = hildon_note_new_confirmation (parent_window, message);
882 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
883 GTK_WINDOW (dialog));
885 response = gtk_dialog_run (GTK_DIALOG (dialog));
887 on_destroy_dialog (GTK_DIALOG(dialog));
889 while (gtk_events_pending ())
890 gtk_main_iteration ();
896 modest_platform_run_yes_no_dialog (GtkWindow *parent_window,
897 const gchar *message)
902 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
903 _("mcen_bd_yes"), GTK_RESPONSE_YES,
904 _("mcen_bd_no"), GTK_RESPONSE_NO,
906 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
907 response = gtk_dialog_run (GTK_DIALOG (dialog));
909 on_destroy_dialog (GTK_DIALOG(dialog));
911 while (gtk_events_pending ())
912 gtk_main_iteration ();
920 modest_platform_run_information_dialog (GtkWindow *parent_window,
921 const gchar *message)
925 note = hildon_note_new_information (parent_window, message);
926 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
929 g_signal_connect_swapped (note,
931 G_CALLBACK (on_destroy_dialog),
934 gtk_widget_show_all (note);
939 typedef struct _ConnectAndWaitData {
941 GMainLoop *wait_loop;
942 gboolean has_callback;
944 } ConnectAndWaitData;
948 quit_wait_loop (TnyAccount *account,
949 ConnectAndWaitData *data)
951 /* Set the has_callback to TRUE (means that the callback was
952 executed and wake up every code waiting for cond to be
954 g_mutex_lock (data->mutex);
955 data->has_callback = TRUE;
957 g_main_loop_quit (data->wait_loop);
958 g_mutex_unlock (data->mutex);
962 on_connection_status_changed (TnyAccount *account,
963 TnyConnectionStatus status,
966 TnyConnectionStatus conn_status;
967 ConnectAndWaitData *data;
969 /* Ignore if reconnecting or disconnected */
970 conn_status = tny_account_get_connection_status (account);
971 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
972 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
975 /* Remove the handler */
976 data = (ConnectAndWaitData *) user_data;
977 g_signal_handler_disconnect (account, data->handler);
979 /* Quit from wait loop */
980 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
984 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
989 /* Quit from wait loop */
990 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
994 modest_platform_connect_and_wait (GtkWindow *parent_window,
997 ConnectAndWaitData *data = NULL;
998 gboolean device_online;
1000 TnyConnectionStatus conn_status;
1002 device = modest_runtime_get_device();
1003 device_online = tny_device_is_online (device);
1005 /* If there is no account check only the device status */
1010 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), NULL);
1013 /* Return if the account is already connected */
1014 conn_status = tny_account_get_connection_status (account);
1015 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1018 /* Create the helper */
1019 data = g_slice_new0 (ConnectAndWaitData);
1020 data->mutex = g_mutex_new ();
1021 data->has_callback = FALSE;
1023 /* Connect the device */
1024 if (!device_online) {
1025 /* Track account connection status changes */
1026 data->handler = g_signal_connect (account, "connection-status-changed",
1027 G_CALLBACK (on_connection_status_changed),
1029 /* Try to connect the device */
1030 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), NULL);
1032 /* If the device connection failed then exit */
1033 if (!device_online && data->handler)
1036 /* Force a reconnection of the account */
1037 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1038 on_tny_camel_account_set_online_cb, data);
1041 /* Wait until the callback is executed */
1042 g_mutex_lock (data->mutex);
1043 if (!data->has_callback) {
1044 data->wait_loop = g_main_loop_new (NULL, FALSE);
1045 gdk_threads_leave ();
1046 g_mutex_unlock (data->mutex);
1047 g_main_loop_run (data->wait_loop);
1048 g_mutex_lock (data->mutex);
1049 gdk_threads_enter ();
1051 g_mutex_unlock (data->mutex);
1055 if (g_signal_handler_is_connected (account, data->handler))
1056 g_signal_handler_disconnect (account, data->handler);
1057 g_mutex_free (data->mutex);
1058 g_main_loop_unref (data->wait_loop);
1059 g_slice_free (ConnectAndWaitData, data);
1062 conn_status = tny_account_get_connection_status (account);
1063 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1067 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1069 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1070 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1071 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1072 /* This must be a maildir account, which does not require a connection: */
1077 return modest_platform_connect_and_wait (parent_window, account);
1081 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1084 return TRUE; /* Maybe it is something local. */
1086 gboolean result = TRUE;
1087 if (TNY_IS_FOLDER (folder_store)) {
1088 /* Get the folder's parent account: */
1089 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1090 if (account != NULL) {
1091 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1092 g_object_unref (account);
1094 } else if (TNY_IS_ACCOUNT (folder_store)) {
1095 /* Use the folder store as an account: */
1096 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1103 modest_platform_is_network_folderstore (TnyFolderStore *folder_store)
1105 TnyAccount *account = NULL;
1106 gboolean result = TRUE;
1108 g_return_val_if_fail(TNY_IS_FOLDER_STORE(folder_store), FALSE);
1110 if (TNY_IS_FOLDER (folder_store)) {
1111 /* Get the folder's parent account: */
1112 account = tny_folder_get_account(TNY_FOLDER(folder_store));
1113 } else if (TNY_IS_ACCOUNT (folder_store)) {
1114 account = TNY_ACCOUNT(folder_store);
1115 g_object_ref(account);
1118 if (account != NULL) {
1119 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1120 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1121 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1122 /* This must be a maildir account, which does
1123 * not require a connection: */
1127 g_object_unref (account);
1136 modest_platform_run_sort_dialog (GtkWindow *parent_window,
1137 ModestSortDialogType type)
1139 GtkWidget *dialog = NULL;
1142 dialog = hildon_sort_dialog_new (parent_window);
1143 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1144 GTK_WINDOW (dialog));
1146 /* Fill sort keys */
1148 case MODEST_SORT_HEADERS:
1149 launch_sort_headers_dialog (parent_window,
1150 HILDON_SORT_DIALOG(dialog));
1155 on_destroy_dialog (GTK_DIALOG(dialog));
1160 modest_platform_set_update_interval (guint minutes)
1162 ModestConf *conf = modest_runtime_get_conf ();
1166 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1168 /* Delete any existing alarm,
1169 * because we will replace it: */
1171 /* TODO: What does the alarm_event_del() return value mean? */
1172 alarm_event_del(alarm_cookie);
1174 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1177 /* 0 means no updates: */
1182 /* Register alarm: */
1184 /* Set the interval in alarm_event_t structure: */
1185 alarm_event_t *event = g_new0(alarm_event_t, 1);
1186 event->alarm_time = minutes * 60; /* seconds */
1188 /* Set recurrence every few minutes: */
1189 event->recurrence = minutes;
1190 event->recurrence_count = -1; /* Means infinite */
1192 /* Specify what should happen when the alarm happens:
1193 * It should call this D-Bus method: */
1195 event->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1196 event->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1197 event->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1198 event->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1200 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1201 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1202 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1203 * This is why we want to use the Alarm API instead of just g_timeout_add().
1204 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1206 event->flags = ALARM_EVENT_NO_DIALOG | ALARM_EVENT_ACTIVATION;
1208 alarm_cookie = alarm_event_add (event);
1211 alarm_event_free (event);
1213 /* Store the alarm ID in GConf, so we can remove it later:
1214 * This is apparently valid between application instances. */
1215 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1217 if (!alarm_cookie) {
1219 const alarm_error_t alarm_error = alarmd_get_error ();
1220 g_debug ("Error setting alarm event. Error code: '%d'\n", alarm_error);
1222 /* Give people some clue: */
1223 /* The alarm API should have a function for this: */
1224 if (alarm_error == ALARMD_ERROR_DBUS) {
1225 g_debug (" ALARMD_ERROR_DBUS: An error with D-Bus occurred, probably coudn't get a D-Bus connection.\n");
1226 } else if (alarm_error == ALARMD_ERROR_CONNECTION) {
1227 g_debug (" ALARMD_ERROR_CONNECTION: Could not contact alarmd via D-Bus.\n");
1228 } else if (alarm_error == ALARMD_ERROR_INTERNAL) {
1229 g_debug (" ALARMD_ERROR_INTERNAL: Some alarmd or libalarm internal error, possibly a version mismatch.\n");
1230 } else if (alarm_error == ALARMD_ERROR_MEMORY) {
1231 g_debug (" ALARMD_ERROR_MEMORY: A memory allocation failed.\n");
1232 } else if (alarm_error == ALARMD_ERROR_ARGUMENT) {
1233 g_debug (" ALARMD_ERROR_ARGUMENT: An argument given by caller was invalid.\n");
1234 } else if (alarm_error == ALARMD_ERROR_NOT_RUNNING) {
1235 g_debug (" ALARMD_ERROR_NOT_RUNNING: alarmd is not running.\n");
1245 modest_platform_on_new_headers_received (TnyList *header_list)
1247 #ifdef MODEST_HAVE_HILDON_NOTIFY
1248 HildonNotification *notification;
1250 GSList *notifications_list = NULL;
1252 /* Get previous notifications ids */
1253 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1254 MODEST_CONF_NOTIFICATION_IDS,
1255 MODEST_CONF_VALUE_INT, NULL);
1257 iter = tny_list_create_iterator (header_list);
1258 while (!tny_iterator_is_done (iter)) {
1259 gchar *url = NULL, *display_address = NULL, *display_date = NULL, *summary = NULL;
1260 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1261 TnyFolder *folder = tny_header_get_folder (header);
1262 gboolean first_notification = TRUE;
1265 display_date = modest_text_utils_get_display_date (tny_header_get_date_received (header));
1267 display_address = g_strdup(tny_header_get_from (header));
1268 modest_text_utils_get_display_address (display_address); /* string is changed in-place */
1270 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1271 notification = hildon_notification_new (summary,
1272 tny_header_get_subject (header),
1273 "qgn_list_messagin",
1276 /* Create the message URL */
1277 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1278 tny_header_get_uid (header));
1280 hildon_notification_add_dbus_action(notification,
1283 MODEST_DBUS_SERVICE,
1286 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1290 /* Play sound if the user wants. Show the LED
1291 pattern. Show and play just one */
1292 if (G_UNLIKELY (first_notification)) {
1293 first_notification = FALSE;
1294 if (modest_conf_get_bool (modest_runtime_get_conf (),
1295 MODEST_CONF_PLAY_SOUND_MSG_ARRIVE,
1297 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1298 "sound-file", "/usr/share/sounds/ui-new_email.wav");
1301 /* Set the led pattern */
1302 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1304 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1306 "PatternCommunicationEmail");
1309 /* Notify. We need to do this in an idle because this function
1310 could be called from a thread */
1311 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1313 /* Save id in the list */
1314 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1315 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1316 /* We don't listen for the "closed" signal, because we
1317 don't care about if the notification was removed or
1318 not to store the list in gconf */
1320 /* Free & carry on */
1321 g_free (display_date);
1322 g_free (display_address);
1325 g_object_unref (folder);
1326 g_object_unref (header);
1327 tny_iterator_next (iter);
1329 g_object_unref (iter);
1332 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1333 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1335 g_slist_free (notifications_list);
1337 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1341 modest_platform_remove_new_mail_notifications (void)
1343 #ifdef MODEST_HAVE_HILDON_NOTIFY
1344 GSList *notif_list = NULL;
1346 /* Get previous notifications ids */
1347 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1348 MODEST_CONF_NOTIFICATION_IDS,
1349 MODEST_CONF_VALUE_INT, NULL);
1351 while (notif_list) {
1353 NotifyNotification *notif;
1355 /* Nasty HACK to remove the notifications, set the id
1356 of the existing ones and then close them */
1357 notif_id = GPOINTER_TO_INT(notif_list->data);
1358 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1359 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1361 /* Close the notification, note that some ids could be
1362 already invalid, but we don't care because it does
1364 notify_notification_close(notif, NULL);
1365 g_object_unref(notif);
1367 /* Delete the link, it's like going to the next */
1368 notif_list = g_slist_delete_link (notif_list, notif_list);
1372 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1373 notif_list, MODEST_CONF_VALUE_INT, NULL);
1375 g_slist_free (notif_list);
1377 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1383 modest_platform_get_global_settings_dialog ()
1385 return modest_maemo_global_settings_dialog_new ();
1389 modest_platform_show_help (GtkWindow *parent_window,
1390 const gchar *help_id)
1392 osso_return_t result;
1394 g_return_if_fail (help_id);
1395 g_return_if_fail (osso_context);
1397 result = hildon_help_show (osso_context, help_id, HILDON_HELP_SHOW_DIALOG);
1399 if (result != OSSO_OK) {
1401 error_msg = g_strdup_printf ("FIXME The help topic %s could not be found", help_id);
1402 hildon_banner_show_information (GTK_WIDGET (parent_window),
1410 modest_platform_set_dialog_help (GtkDialog *parent_window,
1411 const gchar *help_id)
1414 g_return_if_fail (help_id);
1415 g_return_if_fail (osso_context);
1416 g_return_if_fail (GTK_IS_DIALOG (parent_window));
1418 result = hildon_help_dialog_help_enable (parent_window, help_id, osso_context);
1421 g_warning ("Help topic %s not found", help_id);
1426 modest_platform_show_search_messages (GtkWindow *parent_window)
1428 osso_return_t result = OSSO_ERROR;
1430 result = osso_rpc_run_with_defaults (osso_context, "osso_global_search", "search_email", NULL, DBUS_TYPE_INVALID);
1432 if (result != OSSO_OK) {
1433 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1438 modest_platform_show_addressbook (GtkWindow *parent_window)
1440 osso_return_t result = OSSO_ERROR;
1442 result = osso_rpc_run_with_defaults (osso_context, "osso_addressbook", "top_application", NULL, DBUS_TYPE_INVALID);
1444 if (result != OSSO_OK) {
1445 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1450 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1452 GtkWidget *widget = modest_folder_view_new (query);
1454 /* Show one account by default */
1455 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1456 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1459 /* Restore settings */
1460 modest_widget_memory_restore (modest_runtime_get_conf(),
1462 MODEST_CONF_FOLDER_VIEW_KEY);
1468 modest_platform_information_banner (GtkWidget *parent,
1469 const gchar *icon_name,
1472 hildon_banner_show_information (parent, icon_name, text);
1476 modest_platform_animation_banner (GtkWidget *parent,
1477 const gchar *animation_name,
1480 GtkWidget *inf_note = NULL;
1482 g_return_val_if_fail (text != NULL, NULL);
1484 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1492 TnyAccount *account;
1495 } CheckAccountIdleData;
1497 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1500 on_timeout_check_account_is_online(gpointer user_data)
1502 printf ("DEBUG: %s:\n", __FUNCTION__);
1503 CheckAccountIdleData *data = (CheckAccountIdleData*)user_data;
1506 g_warning ("%s: data is NULL.\n", __FUNCTION__);
1509 if (!(data->account)) {
1510 g_warning ("%s: data->account is NULL.\n", __FUNCTION__);
1513 if (data && data->account) {
1514 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__, tny_account_get_connection_status (data->account));
1517 gboolean stop_trying = FALSE;
1518 if (data && data->account &&
1519 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1520 * after which the account is likely to be usable, or never likely to be usable soon: */
1521 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1523 data->is_online = TRUE;
1528 /* Give up if we have tried too many times: */
1529 if (data->count_tries >= NUMBER_OF_TRIES)
1534 /* Wait for another timeout: */
1535 ++(data->count_tries);
1540 /* Allow the function that requested this idle callback to continue: */
1542 g_main_loop_quit (data->loop);
1545 g_object_unref (data->account);
1547 return FALSE; /* Don't call this again. */
1549 return TRUE; /* Call this timeout callback again. */
1553 /* Return TRUE immediately if the account is already online,
1554 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1555 * soon as the account is online, or FALSE if the account does
1556 * not become online in the NUMBER_OF_TRIES seconds.
1557 * This is useful when the D-Bus method was run immediately after
1558 * the application was started (when using D-Bus activation),
1559 * because the account usually takes a short time to go online.
1560 * The return value is maybe not very useful.
1563 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1565 g_return_val_if_fail (account, FALSE);
1567 printf ("DEBUG: %s: account id=%s\n", __FUNCTION__, tny_account_get_id (account));
1569 if (!tny_device_is_online (modest_runtime_get_device())) {
1570 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1574 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1575 * so we avoid wait unnecessarily: */
1576 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1577 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account) ) {
1581 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n",
1582 __FUNCTION__, tny_account_get_connection_status (account));
1584 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1585 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1586 * we want to avoid. */
1587 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1590 /* This blocks on the result: */
1591 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1592 data->is_online = FALSE;
1593 data->account = account;
1594 g_object_ref (data->account);
1595 data->count_tries = 0;
1597 GMainContext *context = NULL; /* g_main_context_new (); */
1598 data->loop = g_main_loop_new (context, FALSE /* not running */);
1600 g_timeout_add (1000, on_timeout_check_account_is_online, data);
1602 /* This main loop will run until the idle handler has stopped it: */
1603 g_main_loop_run (data->loop);
1605 g_main_loop_unref (data->loop);
1606 /* g_main_context_unref (context); */
1608 g_slice_free (CheckAccountIdleData, data);
1610 return data->is_online;
1616 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1618 /* GTK_RESPONSE_HELP means we need to show the certificate */
1619 if (response_id == GTK_RESPONSE_HELP) {
1623 /* Do not close the dialog */
1624 g_signal_stop_emission_by_name (dialog, "response");
1626 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1627 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1628 gtk_dialog_run (GTK_DIALOG(note));
1629 gtk_widget_destroy (note);
1635 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1636 const gchar *certificate)
1640 ModestWindow *main_win;
1642 if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
1643 g_warning ("%s: don't show dialogs if there's no main window; assuming 'Cancel'",
1648 /* don't create it */
1649 main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
1650 g_return_val_if_fail (main_win, FALSE); /* should not happen */
1653 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1656 note = hildon_note_new_confirmation_add_buttons (
1657 GTK_WINDOW(main_win),
1659 _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK,
1660 _("mcen_bd_view"), GTK_RESPONSE_HELP, /* abusing this... */
1661 _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL,
1664 g_signal_connect (G_OBJECT(note), "response",
1665 G_CALLBACK(on_cert_dialog_response),
1666 (gpointer) certificate);
1668 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1670 response = gtk_dialog_run(GTK_DIALOG(note));
1672 on_destroy_dialog (GTK_DIALOG(note));
1675 return response == GTK_RESPONSE_OK;
1681 modest_platform_run_alert_dialog (const gchar* prompt,
1682 gboolean is_question)
1684 ModestWindow *main_win;
1686 if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
1687 g_warning ("%s:\n'%s'\ndon't show dialogs if there's no main window;"
1688 " assuming 'Cancel' for questions, 'Ok' otherwise", prompt, __FUNCTION__);
1689 return is_question ? FALSE : TRUE;
1692 main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (), FALSE);
1693 g_return_val_if_fail (main_win, FALSE); /* should not happen */
1695 gboolean retval = TRUE;
1697 /* The Tinymail documentation says that we should show Yes and No buttons,
1698 * when it is a question.
1699 * Obviously, we need tinymail to use more specific error codes instead,
1700 * so we know what buttons to show. */
1701 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (main_win),
1703 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1704 GTK_WINDOW (dialog));
1706 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1707 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1709 on_destroy_dialog (GTK_DIALOG(dialog));
1711 /* Just show the error text and use the default response: */
1712 modest_platform_run_information_dialog (GTK_WINDOW (main_win),