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 <tny-maemo-conic-device.h>
44 #include <tny-simple-list.h>
45 #include <tny-folder.h>
46 #include <tny-camel-imap-store-account.h>
47 #include <tny-camel-pop-store-account.h>
48 #include <gtk/gtkicontheme.h>
49 #include <gtk/gtkmenuitem.h>
50 #include <gtk/gtkmain.h>
51 #include <modest-text-utils.h>
52 #include "modest-tny-folder.h"
54 #include <libgnomevfs/gnome-vfs-mime-utils.h>
56 #ifdef MODEST_HAVE_ABOOK
57 #include <libosso-abook/osso-abook.h>
58 #endif /*MODEST_HAVE_ABOOK*/
60 #ifdef MODEST_HAVE_LIBALARM
61 #include <alarmd/alarm_event.h> /* For alarm_event_add(), etc. */
62 #endif /*MODEST_HAVE_LIBALARM*/
65 #define HILDON_OSSO_URI_ACTION "uri-action"
66 #define URI_ACTION_COPY "copy:"
69 on_modest_conf_update_interval_changed (ModestConf* self,
71 ModestConfEvent event,
72 ModestConfNotificationId id,
75 g_return_if_fail (key);
77 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
78 const guint update_interval_minutes =
79 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
80 modest_platform_set_update_interval (update_interval_minutes);
87 check_required_files (void)
89 FILE *mcc_file = modest_maemo_open_mcc_mapping_file ();
91 g_printerr ("modest: check for mcc file failed\n");
96 if (access (MODEST_PROVIDERS_DATA_PATH, R_OK) != 0) {
97 g_printerr ("modest: cannot find providers data\n");
105 /* the gpointer here is the osso_context. */
107 modest_platform_init (int argc, char *argv[])
109 osso_context_t *osso_context;
111 osso_hw_state_t hw_state = { 0 };
115 if (!check_required_files ()) {
116 g_printerr ("modest: missing required files\n");
120 osso_context = osso_initialize(PACKAGE,PACKAGE_VERSION,
123 g_printerr ("modest: failed to acquire osso context\n");
126 modest_maemo_utils_set_osso_context (osso_context);
128 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
129 g_printerr ("modest: could not get dbus connection\n");
133 /* Add a D-Bus handler to be used when the main osso-rpc
134 * D-Bus handler has not handled something.
135 * We use this for D-Bus methods that need to use more complex types
136 * than osso-rpc supports.
138 if (!dbus_connection_add_filter (con,
139 modest_dbus_req_filter,
143 g_printerr ("modest: Could not add D-Bus filter\n");
147 /* Register our simple D-Bus callbacks, via the osso API: */
148 osso_return_t result = osso_rpc_set_cb_f(osso_context,
152 modest_dbus_req_handler, NULL /* user_data */);
153 if (result != OSSO_OK) {
154 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
158 /* Register hardware event dbus callback: */
159 hw_state.shutdown_ind = TRUE;
160 osso_hw_set_event_cb(osso_context, NULL,/*&hw_state*/ modest_osso_cb_hw_state_handler, NULL);
162 /* Register osso auto-save callbacks: */
163 result = osso_application_set_autosave_cb (osso_context,
164 modest_on_osso_application_autosave, NULL /* user_data */);
165 if (result != OSSO_OK) {
166 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
171 /* Make sure that the update interval is changed whenever its gconf key
173 /* CAUTION: we're not using here the
174 modest_conf_listen_to_namespace because we know that there
175 are other parts of Modest listening for this namespace, so
176 we'll receive the notifications anyway. We basically do not
177 use it because there is no easy way to do the
178 modest_conf_forget_namespace */
179 ModestConf *conf = modest_runtime_get_conf ();
180 g_signal_connect (G_OBJECT(conf),
182 G_CALLBACK (on_modest_conf_update_interval_changed),
185 /* only force the setting of the default interval, if there are actually
187 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
189 /* Get the initial update interval from gconf: */
190 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
191 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
192 modest_account_mgr_free_account_names (acc_names);
196 #ifdef MODEST_HAVE_ABOOK
197 /* initialize the addressbook */
198 if (!osso_abook_init (&argc, &argv, osso_context)) {
199 g_printerr ("modest: failed to initialized addressbook\n");
202 #endif /*MODEST_HAVE_ABOOK*/
208 modest_platform_uninit (void)
210 osso_context_t *osso_context =
211 modest_maemo_utils_get_osso_context ();
213 osso_deinitialize (osso_context);
222 modest_platform_get_new_device (void)
224 return TNY_DEVICE (tny_maemo_conic_device_new ());
228 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
229 gchar **effective_mime_type)
231 GString *mime_str = NULL;
232 gchar *icon_name = NULL;
233 gchar **icons, **cursor;
235 if (!mime_type || !g_ascii_strcasecmp (mime_type, "application/octet-stream"))
236 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
238 mime_str = g_string_new (mime_type);
239 g_string_ascii_down (mime_str);
242 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
243 for (cursor = icons; cursor; ++cursor) {
244 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
245 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
246 icon_name = g_strdup ("qgn_list_messagin");
248 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
249 icon_name = g_strdup (*cursor);
255 if (effective_mime_type)
256 *effective_mime_type = g_string_free (mime_str, FALSE);
258 g_string_free (mime_str, TRUE);
265 modest_platform_activate_uri (const gchar *uri)
267 HildonURIAction *action;
268 gboolean result = FALSE;
269 GSList *actions, *iter = NULL;
271 g_return_val_if_fail (uri, FALSE);
275 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
277 for (iter = actions; iter; iter = g_slist_next (iter)) {
278 action = (HildonURIAction*) iter->data;
279 if (action && strcmp (hildon_uri_action_get_service (action),
280 "com.nokia.modest") == 0) {
282 result = hildon_uri_open (uri, action, &err);
283 if (!result && err) {
284 g_printerr ("modest: modest_platform_activate_uri : %s",
285 err->message ? err->message : "unknown error");
292 /* if we could not open it with email, try something else */
294 result = hildon_uri_open (uri, NULL, NULL);
297 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
303 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
307 gchar *uri_path = NULL;
309 uri_path = g_strconcat ("file://", path, NULL);
310 con = osso_get_dbus_connection (modest_maemo_utils_get_osso_context());
313 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
315 result = hildon_mime_open_file (con, uri_path);
317 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"));
325 } ModestPlatformPopupInfo;
328 delete_uri_popup (GtkWidget *menu,
332 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
334 g_free (popup_info->uri);
335 hildon_uri_free_actions (popup_info->actions);
341 activate_uri_popup_item (GtkMenuItem *menu_item,
345 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
346 const gchar* action_name;
348 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
350 g_printerr ("modest: no action name defined\n");
354 /* special handling for the copy menu item -- copy the uri to the clipboard */
355 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
356 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
357 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
358 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
360 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
361 action_name += strlen ("mailto:");
363 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
364 return; /* we're done */
367 /* now, the real uri-actions... */
368 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
369 HildonURIAction *action = (HildonURIAction *) node->data;
370 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
371 hildon_uri_open (popup_info->uri, action, NULL);
378 modest_platform_show_uri_popup (const gchar *uri)
380 GSList *actions_list;
385 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
386 if (actions_list != NULL) {
388 GtkWidget *menu = gtk_menu_new ();
389 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
391 popup_info->actions = actions_list;
392 popup_info->uri = g_strdup (uri);
394 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
395 GtkWidget *menu_item;
396 const gchar *action_name;
397 const gchar *translation_domain;
398 HildonURIAction *action = (HildonURIAction *) node->data;
399 action_name = hildon_uri_action_get_name (action);
400 translation_domain = hildon_uri_action_get_translation_domain (action);
401 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
402 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
403 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
406 if (hildon_uri_is_default_action (action, NULL)) {
407 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
409 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
411 gtk_widget_show (menu_item);
414 /* always add the copy item */
415 GtkWidget* menu_item = gtk_menu_item_new_with_label (dgettext("osso-uri", "uri_link_copy_link_location"));
416 g_object_set_data_full (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION,
417 g_strconcat (URI_ACTION_COPY, uri, NULL),
419 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),NULL);
420 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
421 gtk_widget_show (menu_item);
424 /* and what to do when the link is deleted */
425 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
426 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
429 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
437 modest_platform_get_icon (const gchar *name)
440 GdkPixbuf* pixbuf = NULL;
441 GtkIconTheme *current_theme = NULL;
443 g_return_val_if_fail (name, NULL);
445 /* strlen == 0 is not really an error; it just
446 * means the icon is not available
448 if (!name || strlen(name) == 0)
451 #if 0 /* do we still need this? */
452 if (g_str_has_suffix (name, ".png")) { /*FIXME: hack*/
453 pixbuf = gdk_pixbuf_new_from_file (name, &err);
455 g_printerr ("modest: error loading icon '%s': %s\n",
463 current_theme = gtk_icon_theme_get_default ();
464 pixbuf = gtk_icon_theme_load_icon (current_theme, name, 26,
465 GTK_ICON_LOOKUP_NO_SVG,
468 g_printerr ("modest: error loading theme icon '%s': %s\n",
476 modest_platform_get_app_name (void)
478 return _("mcen_ap_name");
482 entry_insert_text (GtkEditable *editable,
491 chars = gtk_editable_get_chars (editable, 0, -1);
492 chars_length = g_utf8_strlen (chars, -1);
494 /* Show WID-INF036 */
495 if (chars_length >= 20) {
496 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
497 _CS("ckdg_ib_maximum_characters_reached"));
499 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
503 tmp = g_strndup (folder_name_forbidden_chars,
504 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
505 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
506 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
511 /* Write the text in the entry if it's valid */
512 g_signal_handlers_block_by_func (editable,
513 (gpointer) entry_insert_text, data);
514 gtk_editable_insert_text (editable, text, length, position);
515 g_signal_handlers_unblock_by_func (editable,
516 (gpointer) entry_insert_text, data);
519 /* Do not allow further processing */
520 g_signal_stop_emission_by_name (editable, "insert_text");
524 entry_changed (GtkEditable *editable,
528 GtkWidget *ok_button;
531 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
532 ok_button = GTK_WIDGET (buttons->next->data);
534 chars = gtk_editable_get_chars (editable, 0, -1);
535 g_return_if_fail (chars != NULL);
538 if (g_utf8_strlen (chars,-1) >= 21)
539 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
540 _CS("ckdg_ib_maximum_characters_reached"));
542 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
545 g_list_free (buttons);
550 launch_sort_headers_dialog (GtkWindow *parent_window,
551 HildonSortDialog *dialog)
553 ModestHeaderView *header_view = NULL;
555 GtkSortType sort_type;
557 gint default_key = 0;
559 gboolean outgoing = FALSE;
560 gint current_sort_colid = -1;
561 GtkSortType current_sort_type;
562 gint attachments_sort_id;
563 gint priority_sort_id;
564 GtkTreeSortable *sortable;
566 /* Get header window */
567 if (MODEST_IS_MAIN_WINDOW (parent_window)) {
568 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_window),
569 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
574 /* Add sorting keys */
575 cols = modest_header_view_get_columns (header_view);
576 if (cols == NULL) return;
577 int sort_model_ids[6];
581 outgoing = (GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cols->data), MODEST_HEADER_VIEW_COLUMN))==
582 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT);
584 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_sender_recipient"));
586 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
587 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
589 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
590 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
593 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_date"));
595 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
596 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE;
598 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
599 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE;
601 default_key = sort_key;
603 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_subject"));
604 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
606 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
608 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
610 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_attachment"));
611 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
612 sort_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
613 attachments_sort_id = sort_key;
615 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_size"));
616 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN;
617 sort_ids[sort_key] = 0;
619 sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_priority"));
620 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
621 sort_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY_MASK;
622 priority_sort_id = sort_key;
624 sortable = GTK_TREE_SORTABLE (gtk_tree_model_filter_get_model
625 (GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)))));
627 if (!gtk_tree_sortable_get_sort_column_id (sortable,
628 ¤t_sort_colid, ¤t_sort_type)) {
629 hildon_sort_dialog_set_sort_key (dialog, default_key);
630 hildon_sort_dialog_set_sort_order (dialog, GTK_SORT_DESCENDING);
632 hildon_sort_dialog_set_sort_order (dialog, current_sort_type);
633 if (current_sort_colid == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
634 gpointer flags_sort_type_pointer;
635 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), MODEST_HEADER_VIEW_FLAG_SORT);
636 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY_MASK)
637 hildon_sort_dialog_set_sort_key (dialog, priority_sort_id);
639 hildon_sort_dialog_set_sort_key (dialog, attachments_sort_id);
641 gint current_sort_keyid = 0;
642 while (current_sort_keyid < 6) {
643 if (sort_model_ids[current_sort_keyid] == current_sort_colid)
646 current_sort_keyid++;
648 hildon_sort_dialog_set_sort_key (dialog, current_sort_keyid);
652 result = gtk_dialog_run (GTK_DIALOG (dialog));
653 if (result == GTK_RESPONSE_OK) {
654 sort_key = hildon_sort_dialog_get_sort_key (dialog);
655 sort_type = hildon_sort_dialog_get_sort_order (dialog);
656 if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
657 g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
658 GINT_TO_POINTER (sort_ids[sort_key]));
659 /* This is a hack to make it resort rows always when flag fields are
660 * selected. If we do not do this, changing sort field from priority to
661 * attachments does not work */
662 modest_header_view_sort_by_column_id (header_view, 0, sort_type);
664 gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data),
665 sort_model_ids[sort_key]);
668 modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
669 gtk_tree_sortable_sort_column_changed (sortable);
672 modest_widget_memory_save (modest_runtime_get_conf (),
673 G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
675 /* while (gtk_events_pending ()) */
676 /* gtk_main_iteration (); */
685 on_response (GtkDialog *dialog,
689 GList *child_vbox, *child_hbox;
690 GtkWidget *hbox, *entry;
691 TnyFolderStore *parent;
693 if (response != GTK_RESPONSE_ACCEPT)
697 child_vbox = gtk_container_get_children (GTK_CONTAINER (dialog->vbox));
698 hbox = child_vbox->data;
699 child_hbox = gtk_container_get_children (GTK_CONTAINER (hbox));
700 entry = child_hbox->next->data;
702 parent = TNY_FOLDER_STORE (user_data);
704 /* Look for another folder with the same name */
705 if (modest_tny_folder_has_subfolder_with_name (parent,
706 gtk_entry_get_text (GTK_ENTRY (entry)))) {
708 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
709 NULL, _CS("ckdg_ib_folder_already_exists"));
710 /* Select the text */
711 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
712 gtk_widget_grab_focus (entry);
713 /* Do not close the dialog */
714 g_signal_stop_emission_by_name (dialog, "response");
721 modest_platform_run_folder_name_dialog (GtkWindow *parent_window,
722 TnyFolderStore *parent,
723 const gchar *dialog_title,
724 const gchar *label_text,
725 const gchar *suggested_name,
728 GtkWidget *accept_btn = NULL;
729 GtkWidget *dialog, *entry, *label, *hbox;
730 GList *buttons = NULL;
733 /* Ask the user for the folder name */
734 dialog = gtk_dialog_new_with_buttons (dialog_title,
736 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
737 _("mcen_bd_dialog_ok"),
739 _("mcen_bd_dialog_cancel"),
743 /* Add accept button (with unsensitive handler) */
744 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
745 accept_btn = GTK_WIDGET (buttons->next->data);
746 /* Create label and entry */
747 label = gtk_label_new (label_text);
748 /* TODO: check that the suggested name does not exist */
749 /* We set 21 as maximum because we want to show WID-INF036
750 when the user inputs more that 20 */
751 entry = gtk_entry_new_with_max_length (21);
753 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
755 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
756 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
758 /* Connect to the response method to avoid closing the dialog
759 when an invalid name is selected*/
760 g_signal_connect (dialog,
762 G_CALLBACK (on_response),
765 /* Track entry changes */
766 g_signal_connect (entry,
768 G_CALLBACK (entry_insert_text),
770 g_signal_connect (entry,
772 G_CALLBACK (entry_changed),
775 /* Create the hbox */
776 hbox = gtk_hbox_new (FALSE, 12);
777 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, FALSE, 0);
778 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, FALSE, 0);
780 /* Add hbox to dialog */
781 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
782 hbox, FALSE, FALSE, 0);
784 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
785 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
787 result = gtk_dialog_run (GTK_DIALOG(dialog));
788 if (result == GTK_RESPONSE_ACCEPT)
789 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
791 gtk_widget_destroy (dialog);
793 while (gtk_events_pending ())
794 gtk_main_iteration ();
800 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
801 TnyFolderStore *parent_folder,
802 gchar *suggested_name,
805 gchar *real_suggested_name = NULL;
808 if(suggested_name == NULL)
810 const gchar *default_name = _("mcen_ia_default_folder_name");
814 for(i = 0; i < 100; ++ i) {
815 gboolean exists = FALSE;
817 sprintf(num_str, "%.2u", i);
820 real_suggested_name = g_strdup (default_name);
822 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
825 exists = modest_tny_folder_has_subfolder_with_name (parent_folder,
826 real_suggested_name);
831 g_free (real_suggested_name);
834 /* Didn't find a free number */
836 real_suggested_name = g_strdup (default_name);
838 real_suggested_name = suggested_name;
841 result = modest_platform_run_folder_name_dialog (parent_window,
843 _("mcen_ti_new_folder"),
844 _("mcen_fi_new_folder_name"),
847 if (suggested_name == NULL)
848 g_free(real_suggested_name);
854 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
855 TnyFolderStore *parent_folder,
856 const gchar *suggested_name,
859 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
861 return modest_platform_run_folder_name_dialog (parent_window,
863 _HL("ckdg_ti_rename_folder"),
864 _HL("ckdg_fi_rename_name"),
872 on_destroy_dialog (GtkDialog *dialog)
874 gtk_widget_destroy (GTK_WIDGET(dialog));
875 if (gtk_events_pending ())
876 gtk_main_iteration ();
880 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
881 const gchar *message)
886 dialog = hildon_note_new_confirmation (parent_window, message);
887 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
888 GTK_WINDOW (dialog));
890 response = gtk_dialog_run (GTK_DIALOG (dialog));
892 on_destroy_dialog (GTK_DIALOG(dialog));
894 while (gtk_events_pending ())
895 gtk_main_iteration ();
901 modest_platform_run_yes_no_dialog (GtkWindow *parent_window,
902 const gchar *message)
907 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
908 _("mcen_bd_yes"), GTK_RESPONSE_YES,
909 _("mcen_bd_no"), GTK_RESPONSE_NO,
911 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
912 response = gtk_dialog_run (GTK_DIALOG (dialog));
914 on_destroy_dialog (GTK_DIALOG(dialog));
916 while (gtk_events_pending ())
917 gtk_main_iteration ();
925 modest_platform_run_information_dialog (GtkWindow *parent_window,
926 const gchar *message)
930 note = hildon_note_new_information (parent_window, message);
931 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
934 g_signal_connect_swapped (note,
936 G_CALLBACK (on_destroy_dialog),
939 gtk_widget_show_all (note);
944 typedef struct _ConnectAndWaitData {
946 GMainLoop *wait_loop;
947 gboolean has_callback;
949 } ConnectAndWaitData;
953 quit_wait_loop (TnyAccount *account,
954 ConnectAndWaitData *data)
956 /* Set the has_callback to TRUE (means that the callback was
957 executed and wake up every code waiting for cond to be
959 g_mutex_lock (data->mutex);
960 data->has_callback = TRUE;
962 g_main_loop_quit (data->wait_loop);
963 g_mutex_unlock (data->mutex);
967 on_connection_status_changed (TnyAccount *account,
968 TnyConnectionStatus status,
971 TnyConnectionStatus conn_status;
972 ConnectAndWaitData *data;
974 /* Ignore if reconnecting or disconnected */
975 conn_status = tny_account_get_connection_status (account);
976 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
977 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
980 /* Remove the handler */
981 data = (ConnectAndWaitData *) user_data;
982 g_signal_handler_disconnect (account, data->handler);
984 /* Quit from wait loop */
985 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
989 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
994 /* Quit from wait loop */
995 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
999 modest_platform_connect_and_wait (GtkWindow *parent_window,
1000 TnyAccount *account)
1002 ConnectAndWaitData *data = NULL;
1003 gboolean device_online;
1005 TnyConnectionStatus conn_status;
1007 device = modest_runtime_get_device();
1008 device_online = tny_device_is_online (device);
1010 /* If there is no account check only the device status */
1015 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), NULL);
1018 /* Return if the account is already connected */
1019 conn_status = tny_account_get_connection_status (account);
1020 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1023 /* Create the helper */
1024 data = g_slice_new0 (ConnectAndWaitData);
1025 data->mutex = g_mutex_new ();
1026 data->has_callback = FALSE;
1028 /* Connect the device */
1029 if (!device_online) {
1030 /* Track account connection status changes */
1031 data->handler = g_signal_connect (account, "connection-status-changed",
1032 G_CALLBACK (on_connection_status_changed),
1034 /* Try to connect the device */
1035 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), NULL);
1037 /* If the device connection failed then exit */
1038 if (!device_online && data->handler)
1041 /* Force a reconnection of the account */
1042 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1043 on_tny_camel_account_set_online_cb, data);
1046 /* Wait until the callback is executed */
1047 g_mutex_lock (data->mutex);
1048 if (!data->has_callback) {
1049 data->wait_loop = g_main_loop_new (NULL, FALSE);
1050 gdk_threads_leave ();
1051 g_mutex_unlock (data->mutex);
1052 g_main_loop_run (data->wait_loop);
1053 g_mutex_lock (data->mutex);
1054 gdk_threads_enter ();
1056 g_mutex_unlock (data->mutex);
1060 if (g_signal_handler_is_connected (account, data->handler))
1061 g_signal_handler_disconnect (account, data->handler);
1062 g_mutex_free (data->mutex);
1063 g_main_loop_unref (data->wait_loop);
1064 g_slice_free (ConnectAndWaitData, data);
1067 conn_status = tny_account_get_connection_status (account);
1068 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1072 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1074 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1075 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1076 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1077 /* This must be a maildir account, which does not require a connection: */
1082 return modest_platform_connect_and_wait (parent_window, account);
1086 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1089 return TRUE; /* Maybe it is something local. */
1091 gboolean result = TRUE;
1092 if (TNY_IS_FOLDER (folder_store)) {
1093 /* Get the folder's parent account: */
1094 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1095 if (account != NULL) {
1096 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1097 g_object_unref (account);
1099 } else if (TNY_IS_ACCOUNT (folder_store)) {
1100 /* Use the folder store as an account: */
1101 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1108 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 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1149 GTK_WINDOW (dialog));
1151 hildon_help_dialog_help_enable (GTK_DIALOG(dialog),
1152 "applications_email_sort",
1153 modest_maemo_utils_get_osso_context());
1155 /* Fill sort keys */
1157 case MODEST_SORT_HEADERS:
1158 launch_sort_headers_dialog (parent_window,
1159 HILDON_SORT_DIALOG(dialog));
1164 on_destroy_dialog (GTK_DIALOG(dialog));
1169 modest_platform_set_update_interval (guint minutes)
1171 #ifdef MODEST_HAVE_LIBALARM
1173 ModestConf *conf = modest_runtime_get_conf ();
1177 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1179 /* Delete any existing alarm,
1180 * because we will replace it: */
1182 /* TODO: What does the alarm_event_del() return value mean? */
1183 alarm_event_del(alarm_cookie);
1185 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1188 /* 0 means no updates: */
1193 /* Register alarm: */
1195 /* Set the interval in alarm_event_t structure: */
1196 alarm_event_t *event = g_new0(alarm_event_t, 1);
1197 event->alarm_time = minutes * 60; /* seconds */
1199 /* Set recurrence every few minutes: */
1200 event->recurrence = minutes;
1201 event->recurrence_count = -1; /* Means infinite */
1203 /* Specify what should happen when the alarm happens:
1204 * It should call this D-Bus method: */
1206 event->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1207 event->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1208 event->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1209 event->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1211 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1212 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1213 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1214 * This is why we want to use the Alarm API instead of just g_timeout_add().
1215 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1217 event->flags = ALARM_EVENT_NO_DIALOG | ALARM_EVENT_ACTIVATION;
1219 alarm_cookie = alarm_event_add (event);
1222 alarm_event_free (event);
1224 /* Store the alarm ID in GConf, so we can remove it later:
1225 * This is apparently valid between application instances. */
1226 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1228 if (!alarm_cookie) {
1230 const alarm_error_t alarm_error = alarmd_get_error ();
1231 g_debug ("Error setting alarm event. Error code: '%d'\n", alarm_error);
1233 /* Give people some clue: */
1234 /* The alarm API should have a function for this: */
1235 if (alarm_error == ALARMD_ERROR_DBUS) {
1236 g_debug (" ALARMD_ERROR_DBUS: An error with D-Bus occurred, probably coudn't get a D-Bus connection.\n");
1237 } else if (alarm_error == ALARMD_ERROR_CONNECTION) {
1238 g_debug (" ALARMD_ERROR_CONNECTION: Could not contact alarmd via D-Bus.\n");
1239 } else if (alarm_error == ALARMD_ERROR_INTERNAL) {
1240 g_debug (" ALARMD_ERROR_INTERNAL: Some alarmd or libalarm internal error, possibly a version mismatch.\n");
1241 } else if (alarm_error == ALARMD_ERROR_MEMORY) {
1242 g_debug (" ALARMD_ERROR_MEMORY: A memory allocation failed.\n");
1243 } else if (alarm_error == ALARMD_ERROR_ARGUMENT) {
1244 g_debug (" ALARMD_ERROR_ARGUMENT: An argument given by caller was invalid.\n");
1245 } else if (alarm_error == ALARMD_ERROR_NOT_RUNNING) {
1246 g_debug (" ALARMD_ERROR_NOT_RUNNING: alarmd is not running.\n");
1251 #endif /* MODEST_HAVE_LIBALARM */
1256 modest_platform_on_new_headers_received (TnyList *header_list)
1258 #ifdef MODEST_HAVE_HILDON_NOTIFY
1259 HildonNotification *notification;
1261 GSList *notifications_list = NULL;
1263 /* Get previous notifications ids */
1264 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1265 MODEST_CONF_NOTIFICATION_IDS,
1266 MODEST_CONF_VALUE_INT, NULL);
1268 iter = tny_list_create_iterator (header_list);
1269 while (!tny_iterator_is_done (iter)) {
1270 gchar *url = NULL, *display_address = NULL, *summary = NULL;
1271 const gchar *display_date;
1272 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1273 TnyFolder *folder = tny_header_get_folder (header);
1274 gboolean first_notification = TRUE;
1277 /* constant string, don't free */
1278 display_date = modest_text_utils_get_display_date (tny_header_get_date_received (header));
1280 display_address = g_strdup(tny_header_get_from (header));
1281 modest_text_utils_get_display_address (display_address); /* string is changed in-place */
1283 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1284 notification = hildon_notification_new (summary,
1285 tny_header_get_subject (header),
1286 "qgn_list_messagin",
1288 /* Create the message URL */
1289 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1290 tny_header_get_uid (header));
1292 hildon_notification_add_dbus_action(notification,
1295 MODEST_DBUS_SERVICE,
1298 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1302 /* Play sound if the user wants. Show the LED
1303 pattern. Show and play just one */
1304 if (G_UNLIKELY (first_notification)) {
1305 first_notification = FALSE;
1306 if (modest_conf_get_bool (modest_runtime_get_conf (),
1307 MODEST_CONF_PLAY_SOUND_MSG_ARRIVE,
1309 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1310 "sound-file", "/usr/share/sounds/ui-new_email.wav");
1313 /* Set the led pattern */
1314 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1316 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1318 "PatternCommunicationEmail");
1321 /* Notify. We need to do this in an idle because this function
1322 could be called from a thread */
1323 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1325 /* Save id in the list */
1326 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1327 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1328 /* We don't listen for the "closed" signal, because we
1329 don't care about if the notification was removed or
1330 not to store the list in gconf */
1332 /* Free & carry on */
1333 g_free (display_address);
1336 g_object_unref (folder);
1337 g_object_unref (header);
1338 tny_iterator_next (iter);
1340 g_object_unref (iter);
1343 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1344 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1346 g_slist_free (notifications_list);
1348 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1352 modest_platform_remove_new_mail_notifications (void)
1354 #ifdef MODEST_HAVE_HILDON_NOTIFY
1355 GSList *notif_list = NULL;
1357 /* Get previous notifications ids */
1358 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1359 MODEST_CONF_NOTIFICATION_IDS,
1360 MODEST_CONF_VALUE_INT, NULL);
1362 while (notif_list) {
1364 NotifyNotification *notif;
1366 /* Nasty HACK to remove the notifications, set the id
1367 of the existing ones and then close them */
1368 notif_id = GPOINTER_TO_INT(notif_list->data);
1369 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1370 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1372 /* Close the notification, note that some ids could be
1373 already invalid, but we don't care because it does
1375 notify_notification_close(notif, NULL);
1376 g_object_unref(notif);
1378 /* Delete the link, it's like going to the next */
1379 notif_list = g_slist_delete_link (notif_list, notif_list);
1383 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1384 notif_list, MODEST_CONF_VALUE_INT, NULL);
1386 g_slist_free (notif_list);
1388 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1394 modest_platform_get_global_settings_dialog ()
1396 return modest_maemo_global_settings_dialog_new ();
1400 modest_platform_show_help (GtkWindow *parent_window,
1401 const gchar *help_id)
1403 osso_return_t result;
1404 g_return_if_fail (help_id);
1406 result = hildon_help_show (modest_maemo_utils_get_osso_context(),
1407 help_id, HILDON_HELP_SHOW_DIALOG);
1409 if (result != OSSO_OK) {
1411 error_msg = g_strdup_printf ("FIXME The help topic %s could not be found", help_id);
1412 hildon_banner_show_information (GTK_WIDGET (parent_window),
1420 modest_platform_show_search_messages (GtkWindow *parent_window)
1422 osso_return_t result = OSSO_ERROR;
1424 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1425 "osso_global_search",
1426 "search_email", NULL, DBUS_TYPE_INVALID);
1428 if (result != OSSO_OK) {
1429 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1434 modest_platform_show_addressbook (GtkWindow *parent_window)
1436 osso_return_t result = OSSO_ERROR;
1438 result = osso_rpc_run_with_defaults (modest_maemo_utils_get_osso_context(),
1440 "top_application", NULL, DBUS_TYPE_INVALID);
1442 if (result != OSSO_OK) {
1443 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1448 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1450 GtkWidget *widget = modest_folder_view_new (query);
1452 /* Show one account by default */
1453 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1454 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1457 /* Restore settings */
1458 modest_widget_memory_restore (modest_runtime_get_conf(),
1460 MODEST_CONF_FOLDER_VIEW_KEY);
1466 modest_platform_information_banner (GtkWidget *parent,
1467 const gchar *icon_name,
1470 hildon_banner_show_information (parent, icon_name, text);
1474 modest_platform_animation_banner (GtkWidget *parent,
1475 const gchar *animation_name,
1478 GtkWidget *inf_note = NULL;
1480 g_return_val_if_fail (text != NULL, NULL);
1482 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1490 TnyAccount *account;
1493 } CheckAccountIdleData;
1495 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1498 on_timeout_check_account_is_online(gpointer user_data)
1500 printf ("DEBUG: %s:\n", __FUNCTION__);
1501 CheckAccountIdleData *data = (CheckAccountIdleData*)user_data;
1503 g_return_val_if_fail (data && data->account, FALSE);
1505 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__,
1506 tny_account_get_connection_status (data->account));
1508 gboolean stop_trying = FALSE;
1509 if (data && data->account &&
1510 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1511 * after which the account is likely to be usable, or never likely to be usable soon: */
1512 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1514 data->is_online = TRUE;
1519 /* Give up if we have tried too many times: */
1520 if (data->count_tries >= NUMBER_OF_TRIES)
1525 /* Wait for another timeout: */
1526 ++(data->count_tries);
1531 /* Allow the function that requested this idle callback to continue: */
1533 g_main_loop_quit (data->loop);
1536 g_object_unref (data->account);
1538 return FALSE; /* Don't call this again. */
1540 return TRUE; /* Call this timeout callback again. */
1544 /* Return TRUE immediately if the account is already online,
1545 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1546 * soon as the account is online, or FALSE if the account does
1547 * not become online in the NUMBER_OF_TRIES seconds.
1548 * This is useful when the D-Bus method was run immediately after
1549 * the application was started (when using D-Bus activation),
1550 * because the account usually takes a short time to go online.
1551 * The return value is maybe not very useful.
1554 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1556 g_return_val_if_fail (account, FALSE);
1558 printf ("DEBUG: %s: account id=%s\n", __FUNCTION__, tny_account_get_id (account));
1560 if (!tny_device_is_online (modest_runtime_get_device())) {
1561 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1565 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1566 * so we avoid wait unnecessarily: */
1567 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1568 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account) ) {
1572 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n",
1573 __FUNCTION__, tny_account_get_connection_status (account));
1575 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1576 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1577 * we want to avoid. */
1578 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1581 /* This blocks on the result: */
1582 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1583 data->is_online = FALSE;
1584 data->account = account;
1585 g_object_ref (data->account);
1586 data->count_tries = 0;
1588 GMainContext *context = NULL; /* g_main_context_new (); */
1589 data->loop = g_main_loop_new (context, FALSE /* not running */);
1591 g_timeout_add (1000, on_timeout_check_account_is_online, data);
1593 /* This main loop will run until the idle handler has stopped it: */
1594 g_main_loop_run (data->loop);
1596 g_main_loop_unref (data->loop);
1597 /* g_main_context_unref (context); */
1599 g_slice_free (CheckAccountIdleData, data);
1601 return data->is_online;
1607 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1609 /* GTK_RESPONSE_HELP means we need to show the certificate */
1610 if (response_id == GTK_RESPONSE_HELP) {
1614 /* Do not close the dialog */
1615 g_signal_stop_emission_by_name (dialog, "response");
1617 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1618 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1619 gtk_dialog_run (GTK_DIALOG(note));
1620 gtk_widget_destroy (note);
1626 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1627 const gchar *certificate)
1631 ModestWindow *main_win;
1633 if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
1634 g_warning ("%s: don't show dialogs if there's no main window; assuming 'Cancel'",
1639 /* don't create it */
1640 main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
1641 g_return_val_if_fail (main_win, FALSE); /* should not happen */
1644 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1647 note = hildon_note_new_confirmation_add_buttons (
1648 GTK_WINDOW(main_win),
1650 _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK,
1651 _("mcen_bd_view"), GTK_RESPONSE_HELP, /* abusing this... */
1652 _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL,
1655 g_signal_connect (G_OBJECT(note), "response",
1656 G_CALLBACK(on_cert_dialog_response),
1657 (gpointer) certificate);
1659 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1661 response = gtk_dialog_run(GTK_DIALOG(note));
1663 on_destroy_dialog (GTK_DIALOG(note));
1666 return response == GTK_RESPONSE_OK;
1672 modest_platform_run_alert_dialog (const gchar* prompt,
1673 gboolean is_question)
1675 ModestWindow *main_win;
1677 if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
1678 g_warning ("%s:\n'%s'\ndon't show dialogs if there's no main window;"
1679 " assuming 'Cancel' for questions, 'Ok' otherwise", prompt, __FUNCTION__);
1680 return is_question ? FALSE : TRUE;
1683 main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (), FALSE);
1684 g_return_val_if_fail (main_win, FALSE); /* should not happen */
1686 gboolean retval = TRUE;
1688 /* The Tinymail documentation says that we should show Yes and No buttons,
1689 * when it is a question.
1690 * Obviously, we need tinymail to use more specific error codes instead,
1691 * so we know what buttons to show. */
1692 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (main_win),
1694 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1695 GTK_WINDOW (dialog));
1697 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1698 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1700 on_destroy_dialog (GTK_DIALOG(dialog));
1702 /* Just show the error text and use the default response: */
1703 modest_platform_run_information_dialog (GTK_WINDOW (main_win),