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*/
66 #define HILDON_OSSO_URI_ACTION "uri-action"
67 #define URI_ACTION_COPY "copy:"
69 static osso_context_t *osso_context = NULL; /* urgh global */
72 on_modest_conf_update_interval_changed (ModestConf* self,
74 ModestConfEvent event,
75 ModestConfNotificationId id,
78 g_return_if_fail (key);
80 if (strcmp (key, MODEST_CONF_UPDATE_INTERVAL) == 0) {
81 const guint update_interval_minutes =
82 modest_conf_get_int (self, MODEST_CONF_UPDATE_INTERVAL, NULL);
83 modest_platform_set_update_interval (update_interval_minutes);
90 check_required_files (void)
92 FILE *mcc_file = modest_maemo_open_mcc_mapping_file ();
94 g_printerr ("modest: check for mcc file failed\n");
99 if (access (MODEST_PROVIDERS_DATA_PATH, R_OK) != 0) {
100 g_printerr ("modest: cannot find providers data\n");
110 modest_platform_init (int argc, char *argv[])
112 osso_hw_state_t hw_state = { 0 };
116 if (!check_required_files ()) {
117 g_printerr ("modest: missing required files\n");
123 osso_initialize(PACKAGE,PACKAGE_VERSION,
126 g_printerr ("modest: failed to acquire osso context\n");
130 if ((con = osso_get_dbus_connection (osso_context)) == NULL) {
131 g_printerr ("modest: could not get dbus connection\n");
136 /* Add a D-Bus handler to be used when the main osso-rpc
137 * D-Bus handler has not handled something.
138 * We use this for D-Bus methods that need to use more complex types
139 * than osso-rpc supports.
141 if (!dbus_connection_add_filter (con,
142 modest_dbus_req_filter,
146 g_printerr ("modest: Could not add D-Bus filter\n");
150 /* Register our simple D-Bus callbacks, via the osso API: */
151 osso_return_t result = osso_rpc_set_cb_f(osso_context,
155 modest_dbus_req_handler, NULL /* user_data */);
156 if (result != OSSO_OK) {
157 g_printerr ("modest: Error setting D-BUS callback (%d)\n", result);
161 /* Add handler for Exit D-BUS messages.
162 * Not used because osso_application_set_exit_cb() is deprecated and obsolete:
163 result = osso_application_set_exit_cb(osso_context,
164 modest_dbus_exit_event_handler,
166 if (result != OSSO_OK) {
167 g_print("Error setting exit callback (%d)\n", result);
172 /* Register hardware event dbus callback: */
173 hw_state.shutdown_ind = TRUE;
174 osso_hw_set_event_cb(osso_context, NULL,/*&hw_state*/ modest_osso_cb_hw_state_handler, NULL);
176 /* Register osso auto-save callbacks: */
177 result = osso_application_set_autosave_cb (osso_context,
178 modest_on_osso_application_autosave, NULL /* user_data */);
179 if (result != OSSO_OK) {
180 g_printerr ("modest: osso_application_set_autosave_cb() failed.\n");
185 /* Make sure that the update interval is changed whenever its gconf key
187 /* CAUTION: we're not using here the
188 modest_conf_listen_to_namespace because we know that there
189 are other parts of Modest listening for this namespace, so
190 we'll receive the notifications anyway. We basically do not
191 use it because there is no easy way to do the
192 modest_conf_forget_namespace */
193 ModestConf *conf = modest_runtime_get_conf ();
194 g_signal_connect (G_OBJECT(conf),
196 G_CALLBACK (on_modest_conf_update_interval_changed),
199 /* only force the setting of the default interval, if there are actually
201 acc_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), TRUE);
203 /* Get the initial update interval from gconf: */
204 on_modest_conf_update_interval_changed(conf, MODEST_CONF_UPDATE_INTERVAL,
205 MODEST_CONF_EVENT_KEY_CHANGED, 0, NULL);
206 modest_account_mgr_free_account_names (acc_names);
210 #ifdef MODEST_HAVE_ABOOK
211 /* initialize the addressbook */
212 if (!osso_abook_init (&argc, &argv, osso_context)) {
213 g_printerr ("modest: failed to initialized addressbook\n");
216 #endif /*MODEST_HAVE_ABOOK*/
223 modest_platform_get_new_device (void)
225 return TNY_DEVICE (tny_maemo_conic_device_new ());
229 modest_platform_get_file_icon_name (const gchar* name, const gchar* mime_type,
230 gchar **effective_mime_type)
232 GString *mime_str = NULL;
233 gchar *icon_name = NULL;
234 gchar **icons, **cursor;
236 if (!mime_type || !g_ascii_strcasecmp (mime_type, "application/octet-stream"))
237 mime_str = g_string_new (gnome_vfs_get_mime_type_for_name (name));
239 mime_str = g_string_new (mime_type);
240 g_string_ascii_down (mime_str);
243 icons = hildon_mime_get_icon_names (mime_str->str, NULL);
244 for (cursor = icons; cursor; ++cursor) {
245 if (!g_ascii_strcasecmp (*cursor, "gnome-mime-message") ||
246 !g_ascii_strcasecmp (*cursor, "gnome-mime-message-rfc822")) {
247 icon_name = g_strdup ("qgn_list_messagin");
249 } else if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default(), *cursor)) {
250 icon_name = g_strdup (*cursor);
256 if (effective_mime_type)
257 *effective_mime_type = g_string_free (mime_str, FALSE);
259 g_string_free (mime_str, TRUE);
266 modest_platform_activate_uri (const gchar *uri)
268 HildonURIAction *action;
269 gboolean result = FALSE;
270 GSList *actions, *iter = NULL;
272 g_return_val_if_fail (uri, FALSE);
276 actions = hildon_uri_get_actions_by_uri (uri, -1, NULL);
278 for (iter = actions; iter; iter = g_slist_next (iter)) {
279 action = (HildonURIAction*) iter->data;
280 if (action && strcmp (hildon_uri_action_get_service (action),
281 "com.nokia.modest") == 0) {
283 result = hildon_uri_open (uri, action, &err);
284 if (!result && err) {
285 g_printerr ("modest: modest_platform_activate_uri : %s",
286 err->message ? err->message : "unknown error");
293 /* if we could not open it with email, try something else */
295 result = hildon_uri_open (uri, NULL, NULL);
298 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
304 modest_platform_activate_file (const gchar *path, const gchar *mime_type)
308 gchar *uri_path = NULL;
310 uri_path = g_strconcat ("file://", path, NULL);
311 con = osso_get_dbus_connection (osso_context);
314 result = hildon_mime_open_file_with_mime_type (con, uri_path, mime_type);
316 result = hildon_mime_open_file (con, uri_path);
318 modest_platform_run_information_dialog (NULL, _("mcen_ni_noregistered_viewer"));
326 } ModestPlatformPopupInfo;
329 delete_uri_popup (GtkWidget *menu,
333 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
335 g_free (popup_info->uri);
336 hildon_uri_free_actions (popup_info->actions);
342 activate_uri_popup_item (GtkMenuItem *menu_item,
346 ModestPlatformPopupInfo *popup_info = (ModestPlatformPopupInfo *) userdata;
347 const gchar* action_name;
349 action_name = g_object_get_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION);
351 g_printerr ("modest: no action name defined\n");
355 /* special handling for the copy menu item -- copy the uri to the clipboard */
356 /* if it's a copy thingy, the uri will look like 'copy:http://slashdot.org' */
357 if (g_str_has_prefix (action_name, URI_ACTION_COPY)) {
358 GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
359 action_name += strlen(URI_ACTION_COPY); /* jump past the prefix */
361 if (g_str_has_prefix (action_name, "mailto:")) /* ignore mailto: prefixes */
362 action_name += strlen ("mailto:");
364 gtk_clipboard_set_text (clipboard, action_name, strlen (action_name));
365 return; /* we're done */
368 /* now, the real uri-actions... */
369 for (node = popup_info->actions; node != NULL; node = g_slist_next (node)) {
370 HildonURIAction *action = (HildonURIAction *) node->data;
371 if (strcmp (action_name, hildon_uri_action_get_name (action))==0) {
372 hildon_uri_open (popup_info->uri, action, NULL);
379 modest_platform_show_uri_popup (const gchar *uri)
381 GSList *actions_list;
386 actions_list = hildon_uri_get_actions_by_uri (uri, -1, NULL);
387 if (actions_list != NULL) {
389 GtkWidget *menu = gtk_menu_new ();
390 ModestPlatformPopupInfo *popup_info = g_new0 (ModestPlatformPopupInfo, 1);
392 popup_info->actions = actions_list;
393 popup_info->uri = g_strdup (uri);
395 for (node = actions_list; node != NULL; node = g_slist_next (node)) {
396 GtkWidget *menu_item;
397 const gchar *action_name;
398 const gchar *translation_domain;
399 HildonURIAction *action = (HildonURIAction *) node->data;
400 action_name = hildon_uri_action_get_name (action);
401 translation_domain = hildon_uri_action_get_translation_domain (action);
402 menu_item = gtk_menu_item_new_with_label (dgettext(translation_domain, action_name));
403 g_object_set_data (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION, (gpointer)action_name); /* hack */
404 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),
407 if (hildon_uri_is_default_action (action, NULL)) {
408 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
410 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
412 gtk_widget_show (menu_item);
415 /* always add the copy item */
416 GtkWidget* menu_item = gtk_menu_item_new_with_label (dgettext("osso-uri", "uri_link_copy_link_location"));
417 g_object_set_data_full (G_OBJECT(menu_item), HILDON_OSSO_URI_ACTION,
418 g_strconcat (URI_ACTION_COPY, uri, NULL),
420 g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (activate_uri_popup_item),NULL);
421 gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
422 gtk_widget_show (menu_item);
425 /* and what to do when the link is deleted */
426 g_signal_connect (G_OBJECT (menu), "delete-event", G_CALLBACK (delete_uri_popup), popup_info);
427 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time ());
430 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unsupported_link"));
438 modest_platform_get_icon (const gchar *name)
441 GdkPixbuf* pixbuf = NULL;
442 GtkIconTheme *current_theme = NULL;
444 g_return_val_if_fail (name, NULL);
446 /* strlen == 0 is not really an error; it just
447 * means the icon is not available
449 if (!name || strlen(name) == 0)
452 #if 0 /* do we still need this? */
453 if (g_str_has_suffix (name, ".png")) { /*FIXME: hack*/
454 pixbuf = gdk_pixbuf_new_from_file (name, &err);
456 g_printerr ("modest: error loading icon '%s': %s\n",
464 current_theme = gtk_icon_theme_get_default ();
465 pixbuf = gtk_icon_theme_load_icon (current_theme, name, 26,
466 GTK_ICON_LOOKUP_NO_SVG,
469 g_printerr ("modest: error loading theme icon '%s': %s\n",
477 modest_platform_get_app_name (void)
479 return _("mcen_ap_name");
483 entry_insert_text (GtkEditable *editable,
492 chars = gtk_editable_get_chars (editable, 0, -1);
493 chars_length = g_utf8_strlen (chars, -1);
495 /* Show WID-INF036 */
496 if (chars_length >= 20) {
497 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)), NULL,
498 _CS("ckdg_ib_maximum_characters_reached"));
500 if (modest_text_utils_is_forbidden_char (*text, FOLDER_NAME_FORBIDDEN_CHARS)) {
504 tmp = g_strndup (folder_name_forbidden_chars,
505 FOLDER_NAME_FORBIDDEN_CHARS_LENGTH);
506 msg = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), tmp);
507 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (data)),
512 /* Write the text in the entry if it's valid */
513 g_signal_handlers_block_by_func (editable,
514 (gpointer) entry_insert_text, data);
515 gtk_editable_insert_text (editable, text, length, position);
516 g_signal_handlers_unblock_by_func (editable,
517 (gpointer) entry_insert_text, data);
520 /* Do not allow further processing */
521 g_signal_stop_emission_by_name (editable, "insert_text");
525 entry_changed (GtkEditable *editable,
529 GtkWidget *ok_button;
532 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (user_data)->action_area));
533 ok_button = GTK_WIDGET (buttons->next->data);
535 chars = gtk_editable_get_chars (editable, 0, -1);
536 g_return_if_fail (chars != NULL);
539 if (g_utf8_strlen (chars,-1) >= 21)
540 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (user_data)), NULL,
541 _CS("ckdg_ib_maximum_characters_reached"));
543 gtk_widget_set_sensitive (ok_button, modest_text_utils_validate_folder_name(chars));
546 g_list_free (buttons);
551 launch_sort_headers_dialog (GtkWindow *parent_window,
552 HildonSortDialog *dialog)
554 ModestHeaderView *header_view = NULL;
556 GtkSortType sort_type;
558 gint default_key = 0;
560 gboolean outgoing = FALSE;
561 gint current_sort_colid = -1;
562 GtkSortType current_sort_type;
563 gint attachments_sort_id;
564 gint priority_sort_id;
565 GtkTreeSortable *sortable;
567 /* Get header window */
568 if (MODEST_IS_MAIN_WINDOW (parent_window)) {
569 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_window),
570 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
572 if (!header_view) return;
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 (GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)))));
626 if (!gtk_tree_sortable_get_sort_column_id (sortable,
627 ¤t_sort_colid, ¤t_sort_type)) {
628 hildon_sort_dialog_set_sort_key (dialog, default_key);
629 hildon_sort_dialog_set_sort_order (dialog, GTK_SORT_DESCENDING);
631 hildon_sort_dialog_set_sort_order (dialog, current_sort_type);
632 if (current_sort_colid == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
633 gpointer flags_sort_type_pointer;
634 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), MODEST_HEADER_VIEW_FLAG_SORT);
635 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY_MASK)
636 hildon_sort_dialog_set_sort_key (dialog, priority_sort_id);
638 hildon_sort_dialog_set_sort_key (dialog, attachments_sort_id);
640 gint current_sort_keyid = 0;
641 while (current_sort_keyid < 6) {
642 if (sort_model_ids[current_sort_keyid] == current_sort_colid)
645 current_sort_keyid++;
647 hildon_sort_dialog_set_sort_key (dialog, current_sort_keyid);
651 result = gtk_dialog_run (GTK_DIALOG (dialog));
652 if (result == GTK_RESPONSE_OK) {
653 sort_key = hildon_sort_dialog_get_sort_key (dialog);
654 sort_type = hildon_sort_dialog_get_sort_order (dialog);
655 if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
656 g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
657 GINT_TO_POINTER (sort_ids[sort_key]));
658 /* This is a hack to make it resort rows always when flag fields are
659 * selected. If we do not do this, changing sort field from priority to
660 * attachments does not work */
661 modest_header_view_sort_by_column_id (header_view, 0, sort_type);
663 gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data),
664 sort_model_ids[sort_key]);
667 modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
668 gtk_tree_sortable_sort_column_changed (sortable);
671 modest_widget_memory_save (modest_runtime_get_conf (),
672 G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
674 /* while (gtk_events_pending ()) */
675 /* gtk_main_iteration (); */
684 on_response (GtkDialog *dialog,
688 GList *child_vbox, *child_hbox;
689 GtkWidget *hbox, *entry;
690 TnyFolderStore *parent;
692 if (response != GTK_RESPONSE_ACCEPT)
696 child_vbox = gtk_container_get_children (GTK_CONTAINER (dialog->vbox));
697 hbox = child_vbox->data;
698 child_hbox = gtk_container_get_children (GTK_CONTAINER (hbox));
699 entry = child_hbox->next->data;
701 parent = TNY_FOLDER_STORE (user_data);
703 /* Look for another folder with the same name */
704 if (modest_tny_folder_has_subfolder_with_name (parent,
705 gtk_entry_get_text (GTK_ENTRY (entry)))) {
707 hildon_banner_show_information (gtk_widget_get_parent (GTK_WIDGET (dialog)),
708 NULL, _CS("ckdg_ib_folder_already_exists"));
709 /* Select the text */
710 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
711 gtk_widget_grab_focus (entry);
712 /* Do not close the dialog */
713 g_signal_stop_emission_by_name (dialog, "response");
720 modest_platform_run_folder_name_dialog (GtkWindow *parent_window,
721 TnyFolderStore *parent,
722 const gchar *dialog_title,
723 const gchar *label_text,
724 const gchar *suggested_name,
727 GtkWidget *accept_btn = NULL;
728 GtkWidget *dialog, *entry, *label, *hbox;
729 GList *buttons = NULL;
732 /* Ask the user for the folder name */
733 dialog = gtk_dialog_new_with_buttons (dialog_title,
735 GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
736 _("mcen_bd_dialog_ok"),
738 _("mcen_bd_dialog_cancel"),
742 /* Add accept button (with unsensitive handler) */
743 buttons = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
744 accept_btn = GTK_WIDGET (buttons->next->data);
745 /* Create label and entry */
746 label = gtk_label_new (label_text);
747 /* TODO: check that the suggested name does not exist */
748 /* We set 21 as maximum because we want to show WID-INF036
749 when the user inputs more that 20 */
750 entry = gtk_entry_new_with_max_length (21);
752 gtk_entry_set_text (GTK_ENTRY (entry), suggested_name);
754 gtk_entry_set_text (GTK_ENTRY (entry), _("mcen_ia_default_folder_name"));
755 gtk_entry_select_region (GTK_ENTRY (entry), 0, -1);
757 /* Connect to the response method to avoid closing the dialog
758 when an invalid name is selected*/
759 g_signal_connect (dialog,
761 G_CALLBACK (on_response),
764 /* Track entry changes */
765 g_signal_connect (entry,
767 G_CALLBACK (entry_insert_text),
769 g_signal_connect (entry,
771 G_CALLBACK (entry_changed),
774 /* Create the hbox */
775 hbox = gtk_hbox_new (FALSE, 12);
776 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, FALSE, 0);
777 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, FALSE, 0);
779 /* Add hbox to dialog */
780 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
781 hbox, FALSE, FALSE, 0);
783 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
784 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
786 result = gtk_dialog_run (GTK_DIALOG(dialog));
787 if (result == GTK_RESPONSE_ACCEPT)
788 *folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
790 gtk_widget_destroy (dialog);
792 while (gtk_events_pending ())
793 gtk_main_iteration ();
799 modest_platform_run_new_folder_dialog (GtkWindow *parent_window,
800 TnyFolderStore *parent_folder,
801 gchar *suggested_name,
804 gchar *real_suggested_name = NULL;
807 if(suggested_name == NULL)
809 const gchar *default_name = _("mcen_ia_default_folder_name");
813 for(i = 0; i < 100; ++ i) {
814 gboolean exists = FALSE;
816 sprintf(num_str, "%.2u", i);
819 real_suggested_name = g_strdup (default_name);
821 real_suggested_name = g_strdup_printf (_("mcen_ia_default_folder_name_s"),
824 exists = modest_tny_folder_has_subfolder_with_name (parent_folder,
825 real_suggested_name);
830 g_free (real_suggested_name);
833 /* Didn't find a free number */
835 real_suggested_name = g_strdup (default_name);
837 real_suggested_name = suggested_name;
840 result = modest_platform_run_folder_name_dialog (parent_window,
842 _("mcen_ti_new_folder"),
843 _("mcen_fi_new_folder_name"),
846 if (suggested_name == NULL)
847 g_free(real_suggested_name);
853 modest_platform_run_rename_folder_dialog (GtkWindow *parent_window,
854 TnyFolderStore *parent_folder,
855 const gchar *suggested_name,
858 g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent_folder), GTK_RESPONSE_REJECT);
860 return modest_platform_run_folder_name_dialog (parent_window,
862 _HL("ckdg_ti_rename_folder"),
863 _HL("ckdg_fi_rename_name"),
871 on_destroy_dialog (GtkDialog *dialog)
873 gtk_widget_destroy (GTK_WIDGET(dialog));
874 if (gtk_events_pending ())
875 gtk_main_iteration ();
879 modest_platform_run_confirmation_dialog (GtkWindow *parent_window,
880 const gchar *message)
885 dialog = hildon_note_new_confirmation (parent_window, message);
886 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
887 GTK_WINDOW (dialog));
889 response = gtk_dialog_run (GTK_DIALOG (dialog));
891 on_destroy_dialog (GTK_DIALOG(dialog));
893 while (gtk_events_pending ())
894 gtk_main_iteration ();
900 modest_platform_run_yes_no_dialog (GtkWindow *parent_window,
901 const gchar *message)
906 dialog = hildon_note_new_confirmation_add_buttons (parent_window, message,
907 _("mcen_bd_yes"), GTK_RESPONSE_YES,
908 _("mcen_bd_no"), GTK_RESPONSE_NO,
910 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
911 response = gtk_dialog_run (GTK_DIALOG (dialog));
913 on_destroy_dialog (GTK_DIALOG(dialog));
915 while (gtk_events_pending ())
916 gtk_main_iteration ();
924 modest_platform_run_information_dialog (GtkWindow *parent_window,
925 const gchar *message)
929 note = hildon_note_new_information (parent_window, message);
930 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
933 g_signal_connect_swapped (note,
935 G_CALLBACK (on_destroy_dialog),
938 gtk_widget_show_all (note);
943 typedef struct _ConnectAndWaitData {
945 GMainLoop *wait_loop;
946 gboolean has_callback;
948 } ConnectAndWaitData;
952 quit_wait_loop (TnyAccount *account,
953 ConnectAndWaitData *data)
955 /* Set the has_callback to TRUE (means that the callback was
956 executed and wake up every code waiting for cond to be
958 g_mutex_lock (data->mutex);
959 data->has_callback = TRUE;
961 g_main_loop_quit (data->wait_loop);
962 g_mutex_unlock (data->mutex);
966 on_connection_status_changed (TnyAccount *account,
967 TnyConnectionStatus status,
970 TnyConnectionStatus conn_status;
971 ConnectAndWaitData *data;
973 /* Ignore if reconnecting or disconnected */
974 conn_status = tny_account_get_connection_status (account);
975 if (conn_status == TNY_CONNECTION_STATUS_RECONNECTING ||
976 conn_status == TNY_CONNECTION_STATUS_DISCONNECTED)
979 /* Remove the handler */
980 data = (ConnectAndWaitData *) user_data;
981 g_signal_handler_disconnect (account, data->handler);
983 /* Quit from wait loop */
984 quit_wait_loop (account, (ConnectAndWaitData *) user_data);
988 on_tny_camel_account_set_online_cb (TnyCamelAccount *account,
993 /* Quit from wait loop */
994 quit_wait_loop (TNY_ACCOUNT (account), (ConnectAndWaitData *) user_data);
998 modest_platform_connect_and_wait (GtkWindow *parent_window,
1001 ConnectAndWaitData *data = NULL;
1002 gboolean device_online;
1004 TnyConnectionStatus conn_status;
1006 device = modest_runtime_get_device();
1007 device_online = tny_device_is_online (device);
1009 /* If there is no account check only the device status */
1014 return tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), NULL);
1017 /* Return if the account is already connected */
1018 conn_status = tny_account_get_connection_status (account);
1019 if (device_online && conn_status == TNY_CONNECTION_STATUS_CONNECTED)
1022 /* Create the helper */
1023 data = g_slice_new0 (ConnectAndWaitData);
1024 data->mutex = g_mutex_new ();
1025 data->has_callback = FALSE;
1027 /* Connect the device */
1028 if (!device_online) {
1029 /* Track account connection status changes */
1030 data->handler = g_signal_connect (account, "connection-status-changed",
1031 G_CALLBACK (on_connection_status_changed),
1033 /* Try to connect the device */
1034 device_online = tny_maemo_conic_device_connect (TNY_MAEMO_CONIC_DEVICE (device), NULL);
1036 /* If the device connection failed then exit */
1037 if (!device_online && data->handler)
1040 /* Force a reconnection of the account */
1041 tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (account), TRUE,
1042 on_tny_camel_account_set_online_cb, data);
1045 /* Wait until the callback is executed */
1046 g_mutex_lock (data->mutex);
1047 if (!data->has_callback) {
1048 data->wait_loop = g_main_loop_new (NULL, FALSE);
1049 gdk_threads_leave ();
1050 g_mutex_unlock (data->mutex);
1051 g_main_loop_run (data->wait_loop);
1052 g_mutex_lock (data->mutex);
1053 gdk_threads_enter ();
1055 g_mutex_unlock (data->mutex);
1059 if (g_signal_handler_is_connected (account, data->handler))
1060 g_signal_handler_disconnect (account, data->handler);
1061 g_mutex_free (data->mutex);
1062 g_main_loop_unref (data->wait_loop);
1063 g_slice_free (ConnectAndWaitData, data);
1066 conn_status = tny_account_get_connection_status (account);
1067 return (conn_status == TNY_CONNECTION_STATUS_CONNECTED) ? TRUE: FALSE;
1071 modest_platform_connect_and_wait_if_network_account (GtkWindow *parent_window, TnyAccount *account)
1073 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1074 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1075 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1076 /* This must be a maildir account, which does not require a connection: */
1081 return modest_platform_connect_and_wait (parent_window, account);
1085 modest_platform_connect_and_wait_if_network_folderstore (GtkWindow *parent_window, TnyFolderStore *folder_store)
1088 return TRUE; /* Maybe it is something local. */
1090 gboolean result = TRUE;
1091 if (TNY_IS_FOLDER (folder_store)) {
1092 /* Get the folder's parent account: */
1093 TnyAccount *account = tny_folder_get_account(TNY_FOLDER (folder_store));
1094 if (account != NULL) {
1095 result = modest_platform_connect_and_wait_if_network_account (NULL, account);
1096 g_object_unref (account);
1098 } else if (TNY_IS_ACCOUNT (folder_store)) {
1099 /* Use the folder store as an account: */
1100 result = modest_platform_connect_and_wait_if_network_account (NULL, TNY_ACCOUNT (folder_store));
1107 modest_platform_is_network_folderstore (TnyFolderStore *folder_store)
1109 TnyAccount *account = NULL;
1110 gboolean result = TRUE;
1112 g_return_val_if_fail(TNY_IS_FOLDER_STORE(folder_store), FALSE);
1114 if (TNY_IS_FOLDER (folder_store)) {
1115 /* Get the folder's parent account: */
1116 account = tny_folder_get_account(TNY_FOLDER(folder_store));
1117 } else if (TNY_IS_ACCOUNT (folder_store)) {
1118 account = TNY_ACCOUNT(folder_store);
1119 g_object_ref(account);
1122 if (account != NULL) {
1123 if (tny_account_get_account_type (account) == TNY_ACCOUNT_TYPE_STORE) {
1124 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1125 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account)) {
1126 /* This must be a maildir account, which does
1127 * not require a connection: */
1131 g_object_unref (account);
1140 modest_platform_run_sort_dialog (GtkWindow *parent_window,
1141 ModestSortDialogType type)
1143 GtkWidget *dialog = NULL;
1146 dialog = hildon_sort_dialog_new (parent_window);
1147 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1148 GTK_WINDOW (dialog));
1150 /* Fill sort keys */
1152 case MODEST_SORT_HEADERS:
1153 launch_sort_headers_dialog (parent_window,
1154 HILDON_SORT_DIALOG(dialog));
1159 on_destroy_dialog (GTK_DIALOG(dialog));
1164 modest_platform_set_update_interval (guint minutes)
1166 #ifdef MODEST_HAVE_LIBALARM
1168 ModestConf *conf = modest_runtime_get_conf ();
1172 cookie_t alarm_cookie = modest_conf_get_int (conf, MODEST_CONF_ALARM_ID, NULL);
1174 /* Delete any existing alarm,
1175 * because we will replace it: */
1177 /* TODO: What does the alarm_event_del() return value mean? */
1178 alarm_event_del(alarm_cookie);
1180 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, 0, NULL);
1183 /* 0 means no updates: */
1188 /* Register alarm: */
1190 /* Set the interval in alarm_event_t structure: */
1191 alarm_event_t *event = g_new0(alarm_event_t, 1);
1192 event->alarm_time = minutes * 60; /* seconds */
1194 /* Set recurrence every few minutes: */
1195 event->recurrence = minutes;
1196 event->recurrence_count = -1; /* Means infinite */
1198 /* Specify what should happen when the alarm happens:
1199 * It should call this D-Bus method: */
1201 event->dbus_path = g_strdup(MODEST_DBUS_OBJECT);
1202 event->dbus_interface = g_strdup (MODEST_DBUS_IFACE);
1203 event->dbus_service = g_strdup (MODEST_DBUS_SERVICE);
1204 event->dbus_name = g_strdup (MODEST_DBUS_METHOD_SEND_RECEIVE);
1206 /* Use ALARM_EVENT_NO_DIALOG: Otherwise, a dialog will be shown if
1207 * exec_name or dbus_path is NULL, even though we have specified no dialog text.
1208 * Also use ALARM_EVENT_ACTIVATION so that modest is started (without UI) to get emails
1209 * This is why we want to use the Alarm API instead of just g_timeout_add().
1210 * (The old maemo email-client did this, though it isn't specified in the UI spec.)
1212 event->flags = ALARM_EVENT_NO_DIALOG | ALARM_EVENT_ACTIVATION;
1214 alarm_cookie = alarm_event_add (event);
1217 alarm_event_free (event);
1219 /* Store the alarm ID in GConf, so we can remove it later:
1220 * This is apparently valid between application instances. */
1221 modest_conf_set_int (conf, MODEST_CONF_ALARM_ID, alarm_cookie, NULL);
1223 if (!alarm_cookie) {
1225 const alarm_error_t alarm_error = alarmd_get_error ();
1226 g_debug ("Error setting alarm event. Error code: '%d'\n", alarm_error);
1228 /* Give people some clue: */
1229 /* The alarm API should have a function for this: */
1230 if (alarm_error == ALARMD_ERROR_DBUS) {
1231 g_debug (" ALARMD_ERROR_DBUS: An error with D-Bus occurred, probably coudn't get a D-Bus connection.\n");
1232 } else if (alarm_error == ALARMD_ERROR_CONNECTION) {
1233 g_debug (" ALARMD_ERROR_CONNECTION: Could not contact alarmd via D-Bus.\n");
1234 } else if (alarm_error == ALARMD_ERROR_INTERNAL) {
1235 g_debug (" ALARMD_ERROR_INTERNAL: Some alarmd or libalarm internal error, possibly a version mismatch.\n");
1236 } else if (alarm_error == ALARMD_ERROR_MEMORY) {
1237 g_debug (" ALARMD_ERROR_MEMORY: A memory allocation failed.\n");
1238 } else if (alarm_error == ALARMD_ERROR_ARGUMENT) {
1239 g_debug (" ALARMD_ERROR_ARGUMENT: An argument given by caller was invalid.\n");
1240 } else if (alarm_error == ALARMD_ERROR_NOT_RUNNING) {
1241 g_debug (" ALARMD_ERROR_NOT_RUNNING: alarmd is not running.\n");
1246 #endif /* MODEST_HAVE_LIBALARM */
1251 modest_platform_on_new_headers_received (TnyList *header_list)
1253 #ifdef MODEST_HAVE_HILDON_NOTIFY
1254 HildonNotification *notification;
1256 GSList *notifications_list = NULL;
1258 /* Get previous notifications ids */
1259 notifications_list = modest_conf_get_list (modest_runtime_get_conf (),
1260 MODEST_CONF_NOTIFICATION_IDS,
1261 MODEST_CONF_VALUE_INT, NULL);
1263 iter = tny_list_create_iterator (header_list);
1264 while (!tny_iterator_is_done (iter)) {
1265 gchar *url = NULL, *display_address = NULL, *summary = NULL;
1266 const gchar *display_date;
1267 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1268 TnyFolder *folder = tny_header_get_folder (header);
1269 gboolean first_notification = TRUE;
1272 /* constant string, don't free */
1273 display_date = modest_text_utils_get_display_date (tny_header_get_date_received (header));
1275 display_address = g_strdup(tny_header_get_from (header));
1276 modest_text_utils_get_display_address (display_address); /* string is changed in-place */
1278 summary = g_strdup_printf ("%s - %s", display_date, display_address);
1279 notification = hildon_notification_new (summary,
1280 tny_header_get_subject (header),
1281 "qgn_list_messagin",
1283 /* Create the message URL */
1284 url = g_strdup_printf ("%s/%s", tny_folder_get_url_string (folder),
1285 tny_header_get_uid (header));
1287 hildon_notification_add_dbus_action(notification,
1290 MODEST_DBUS_SERVICE,
1293 MODEST_DBUS_METHOD_OPEN_MESSAGE,
1297 /* Play sound if the user wants. Show the LED
1298 pattern. Show and play just one */
1299 if (G_UNLIKELY (first_notification)) {
1300 first_notification = FALSE;
1301 if (modest_conf_get_bool (modest_runtime_get_conf (),
1302 MODEST_CONF_PLAY_SOUND_MSG_ARRIVE,
1304 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1305 "sound-file", "/usr/share/sounds/ui-new_email.wav");
1308 /* Set the led pattern */
1309 notify_notification_set_hint_int32 (NOTIFY_NOTIFICATION (notification),
1311 notify_notification_set_hint_string(NOTIFY_NOTIFICATION (notification),
1313 "PatternCommunicationEmail");
1316 /* Notify. We need to do this in an idle because this function
1317 could be called from a thread */
1318 notify_notification_show (NOTIFY_NOTIFICATION (notification), NULL);
1320 /* Save id in the list */
1321 g_object_get(G_OBJECT(notification), "id", ¬if_id, NULL);
1322 notifications_list = g_slist_prepend (notifications_list, GINT_TO_POINTER(notif_id));
1323 /* We don't listen for the "closed" signal, because we
1324 don't care about if the notification was removed or
1325 not to store the list in gconf */
1327 /* Free & carry on */
1328 g_free (display_address);
1331 g_object_unref (folder);
1332 g_object_unref (header);
1333 tny_iterator_next (iter);
1335 g_object_unref (iter);
1338 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1339 notifications_list, MODEST_CONF_VALUE_INT, NULL);
1341 g_slist_free (notifications_list);
1343 #endif /*MODEST_HAVE_HILDON_NOTIFY*/
1347 modest_platform_remove_new_mail_notifications (void)
1349 #ifdef MODEST_HAVE_HILDON_NOTIFY
1350 GSList *notif_list = NULL;
1352 /* Get previous notifications ids */
1353 notif_list = modest_conf_get_list (modest_runtime_get_conf (),
1354 MODEST_CONF_NOTIFICATION_IDS,
1355 MODEST_CONF_VALUE_INT, NULL);
1357 while (notif_list) {
1359 NotifyNotification *notif;
1361 /* Nasty HACK to remove the notifications, set the id
1362 of the existing ones and then close them */
1363 notif_id = GPOINTER_TO_INT(notif_list->data);
1364 notif = notify_notification_new("dummy", NULL, NULL, NULL);
1365 g_object_set(G_OBJECT(notif), "id", notif_id, NULL);
1367 /* Close the notification, note that some ids could be
1368 already invalid, but we don't care because it does
1370 notify_notification_close(notif, NULL);
1371 g_object_unref(notif);
1373 /* Delete the link, it's like going to the next */
1374 notif_list = g_slist_delete_link (notif_list, notif_list);
1378 modest_conf_set_list (modest_runtime_get_conf (), MODEST_CONF_NOTIFICATION_IDS,
1379 notif_list, MODEST_CONF_VALUE_INT, NULL);
1381 g_slist_free (notif_list);
1383 #endif /* MODEST_HAVE_HILDON_NOTIFY */
1389 modest_platform_get_global_settings_dialog ()
1391 return modest_maemo_global_settings_dialog_new ();
1395 modest_platform_show_help (GtkWindow *parent_window,
1396 const gchar *help_id)
1398 osso_return_t result;
1400 g_return_if_fail (help_id);
1401 g_return_if_fail (osso_context);
1403 result = hildon_help_show (osso_context, help_id, HILDON_HELP_SHOW_DIALOG);
1405 if (result != OSSO_OK) {
1407 error_msg = g_strdup_printf ("FIXME The help topic %s could not be found", help_id);
1408 hildon_banner_show_information (GTK_WIDGET (parent_window),
1416 modest_platform_set_dialog_help (GtkDialog *parent_window,
1417 const gchar *help_id)
1420 g_return_if_fail (help_id);
1421 g_return_if_fail (osso_context);
1422 g_return_if_fail (GTK_IS_DIALOG (parent_window));
1424 result = hildon_help_dialog_help_enable (parent_window, help_id, osso_context);
1427 g_warning ("Help topic %s not found", help_id);
1432 modest_platform_show_search_messages (GtkWindow *parent_window)
1434 osso_return_t result = OSSO_ERROR;
1436 result = osso_rpc_run_with_defaults (osso_context, "osso_global_search", "search_email", NULL, DBUS_TYPE_INVALID);
1438 if (result != OSSO_OK) {
1439 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1444 modest_platform_show_addressbook (GtkWindow *parent_window)
1446 osso_return_t result = OSSO_ERROR;
1448 result = osso_rpc_run_with_defaults (osso_context, "osso_addressbook", "top_application", NULL, DBUS_TYPE_INVALID);
1450 if (result != OSSO_OK) {
1451 g_warning ("%s: osso_rpc_run_with_defaults() failed.\n", __FUNCTION__);
1456 modest_platform_create_folder_view (TnyFolderStoreQuery *query)
1458 GtkWidget *widget = modest_folder_view_new (query);
1460 /* Show one account by default */
1461 modest_folder_view_set_style (MODEST_FOLDER_VIEW (widget),
1462 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
1465 /* Restore settings */
1466 modest_widget_memory_restore (modest_runtime_get_conf(),
1468 MODEST_CONF_FOLDER_VIEW_KEY);
1474 modest_platform_information_banner (GtkWidget *parent,
1475 const gchar *icon_name,
1478 hildon_banner_show_information (parent, icon_name, text);
1482 modest_platform_animation_banner (GtkWidget *parent,
1483 const gchar *animation_name,
1486 GtkWidget *inf_note = NULL;
1488 g_return_val_if_fail (text != NULL, NULL);
1490 inf_note = hildon_banner_show_animation (parent, animation_name, text);
1498 TnyAccount *account;
1501 } CheckAccountIdleData;
1503 #define NUMBER_OF_TRIES 10 /* Try approx every second, ten times. */
1506 on_timeout_check_account_is_online(gpointer user_data)
1508 printf ("DEBUG: %s:\n", __FUNCTION__);
1509 CheckAccountIdleData *data = (CheckAccountIdleData*)user_data;
1512 g_warning ("%s: data is NULL.\n", __FUNCTION__);
1515 if (!(data->account)) {
1516 g_warning ("%s: data->account is NULL.\n", __FUNCTION__);
1519 if (data && data->account) {
1520 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n", __FUNCTION__, tny_account_get_connection_status (data->account));
1523 gboolean stop_trying = FALSE;
1524 if (data && data->account &&
1525 /* We want to wait until TNY_CONNECTION_STATUS_INIT has changed to something else,
1526 * after which the account is likely to be usable, or never likely to be usable soon: */
1527 (tny_account_get_connection_status (data->account) != TNY_CONNECTION_STATUS_INIT) )
1529 data->is_online = TRUE;
1534 /* Give up if we have tried too many times: */
1535 if (data->count_tries >= NUMBER_OF_TRIES)
1540 /* Wait for another timeout: */
1541 ++(data->count_tries);
1546 /* Allow the function that requested this idle callback to continue: */
1548 g_main_loop_quit (data->loop);
1551 g_object_unref (data->account);
1553 return FALSE; /* Don't call this again. */
1555 return TRUE; /* Call this timeout callback again. */
1559 /* Return TRUE immediately if the account is already online,
1560 * otherwise check every second for NUMBER_OF_TRIES seconds and return TRUE as
1561 * soon as the account is online, or FALSE if the account does
1562 * not become online in the NUMBER_OF_TRIES seconds.
1563 * This is useful when the D-Bus method was run immediately after
1564 * the application was started (when using D-Bus activation),
1565 * because the account usually takes a short time to go online.
1566 * The return value is maybe not very useful.
1569 modest_platform_check_and_wait_for_account_is_online(TnyAccount *account)
1571 g_return_val_if_fail (account, FALSE);
1573 printf ("DEBUG: %s: account id=%s\n", __FUNCTION__, tny_account_get_id (account));
1575 if (!tny_device_is_online (modest_runtime_get_device())) {
1576 printf ("DEBUG: %s: device is offline.\n", __FUNCTION__);
1580 /* The local_folders account never seems to leave TNY_CONNECTION_STATUS_INIT,
1581 * so we avoid wait unnecessarily: */
1582 if (!TNY_IS_CAMEL_POP_STORE_ACCOUNT (account) &&
1583 !TNY_IS_CAMEL_IMAP_STORE_ACCOUNT (account) ) {
1587 printf ("DEBUG: %s: tny_account_get_connection_status()==%d\n",
1588 __FUNCTION__, tny_account_get_connection_status (account));
1590 /* The POP & IMAP store accounts seem to be TNY_CONNECTION_STATUS_DISCONNECTED,
1591 * and that seems to be an OK time to use them. Maybe it's just TNY_CONNECTION_STATUS_INIT that
1592 * we want to avoid. */
1593 if (tny_account_get_connection_status (account) != TNY_CONNECTION_STATUS_INIT)
1596 /* This blocks on the result: */
1597 CheckAccountIdleData *data = g_slice_new0 (CheckAccountIdleData);
1598 data->is_online = FALSE;
1599 data->account = account;
1600 g_object_ref (data->account);
1601 data->count_tries = 0;
1603 GMainContext *context = NULL; /* g_main_context_new (); */
1604 data->loop = g_main_loop_new (context, FALSE /* not running */);
1606 g_timeout_add (1000, on_timeout_check_account_is_online, data);
1608 /* This main loop will run until the idle handler has stopped it: */
1609 g_main_loop_run (data->loop);
1611 g_main_loop_unref (data->loop);
1612 /* g_main_context_unref (context); */
1614 g_slice_free (CheckAccountIdleData, data);
1616 return data->is_online;
1622 on_cert_dialog_response (GtkDialog *dialog, gint response_id, const gchar* cert)
1624 /* GTK_RESPONSE_HELP means we need to show the certificate */
1625 if (response_id == GTK_RESPONSE_HELP) {
1629 /* Do not close the dialog */
1630 g_signal_stop_emission_by_name (dialog, "response");
1632 msg = g_strdup_printf (_("mcen_ni_view_unknown_certificate"), cert);
1633 note = hildon_note_new_information (GTK_WINDOW(dialog), msg);
1634 gtk_dialog_run (GTK_DIALOG(note));
1635 gtk_widget_destroy (note);
1641 modest_platform_run_certificate_confirmation_dialog (const gchar* server_name,
1642 const gchar *certificate)
1646 ModestWindow *main_win;
1648 if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
1649 g_warning ("%s: don't show dialogs if there's no main window; assuming 'Cancel'",
1654 /* don't create it */
1655 main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(), FALSE);
1656 g_return_val_if_fail (main_win, FALSE); /* should not happen */
1659 gchar *question = g_strdup_printf (_("mcen_nc_unknown_certificate"),
1662 note = hildon_note_new_confirmation_add_buttons (
1663 GTK_WINDOW(main_win),
1665 _("mcen_bd_dialog_ok"), GTK_RESPONSE_OK,
1666 _("mcen_bd_view"), GTK_RESPONSE_HELP, /* abusing this... */
1667 _("mcen_bd_dialog_cancel"), GTK_RESPONSE_CANCEL,
1670 g_signal_connect (G_OBJECT(note), "response",
1671 G_CALLBACK(on_cert_dialog_response),
1672 (gpointer) certificate);
1674 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1676 response = gtk_dialog_run(GTK_DIALOG(note));
1678 on_destroy_dialog (GTK_DIALOG(note));
1681 return response == GTK_RESPONSE_OK;
1687 modest_platform_run_alert_dialog (const gchar* prompt,
1688 gboolean is_question)
1690 ModestWindow *main_win;
1692 if (!modest_window_mgr_main_window_exists (modest_runtime_get_window_mgr())) {
1693 g_warning ("%s:\n'%s'\ndon't show dialogs if there's no main window;"
1694 " assuming 'Cancel' for questions, 'Ok' otherwise", prompt, __FUNCTION__);
1695 return is_question ? FALSE : TRUE;
1698 main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (), FALSE);
1699 g_return_val_if_fail (main_win, FALSE); /* should not happen */
1701 gboolean retval = TRUE;
1703 /* The Tinymail documentation says that we should show Yes and No buttons,
1704 * when it is a question.
1705 * Obviously, we need tinymail to use more specific error codes instead,
1706 * so we know what buttons to show. */
1707 GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (main_win),
1709 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
1710 GTK_WINDOW (dialog));
1712 const int response = gtk_dialog_run (GTK_DIALOG (dialog));
1713 retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK);
1715 on_destroy_dialog (GTK_DIALOG(dialog));
1717 /* Just show the error text and use the default response: */
1718 modest_platform_run_information_dialog (GTK_WINDOW (main_win),